generate_configs.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #!/usr/bin/env python3
  2. #
  3. # Copyright 2019 The Chromium Authors. All rights reserved.
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. """Creates config files for building dav1d."""
  7. from __future__ import print_function
  8. import os
  9. import re
  10. import shlex
  11. import shutil
  12. import subprocess
  13. import sys
  14. import tempfile
  15. BASE_DIR = os.path.abspath(os.path.dirname(__file__))
  16. CHROMIUM_ROOT_DIR = os.path.abspath(os.path.join(BASE_DIR, '..', '..'))
  17. sys.path.append(os.path.join(CHROMIUM_ROOT_DIR, 'build'))
  18. import gn_helpers
  19. MESON = ['meson.py']
  20. DEFAULT_BUILD_ARGS = [
  21. '-Denable_tools=false', '-Denable_tests=false', '-Ddefault_library=static',
  22. '--buildtype', 'release'
  23. ]
  24. WINDOWS_BUILD_ARGS = ['-Dc_winlibs=']
  25. def PrintAndCheckCall(argv, *args, **kwargs):
  26. print('\n-------------------------------------------------\nRunning %s' %
  27. ' '.join(argv))
  28. c = subprocess.check_call(argv, *args, **kwargs)
  29. def RewriteFile(path, search_replace):
  30. with open(path) as f:
  31. contents = f.read()
  32. with open(path, 'w') as f:
  33. for search, replace in search_replace:
  34. contents = re.sub(search, replace, contents)
  35. # Cleanup trailing newlines.
  36. f.write(contents.strip() + '\n')
  37. def SetupWindowsCrossCompileToolchain(target_arch):
  38. # First retrieve various MSVC and Windows SDK paths.
  39. output = subprocess.check_output([
  40. 'python3',
  41. os.path.join(CHROMIUM_ROOT_DIR, 'build', 'vs_toolchain.py'),
  42. 'get_toolchain_dir'
  43. ],
  44. universal_newlines=True)
  45. # Turn this into a dictionary.
  46. win_dirs = gn_helpers.FromGNArgs(output)
  47. # Use those paths with a second script which will tell us the proper include
  48. # and lib paths to specify for cflags and ldflags respectively.
  49. output = subprocess.check_output([
  50. 'python3',
  51. os.path.join(CHROMIUM_ROOT_DIR, 'build', 'toolchain', 'win',
  52. 'setup_toolchain.py'), win_dirs['vs_path'],
  53. win_dirs['sdk_path'], win_dirs['runtime_dirs'], 'win', target_arch,
  54. 'none'
  55. ],
  56. universal_newlines=True)
  57. flags = gn_helpers.FromGNArgs(output)
  58. cwd = os.getcwd()
  59. target_env = os.environ
  60. # Each path is of the form:
  61. # "/I../depot_tools/win_toolchain/vs_files/20d5f2553f/Windows Kits/10/Include/10.0.19041.0/winrt"
  62. #
  63. # Since there's a space in the include path, inputs are quoted in |flags|, we
  64. # can helpfully use shlex to split on spaces while preserving quoted strings.
  65. include_paths = []
  66. for include_path in shlex.split(flags['include_flags_I']):
  67. # Apparently setup_toolchain prefers relative include paths, which
  68. # may work for chrome, but it does not work for dav1d, so let's make
  69. # them asbolute again.
  70. include_path = os.path.abspath(os.path.join(cwd, include_path[2:]))
  71. include_paths.append(include_path)
  72. SYSROOT_PREFIX = '/winsysroot:'
  73. for k in flags:
  74. if SYSROOT_PREFIX in flags[k]:
  75. target_env['WINSYSROOT'] = os.path.abspath(
  76. os.path.join(cwd, flags[k][len(SYSROOT_PREFIX):]))
  77. break
  78. target_env = os.environ
  79. target_env['INCLUDE'] = ';'.join(include_paths)
  80. return target_env
  81. def CopyConfigs(src_dir, dest_dir):
  82. if not os.path.exists(dest_dir):
  83. os.makedirs(dest_dir)
  84. shutil.copy(os.path.join(src_dir, 'config.h'), dest_dir)
  85. # The .asm file will not be present for all configurations.
  86. asm_file = os.path.join(src_dir, 'config.asm')
  87. if os.path.exists(asm_file):
  88. shutil.copy(asm_file, dest_dir)
  89. def GenerateConfig(config_dir, env, special_args=[]):
  90. temp_dir = tempfile.mkdtemp()
  91. PrintAndCheckCall(MESON + DEFAULT_BUILD_ARGS + special_args + [temp_dir],
  92. cwd='libdav1d',
  93. env=env)
  94. RewriteFile(
  95. os.path.join(temp_dir, 'config.h'),
  96. [
  97. # We don't want non-visible log strings polluting the official binary.
  98. (r'(#define CONFIG_LOG .*)',
  99. r'// \1 -- Logging is controlled by Chromium'),
  100. # The Chromium build system already defines this.
  101. (r'(#define _WIN32_WINNT .*)',
  102. r'// \1 -- Windows version is controlled by Chromium'),
  103. # Clang LTO doesn't respect stack alignment, so we must use the
  104. # platform's default stack alignment; https://crbug.com/928743.
  105. (r'(#define STACK_ALIGNMENT \d{1,2})',
  106. r'// \1 -- Stack alignment is controlled by Chromium'),
  107. # Android doesn't have pthread_getaffinity_np.
  108. (r'(#define HAVE_PTHREAD_GETAFFINITY_NP \d{1,2})',
  109. r'// \1 -- Controlled by Chomium'),
  110. ])
  111. config_asm_path = os.path.join(temp_dir, 'config.asm')
  112. if (os.path.exists(config_asm_path)):
  113. RewriteFile(config_asm_path,
  114. [(r'(%define STACK_ALIGNMENT \d{1,2})',
  115. r'; \1 -- Stack alignment is controlled by Chromium')])
  116. CopyConfigs(temp_dir, config_dir)
  117. shutil.rmtree(temp_dir)
  118. def GenerateWindowsArm64Config(src_dir):
  119. win_arm64_dir = 'config/win/arm64'
  120. if not os.path.exists(win_arm64_dir):
  121. os.makedirs(win_arm64_dir)
  122. shutil.copy(os.path.join(src_dir, 'config.h'), win_arm64_dir)
  123. # Flip flags such that it looks like an arm64 configuration.
  124. RewriteFile(os.path.join(win_arm64_dir, 'config.h'),
  125. [(r'#define ARCH_X86 1', r'#define ARCH_X86 0'),
  126. (r'#define ARCH_X86_64 1', r'#define ARCH_X86_64 0'),
  127. (r'#define ARCH_AARCH64 0', r'#define ARCH_AARCH64 1')])
  128. def CopyVersions(src_dir, dest_dir):
  129. if not os.path.exists(dest_dir):
  130. os.makedirs(dest_dir)
  131. shutil.copy(os.path.join(src_dir, 'include', 'dav1d', 'version.h'),
  132. dest_dir)
  133. shutil.copy(os.path.join(src_dir, 'include', 'vcs_version.h'), dest_dir)
  134. def GenerateVersion(version_dir, env):
  135. temp_dir = tempfile.mkdtemp()
  136. PrintAndCheckCall(MESON + DEFAULT_BUILD_ARGS + [temp_dir],
  137. cwd='libdav1d',
  138. env=env)
  139. PrintAndCheckCall(['ninja', '-C', temp_dir, 'include/vcs_version.h'],
  140. cwd='libdav1d',
  141. env=env)
  142. CopyVersions(temp_dir, version_dir)
  143. shutil.rmtree(temp_dir)
  144. def main():
  145. linux_env = os.environ
  146. linux_env['CC'] = 'clang'
  147. GenerateConfig('config/linux/x64', linux_env)
  148. GenerateConfig('config/linux-noasm/x64', linux_env, ['-Denable_asm=false'])
  149. GenerateConfig('config/linux-noasm/riscv64', linux_env, ['-Denable_asm=false'])
  150. GenerateConfig('config/linux/x86', linux_env,
  151. ['--cross-file', '../crossfiles/linux32.crossfile'])
  152. GenerateConfig('config/linux/arm', linux_env,
  153. ['--cross-file', '../crossfiles/arm.crossfile'])
  154. GenerateConfig('config/linux/arm64', linux_env,
  155. ['--cross-file', '../crossfiles/arm64.crossfile'])
  156. GenerateConfig('config/linux/ppc64', linux_env)
  157. win_x86_env = SetupWindowsCrossCompileToolchain('x86')
  158. GenerateConfig('config/win/x86', win_x86_env,
  159. ['--cross-file', '../crossfiles/win32.crossfile'] + [
  160. '-Dc_args=-m32 -fuse-ld=lld /winsysroot ' +
  161. win_x86_env['WINSYSROOT']
  162. ] + WINDOWS_BUILD_ARGS)
  163. win_x64_dir = 'config/win/x64'
  164. win_x64_env = SetupWindowsCrossCompileToolchain('x64')
  165. GenerateConfig(
  166. win_x64_dir, win_x64_env,
  167. ['--cross-file', '../crossfiles/win64.crossfile'] +
  168. ['-Dc_args=-fuse-ld=lld /winsysroot ' + win_x64_env['WINSYSROOT']] +
  169. WINDOWS_BUILD_ARGS)
  170. # Sadly meson doesn't support arm64 + clang-cl, so we need to create the
  171. # Windows arm64 config from the Windows x64 config.
  172. GenerateWindowsArm64Config(win_x64_dir)
  173. GenerateVersion('version', linux_env)
  174. if __name__ == '__main__':
  175. main()