blob: 28e5f982d6f7ca2b2dabe42b4c0f83f65033ffdb [file] [log] [blame]
#!/usr/bin/python
#
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Creates config files for building dav1d."""
from __future__ import print_function
import os
import re
import shutil
import subprocess
import sys
import tempfile
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
CHROMIUM_ROOT_DIR = os.path.abspath(os.path.join(BASE_DIR, '..', '..'))
sys.path.append(os.path.join(CHROMIUM_ROOT_DIR, 'build'))
import gn_helpers
MESON = ['meson.py']
DEFAULT_BUILD_ARGS = [
'-Dbuild_tools=false', '-Dbuild_tests=false', '--buildtype', 'release'
]
WINDOWS_BUILD_ARGS = ['-Dc_winlibs=']
def PrintAndCheckCall(argv, *args, **kwargs):
print('\n-------------------------------------------------\nRunning %s' %
' '.join(argv))
c = subprocess.check_call(argv, *args, **kwargs)
def RewriteFile(path, search_replace):
with open(path) as f:
contents = f.read()
with open(path, 'w') as f:
for search, replace in search_replace:
contents = re.sub(search, replace, contents)
# Cleanup trailing newlines.
f.write(contents.strip() + '\n')
def SetupWindowsCrossCompileToolchain(target_arch):
# First retrieve various MSVC and Windows SDK paths.
output = subprocess.check_output([
os.path.join(CHROMIUM_ROOT_DIR, 'build', 'vs_toolchain.py'),
'get_toolchain_dir'
])
# Turn this into a dictionary.
win_dirs = gn_helpers.FromGNArgs(output)
# Use those paths with a second script which will tell us the proper include
# and lib paths to specify for cflags and ldflags respectively.
output = subprocess.check_output([
'python',
os.path.join(CHROMIUM_ROOT_DIR, 'build', 'toolchain', 'win',
'setup_toolchain.py'), win_dirs['vs_path'],
win_dirs['sdk_path'], win_dirs['runtime_dirs'], 'win', target_arch, 'none'
])
flags = gn_helpers.FromGNArgs(output)
cwd = os.getcwd()
target_env = os.environ
include_paths = []
for cflag in flags['include_flags_imsvc'].split(' '):
# Apparently setup_toolchain prefers relative include paths, which
# may work for chrome, but it does not work for ffmpeg, so let's make
# them asbolute again.
include_path = cflag.strip('"')
if include_path.startswith('-imsvc'):
include_path = os.path.abspath(os.path.join(cwd, include_path[6:]))
include_paths.append(include_path)
# TODO(dalecurtis): Why isn't the ucrt path printed?
flags['vc_lib_ucrt_path'] = flags['vc_lib_um_path'].replace('/um/', '/ucrt/')
# Unlike the cflags, the lib include paths are each in a separate variable.
lib_paths = []
for k in flags:
# libpath_flags is like cflags. Since it is also redundant, skip it.
if 'lib' in k and k != 'libpath_flags':
lib_paths.append(flags[k])
target_env = os.environ
target_env['INCLUDE'] = ';'.join(include_paths)
target_env['LIB'] = ';'.join(lib_paths)
return target_env
def CopyConfigsAndCleanup(config_dir, dest_dir):
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
shutil.copy(os.path.join(config_dir, 'config.h'), dest_dir)
# The .asm file will not be present for all configurations.
asm_file = os.path.join(config_dir, 'config.asm')
if os.path.exists(asm_file):
shutil.copy(asm_file, dest_dir)
shutil.rmtree(config_dir)
def GenerateConfig(config_dir, env, special_args=[]):
temp_dir = tempfile.mkdtemp()
PrintAndCheckCall(
MESON + DEFAULT_BUILD_ARGS + special_args + [temp_dir],
cwd='libdav1d',
env=env)
# We don't want non-visible log strings polluting the official binary.
RewriteFile(
os.path.join(temp_dir, 'config.h'),
[(r'(#define CONFIG_LOG .*)',
r'// \1 -- Logging is controlled by Chromium')])
# Clang LTO doesn't respect stack alignment, so we must use the platform's
# default stack alignment in that case; https://crbug.com/928743.
RewriteFile(
os.path.join(temp_dir, 'config.h'),
[(r'(#define STACK_ALIGNMENT \d{1,2})',
r'// \1 -- Stack alignment is controlled by Chromium')])
if (os.path.exists(os.path.join(config_dir, 'config.asm'))):
RewriteFile(
os.path.join(temp_dir, 'config.asm'),
[(r'(%define STACK_ALIGNMENT \d{1,2})',
r'; \1 -- Stack alignment is controlled by Chromium')])
CopyConfigsAndCleanup(temp_dir, config_dir)
def GenerateWindowsArm64Config(src_dir):
win_arm64_dir = 'config/win/arm64'
if not os.path.exists(win_arm64_dir):
os.makedirs(win_arm64_dir)
shutil.copy(os.path.join(src_dir, 'config.h'), win_arm64_dir)
# Flip flags such that it looks like an arm64 configuration.
RewriteFile(
os.path.join(win_arm64_dir, 'config.h'),
[(r'#define ARCH_X86 1', r'#define ARCH_X86 0'),
(r'#define ARCH_X86_64 1', r'#define ARCH_X86_64 0'),
(r'#define ARCH_AARCH64 0', r'#define ARCH_AARCH64 1')])
def main():
linux_env = os.environ
linux_env['CC'] = 'clang'
GenerateConfig('config/linux/x64', linux_env)
GenerateConfig('config/linux-noasm/x64', linux_env, ['-Dbuild_asm=false'])
GenerateConfig('config/linux/x86', linux_env,
['--cross-file', '../crossfiles/linux32.crossfile'])
GenerateConfig('config/linux/arm', linux_env,
['--cross-file', '../crossfiles/arm.crossfile'])
GenerateConfig('config/linux/arm64', linux_env,
['--cross-file', '../crossfiles/arm64.crossfile'])
win_x86_env = SetupWindowsCrossCompileToolchain('x86')
GenerateConfig('config/win/x86', win_x86_env,
['--cross-file', '../crossfiles/win32.crossfile'] +
WINDOWS_BUILD_ARGS)
win_x64_dir = 'config/win/x64'
win_x64_env = SetupWindowsCrossCompileToolchain('x64')
GenerateConfig(win_x64_dir, win_x64_env,
['--cross-file', '../crossfiles/win64.crossfile'] +
WINDOWS_BUILD_ARGS)
# Sadly meson doesn't support arm64 + clang-cl, so we need to create the
# Windows arm64 config from the Windows x64 config.
GenerateWindowsArm64Config(win_x64_dir)
if __name__ == '__main__':
main()