from __future__ import print_function
import atexit
import collections
import functools
import glob
import optparse
import os
import platform
import re
import shlex
import shutil
import signal
import subprocess
import sys
import tempfile
from robo_lib import config
ROBO_CONFIGURATION = config.RoboConfiguration()
FFMPEG_DIR = ROBO_CONFIGURATION.ffmpeg_src()
FFMPEG_HOME = ROBO_CONFIGURATION.ffmpeg_home()
CHROMIUM_ROOT_DIR = ROBO_CONFIGURATION.chrome_src()
NDK_ROOT_DIR = os.path.abspath(
os.path.join(CHROMIUM_ROOT_DIR, 'third_party', 'android_toolchain', 'ndk'))
SUCCESS_TOKEN = 'THIS_BUILD_WORKED'
sys.path.append(os.path.join(CHROMIUM_ROOT_DIR, 'build'))
import gn_helpers
BRANDINGS = [
'Chrome',
'Chromium',
]
ARCH_MAP = {
'android': ['ia32', 'x64', 'arm-neon', 'arm64'],
'linux': ['ia32', 'x64', 'noasm-x64', 'arm', 'arm-neon', 'arm64', 'riscv64'],
'mac': ['x64', 'arm64'],
'win': ['ia32', 'x64', 'arm64'],
}
USAGE_BEGIN = """Usage: %prog TARGET_OS TARGET_ARCH [options] -- [configure_args]"""
USAGE_END = """
Valid combinations are android [%(android)s]
linux [%(linux)s]
mac [%(mac)s]
win [%(win)s]
If no target architecture is specified all will be built. Usually you don't want
to run this script manually and should instead be using robosushi.py.
Platform specific build notes:
android:
Script can be run on a normal x64 Ubuntu box with an Android-ready Chromium
checkout: https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md
linux ia32/x64:
Script can run on a normal Ubuntu box.
linux arm/arm-neon/arm64/mipsel/mips64el/riscv64:
Script can run on a normal Ubuntu with ARM/ARM64 or MIPS32/MIPS64 or RISCV64
ready Chromium checkout:
build/linux/sysroot_scripts/install-sysroot.py --arch=arm
build/linux/sysroot_scripts/install-sysroot.py --arch=arm64
build/linux/sysroot_scripts/install-sysroot.py --arch=mips
build/linux/sysroot_scripts/install-sysroot.py --arch=mips64el
build/linux/sysroot_scripts/install-sysroot.py --arch=riscv64
mac:
Script must be run on Linux or macOS. Additionally, ensure the Chromium
(not Apple) version of clang is in the path; usually found under
src/third_party/llvm-build/Release+Asserts/bin
The arm64 version has to be built with an SDK that can build mac/arm64
binaries -- currently Xcode 12 beta and its included 11.0 SDK. You must
pass --enable-cross-compile to be able to build ffmpeg for mac/arm64 on an
Intel Mac. On a Mac, run like so:
PATH=$PWD/../../third_party/llvm-build/Release+Asserts/bin:$PATH \
SDKROOT=/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
chromium/scripts/build_ffmpeg.py mac arm64 -- --enable-cross-compile
On Linux, the normal robosushi flow will work for arm64.
win:
Script may be run unders Linux or Windows; if cross-compiling you will need
to follow the Chromium instruction for Cross-compiling Chrome/win:
https://chromium.googlesource.com/chromium/src/+/master/docs/win_cross.md
Once you have a working Chromium build that can cross-compile, you'll also
need to run $chrome_dir/tools/clang/scripts/update.py --package=objdump to
pick up the llvm-ar and llvm-nm tools. You can then build as normal.
If not cross-compiling, script must be run on Windows with VS2015 or higher
under Cygwin (or MinGW, but as of 1.0.11, it has serious performance issues
with make which makes building take hours).
Additionally, ensure you have the correct toolchain environment for builds.
The x86 toolchain environment is required for ia32 builds and the x64 one
for x64 builds. This can be verified by running "cl.exe" and checking if
the version string ends with "for x64" or "for x86."
Building on Windows also requires some additional Cygwin packages plus a
wrapper script for converting Cygwin paths to DOS paths.
- Add these packages at install time: diffutils, nasm, make, python.
- Copy chromium/scripts/cygwin-wrapper to /usr/local/bin
Resulting binaries will be placed in:
build.TARGET_ARCH.TARGET_OS/Chrome/
build.TARGET_ARCH.TARGET_OS/Chromium/
"""
def PrintAndCheckCall(argv, *args, **kwargs):
print('Running %s' % '\n '.join(argv))
subprocess.check_call(argv, *args, **kwargs)
def GetDsoName(target_os, dso_name, dso_version):
if target_os in ('linux', 'linux-noasm', 'android'):
return 'lib%s.so.%s' % (dso_name, dso_version)
elif target_os == 'mac':
return 'lib%s.%s.dylib' % (dso_name, dso_version)
elif target_os == 'win':
return '%s-%s.dll' % (dso_name, dso_version)
else:
raise ValueError('Unexpected target_os %s' % target_os)
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)
f.write(contents)
class AndroidApiLevels:
__instance = None
def Setup(self):
print('Creating a temporary GN config to retrieve Android API levels:')
tmp_dir = tempfile.mkdtemp(
prefix='android_build_ffmpeg_for_api_level_config')
print('Created temporary directory ' + tmp_dir)
with open(os.path.join(tmp_dir, 'args.gn'), 'w') as args_gn_file:
args_gn_file.write('target_os = "android"\n')
print('Created ' + os.path.realpath(args_gn_file.name))
PrintAndCheckCall(['gn', 'gen', tmp_dir], cwd=CHROMIUM_ROOT_DIR)
print('Retrieving config vars')
config_output = subprocess.check_output(
['gn', 'args', tmp_dir, '--short', '--list'],
cwd=CHROMIUM_ROOT_DIR).decode('utf-8')
print('removing temp dir ' + tmp_dir)
shutil.rmtree(tmp_dir, ignore_errors=False)
api_match = re.search(r'android_ndk_api_level\s*=\s*(\d{2})',
config_output)
if not api_match:
raise Exception('Failed to find the android api levels')
self.api32 = api_match.group(1)
self.api64 = api_match.group(1)
def ApiLevels(self):
return (self.api32, self.api64)
@classmethod
def Get(cls):
if cls.__instance is None:
cls.__instance = AndroidApiLevels()
cls.__instance.Setup()
return cls.__instance.ApiLevels()
def SetupAndroidToolchain(target_arch):
api_level, api64_level = AndroidApiLevels.Get()
print('Determined Android API levels: 32bit=' + api_level + ', 64bit=' +
api64_level)
toolchain_level = api_level
toolchain_bin_prefix = target_arch
if target_arch == 'arm-neon' or target_arch == 'arm':
toolchain_bin_prefix = 'arm-linux-androideabi'
elif target_arch == 'arm64':
toolchain_level = api64_level
toolchain_bin_prefix = 'aarch64-linux-android'
elif target_arch == 'ia32':
toolchain_bin_prefix = 'i686-linux-android'
elif target_arch == 'x64':
toolchain_level = api64_level
toolchain_bin_prefix = 'x86_64-linux-android'
elif target_arch == 'mipsel':
toolchain_bin_prefix = 'mipsel-linux-android'
elif target_arch == 'mips64el':
toolchain_level = api64_level
toolchain_bin_prefix = 'mips64el-linux-android'
clang_toolchain_dir = NDK_ROOT_DIR + '/toolchains/llvm/prebuilt/linux-x86_64/'
fakedir = '/tmp/fakelinkerscripts'
os.system('mkdir -p {fakedir} && touch {fakedir}/libunwind.a'.format(
fakedir=fakedir))
return [
'--enable-pic',
'--cc=clang',
'--cxx=clang++',
'--ld=clang',
'--enable-cross-compile',
'--sysroot=' + clang_toolchain_dir + 'sysroot',
'--extra-cflags=-I' + clang_toolchain_dir + 'sysroot/usr/include',
'--extra-cflags=-I' + clang_toolchain_dir + 'sysroot/usr/include/' +
toolchain_bin_prefix,
'--extra-cflags=--target=' + toolchain_bin_prefix + toolchain_level,
'--extra-ldflags=--target=' + toolchain_bin_prefix + toolchain_level,
'--extra-ldflags=-L{}'.format(fakedir),
'--extra-ldflags=-L' + clang_toolchain_dir + toolchain_bin_prefix,
'--extra-ldflags=--gcc-toolchain=' + clang_toolchain_dir,
'--target-os=android',
]
def SetupWindowsCrossCompileToolchain(target_arch):
output = subprocess.check_output([
os.path.join(CHROMIUM_ROOT_DIR, 'build', 'vs_toolchain.py'),
'get_toolchain_dir'
]).decode('utf-8')
new_args = [
'--enable-cross-compile',
'--cc=clang-cl',
'--ld=lld-link',
'--nm=llvm-nm',
'--ar=llvm-ar',
'--extra-cflags=-O2',
]
if target_arch == 'ia32':
new_args += ['--extra-cflags=-m32']
if target_arch == 'ia32':
target_arch = 'x86'
if target_arch == 'arm64':
new_args += [
'--arch=aarch64',
'--as=clang-cl',
'--extra-cflags=--target=arm64-windows'
]
win_dirs = gn_helpers.FromGNArgs(output)
output = subprocess.check_output([
'python3',
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'
]).decode('utf-8')
flags = gn_helpers.FromGNArgs(output)
new_args += [
'--extra-cflags=/winsysroot' + win_dirs['vs_path'],
'--extra-ldflags=/winsysroot:' + win_dirs['vs_path'],
]
def do_remove_temp_link(temp_name):
assert os.path.exists(temp_name)
assert os.path.islink(temp_name)
print('Removing temporary link ' + temp_name)
os.remove(temp_name)
def do_make_temp_link(real_target):
temp_file = tempfile.NamedTemporaryFile(prefix='windows_build_ffmpeg')
temp_name = temp_file.name
temp_file.close()
os.symlink(real_target, temp_name)
assert os.path.exists(temp_name)
assert os.path.islink(temp_name)
atexit.register(do_remove_temp_link, temp_name)
return temp_name
return new_args
def SetupMacCrossCompileToolchain(target_arch):
mac_min_ver = '12.0'
developer_dir = os.path.join(CHROMIUM_ROOT_DIR, 'build', 'mac_files',
'xcode_binaries', 'Contents', 'Developer')
sdk_dir = os.path.join(developer_dir, 'Platforms', 'MacOSX.platform',
'Developer', 'SDKs', 'MacOSX.sdk')
if target_arch == 'x64':
target_triple = 'x86_64-apple-macosx'
elif target_arch == 'arm64':
target_triple = 'arm64-apple-macosx'
else:
raise Exception("unknown arch " + target_arch)
if not os.path.exists(sdk_dir):
print(sdk_dir)
raise Exception("Can't find the mac sdk. Please see crbug.com/841826")
frameworks_dir = os.path.join(sdk_dir, "System", "Library", "Frameworks")
libs_dir = os.path.join(sdk_dir, "usr", "lib")
new_args = [
'--enable-cross-compile',
'--cc=clang',
'--ld=ld64.lld',
'--nm=llvm-nm',
'--ar=llvm-ar',
'--target-os=darwin',
'--extra-cflags=--target=' + target_triple,
'--extra-cflags=-F' + frameworks_dir,
'--extra-cflags=-mmacosx-version-min=' + mac_min_ver
]
clang_dir = glob.glob(
os.path.join(CHROMIUM_ROOT_DIR, 'third_party', 'llvm-build',
'Release+Asserts', 'lib', 'clang', '*', 'include'))[0]
new_args += [
'--extra-cflags=-fblocks',
'--extra-cflags=-nostdinc',
'--extra-cflags=-isystem%s/usr/include' % sdk_dir,
'--extra-cflags=-isystem' + clang_dir,
'--extra-ldflags=-syslibroot',
'--extra-ldflags=' + sdk_dir,
'--extra-ldflags=' + '-L' + libs_dir,
'--extra-ldflags=-lSystem',
'--extra-ldflags=-macosx_version_min',
'--extra-ldflags=' + mac_min_ver,
'--extra-ldflags=-sdk_version',
'--extra-ldflags=' + mac_min_ver,
'--extra-ldflags=-platform_version',
'--extra-ldflags=macos',
'--extra-ldflags=' + mac_min_ver,
'--extra-ldflags=' + mac_min_ver
]
return new_args
def BuildFFmpeg(target_os, target_arch, host_os, host_arch, parallel_jobs,
config_only, config, configure_flags, options):
config_dir = ROBO_CONFIGURATION.target_config_directory(
target_arch, target_os, config)
token_file = os.path.join(config_dir, SUCCESS_TOKEN)
if os.path.exists(token_file) and options.fast:
print('Success token exists, skipping build of %s' % config_dir)
return
shutil.rmtree(config_dir, ignore_errors=True)
os.makedirs(config_dir)
PrintAndCheckCall([os.path.join(FFMPEG_DIR, 'configure')] +
configure_flags,
cwd=config_dir)
pre_make_rewrites = [
(r'(#define HAVE_VALGRIND_VALGRIND_H [01])',
r'#define HAVE_VALGRIND_VALGRIND_H 0 /* \1 -- forced to 0. See '
r'https://crbug.com/590440 */')
]
pre_make_asm_rewrites = [
(r'(%define HAVE_VALGRIND_VALGRIND_H [01])',
r'%define HAVE_VALGRIND_VALGRIND_H 0 ; \1 -- forced to 0. See '
r'https://crbug.com/590440')
]
if target_os == 'android':
pre_make_rewrites += [
(r'(#define HAVE_POSIX_MEMALIGN [01])',
r'#define HAVE_POSIX_MEMALIGN 0 /* \1 -- forced to 0. See '
r'https://crbug.com/604451 */')
]
if target_os in ['linux', 'linux-noasm']:
pre_make_rewrites += [
(r'(#define HAVE_SYSCTL [01])',
r'#define HAVE_SYSCTL 0 /* \1 -- forced to 0 for Fuchsia */'),
(r'(#define HAVE_PRCTL [01])',
r'#define HAVE_PRCTL 0 /* \1 -- forced to 0 for Fuchsia */')
]
if target_os == 'win':
pre_make_rewrites += [(r'(#define HAVE_BCRYPT [01])',
r'#define HAVE_BCRYPT 0')]
if target_arch == 'ia32':
pre_make_rewrites += [
(r'(#define HAVE_EBP_AVAILABLE [01])',
r'/* \1 -- ebp selection is done by the chrome build */')
]
RewriteFile(os.path.join(config_dir, 'config.h'), pre_make_rewrites)
asm_path = os.path.join(config_dir, 'config.asm')
if os.path.exists(asm_path):
RewriteFile(asm_path, pre_make_asm_rewrites)
if target_os == 'win':
RewriteFile(os.path.join(config_dir, 'ffbuild/config.mak'),
[(r'(LDFLAGS=.*)', r'\1 -FORCE:UNRESOLVED')])
if target_os == 'mac' and host_os == 'linux':
RewriteFile(os.path.join(config_dir, 'ffbuild/config.mak'),
[(r'LD=ld64.lld', r'LD=' +
ROBO_CONFIGURATION.get_script_path('fake_linker.py'))])
if target_os == 'win' and target_arch == 'arm64' and host_os == 'linux':
RewriteFile(os.path.join(config_dir, 'ffbuild/config.mak'),
[(r'LD=lld-link', r'LD=' +
ROBO_CONFIGURATION.get_script_path('fake_linker.py'))])
if target_os in (host_os, host_os + '-noasm', 'android', 'win',
'mac') and not config_only:
PrintAndCheckCall(['make', '-j%d' % parallel_jobs], cwd=config_dir)
elif config_only:
print('Skipping build step as requested.')
else:
print(
'Skipping compile as host configuration differs from target.\n'
'Please compare the generated config.h with the previous version.\n'
'You may also patch the script to properly cross-compile.\n'
'Host OS : %s\n'
'Target OS : %s\n'
'Host arch : %s\n'
'Target arch : %s\n' %
(host_os, target_os, host_arch, target_arch))
post_make_rewrites = [
(r'(#define FFMPEG_CONFIGURATION .*)',
r'/* \1 -- elide long configuration string from binary */')
]
if target_arch in ('arm', 'arm-neon', 'arm64'):
post_make_rewrites += [
(r'(#define HAVE_VFP_ARGS [01])',
r'/* \1 -- softfp/hardfp selection is done by the chrome build */'
),
(r'(#define HAVE_VFP_INLINE [01])', r'#define HAVE_VFP_INLINE 1'),
(r'(#define HAVE_VFP_EXTERNAL [01])',
r'#define HAVE_VFP_EXTERNAL 1'),
(r'(#define HAVE_VFP [01])', r'#define HAVE_VFP 1')
]
RewriteFile(os.path.join(config_dir, 'config.h'), post_make_rewrites)
with open(token_file, 'w'):
pass
def main(argv):
clean_arch_map = {k: '|'.join(v) for k, v in ARCH_MAP.items()}
formatted_usage_end = USAGE_END % clean_arch_map
parser = optparse.OptionParser(usage=USAGE_BEGIN + formatted_usage_end)
parser.add_option(
'--branding',
action='append',
dest='brandings',
choices=BRANDINGS,
help='Branding to build; determines e.g. supported codecs')
parser.add_option('--config-only',
action='store_true',
help='Skip the build step. Useful when a given platform '
'is not necessary for generate_gn.py')
parser.add_option(
'--fast',
action='store_true',
help='Skip building (successfully) if the success token file exists')
options, args = parser.parse_args(argv)
if len(args) < 1:
parser.print_help()
return 1
target_os = args[0]
target_arch = ''
if len(args) >= 2:
target_arch = args[1]
configure_args = args[2:]
if target_os not in ('android', 'linux', 'linux-noasm', 'mac', 'win',
'all'):
parser.print_help()
return 1
host_os = ROBO_CONFIGURATION.host_operating_system()
host_arch = ROBO_CONFIGURATION.host_architecture()
parallel_jobs = 8
if target_os.split('-', 1)[0] != host_os and (host_os != 'linux'
or host_arch != 'x64'):
print('Cross compilation can only be done from a linux x64 host.')
return 1
for os in ARCH_MAP.keys():
if os != target_os and target_os != 'all':
continue
for arch in ARCH_MAP[os]:
if target_arch and arch != target_arch:
continue
print('System information:\n'
'Host OS : %s\n'
'Target OS : %s\n'
'Host arch : %s\n'
'Target arch : %s\n' % (host_os, os, host_arch, arch))
ConfigureAndBuild(arch,
os,
host_os,
host_arch,
parallel_jobs,
configure_args,
options=options)
def ConfigureAndBuild(target_arch, target_os, host_os, host_arch,
parallel_jobs, configure_args, options):
if target_os == 'linux' and target_arch == 'noasm-x64':
target_os = 'linux-noasm'
target_arch = 'x64'
configure_flags = collections.defaultdict(list)
configure_flags['Common'].extend([
'--disable-everything',
'--disable-all',
'--disable-doc',
'--disable-htmlpages',
'--disable-manpages',
'--disable-podpages',
'--disable-txtpages',
'--disable-static',
'--enable-avcodec',
'--enable-avformat',
'--enable-avutil',
'--enable-static',
'--enable-libopus',
'--disable-debug',
'--disable-bzlib',
'--disable-error-resilience',
'--disable-iconv',
'--disable-network',
'--disable-schannel',
'--disable-sdl2',
'--disable-symver',
'--disable-xlib',
'--disable-zlib',
'--disable-securetransport',
'--disable-faan',
'--disable-alsa',
'--disable-iamf',
'--disable-autodetect',
'--enable-decoder=vorbis,libopus,flac',
'--enable-decoder=pcm_u8,pcm_s16le,pcm_s24le,pcm_s32le,pcm_f32le,mp3',
'--enable-decoder=pcm_s16be,pcm_s24be,pcm_mulaw,pcm_alaw',
'--enable-demuxer=ogg,matroska,wav,flac,mp3,mov',
'--enable-parser=opus,vorbis,flac,mpegaudio,vp9',
'--extra-cflags=-I' +
os.path.join(CHROMIUM_ROOT_DIR, 'third_party/opus/src/include'),
'--disable-linux-perf',
'--x86asmexe=nasm',
])
if target_os == 'android':
configure_flags['Common'].extend([
'--enable-small',
])
configure_flags['Common'].extend(SetupAndroidToolchain(target_arch))
else:
configure_flags['Common'].extend([
'--optflags="-O2"',
])
if target_os in ('linux', 'linux-noasm', 'android'):
if target_arch == 'x64':
if target_os == 'android':
configure_flags['Common'].extend([
'--arch=x86_64',
])
else:
configure_flags['Common'].extend([
'--enable-lto',
'--arch=x86_64',
'--target-os=linux',
])
if host_arch != 'x64':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--cross-prefix=/usr/bin/x86_64-linux-gnu-',
'--extra-cflags=--target=x86_64-linux-gnu',
'--extra-ldflags=--target=x86_64-linux-gnu',
])
elif target_arch == 'ia32':
configure_flags['Common'].extend([
'--arch=i686',
'--extra-cflags="-m32"',
'--extra-ldflags="-m32"',
])
if target_os == 'android':
configure_flags['Common'].extend([
'--disable-x86asm',
])
elif target_arch == 'arm' or target_arch == 'arm-neon':
configure_flags['Common'].extend([
'--arch=arm',
'--enable-armv6',
'--enable-armv6t2',
'--enable-vfp',
'--enable-thumb',
'--extra-cflags=-march=armv7-a',
])
if target_os == 'android':
configure_flags['Common'].extend([
'--enable-neon',
'--extra-cflags=-mtune=generic-armv7-a',
'--extra-cflags=-mfloat-abi=softfp',
])
if target_arch == 'arm':
print(
'arm-neon is the only supported arm arch for Android.\n'
)
return 1
if target_arch == 'arm-neon':
configure_flags['Common'].extend([
'--extra-cflags=-mfpu=neon',
])
else:
configure_flags['Common'].extend([
'--extra-cflags=-mfpu=vfpv3-d16',
])
else:
if host_arch != 'arm':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--target-os=linux',
'--extra-cflags=--target=arm-linux-gnueabihf',
'--extra-ldflags=--target=arm-linux-gnueabihf',
'--sysroot=' + os.path.join(
CHROMIUM_ROOT_DIR,
'build/linux/debian_bullseye_armhf-sysroot'),
'--extra-cflags=-mtune=cortex-a8',
'--extra-cflags=-mfloat-abi=hard',
'--extra-cflags=-O2',
])
if target_arch == 'arm-neon':
configure_flags['Common'].extend([
'--enable-neon',
'--extra-cflags=-mfpu=neon',
])
else:
configure_flags['Common'].extend([
'--disable-neon',
'--extra-cflags=-mfpu=vfpv3-d16',
])
elif target_arch == 'arm64':
if target_os != 'android':
if host_arch != 'arm64':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--cross-prefix=/usr/bin/aarch64-linux-gnu-',
'--extra-cflags=--target=aarch64-linux-gnu',
'--extra-ldflags=--target=aarch64-linux-gnu',
])
configure_flags['Common'].extend([
'--target-os=linux',
'--sysroot=' +
os.path.join(CHROMIUM_ROOT_DIR,
'build/linux/debian_bullseye_arm64-sysroot'),
'--disable-dotprod',
'--disable-i8mm',
])
configure_flags['Common'].extend([
'--arch=aarch64',
'--enable-armv8',
'--extra-cflags=-march=armv8-a',
])
elif target_arch == 'mipsel':
configure_flags['Common'].extend([
'--arch=mipsel',
'--disable-mips32r6',
'--disable-mips32r5',
'--disable-mips32r2',
'--disable-mipsdsp',
'--disable-mipsdspr2',
'--disable-msa',
'--enable-mipsfpu',
'--extra-cflags=-march=mipsel',
'--extra-cflags=-mcpu=mips32',
'--extra-ldflags=-z notext',
])
if target_os == 'linux':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--target-os=linux',
'--sysroot=' +
os.path.join(CHROMIUM_ROOT_DIR,
'build/linux/debian_bullseye_mips-sysroot'),
'--extra-cflags=--target=mipsel-linux-gnu',
'--extra-ldflags=--target=mipsel-linux-gnu',
])
elif target_arch == 'mips64el':
configure_flags['Common'].extend([
'--arch=mips64el',
'--enable-mipsfpu',
'--disable-mipsdsp',
'--disable-mipsdspr2',
'--extra-cflags=-march=mips64el',
'--extra-ldflags=-z notext',
])
if target_os == 'android':
configure_flags['Common'].extend([
'--enable-mips64r6',
'--extra-cflags=-mcpu=mips64r6',
'--disable-mips64r2',
'--enable-msa',
])
if target_os == 'linux':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--target-os=linux',
'--sysroot=' + os.path.join(
CHROMIUM_ROOT_DIR,
'build/linux/debian_bullseye_mips64el-sysroot'),
'--enable-mips64r2',
'--disable-mips64r6',
'--disable-msa',
'--extra-cflags=-mcpu=mips64r2',
'--extra-cflags=--target=mips64el-linux-gnuabi64',
'--extra-ldflags=--target=mips64el-linux-gnuabi64',
])
elif target_arch == "riscv64":
configure_flags['Common'].extend([
'--arch=riscv64',
'--extra-cflags=-march=rv64gc',
])
if target_os == 'linux':
configure_flags['Common'].extend([
'--enable-cross-compile',
'--target-os=linux',
'--sysroot=' + os.path.join(
CHROMIUM_ROOT_DIR, 'build/linux/debian_trixie_riscv64-sysroot'),
'--extra-cflags=--target=riscv64-linux-gnu',
'--extra-ldflags=--target=riscv64-linux-gnu',
])
else:
print('Error: Unknown target arch %r for target OS %r!' %
(target_arch, target_os),
file=sys.stderr)
return 1
if target_os == 'linux-noasm':
configure_flags['Common'].extend([
'--disable-asm',
'--disable-inline-asm',
])
if 'win' not in target_os and 'android' not in target_os:
configure_flags['Common'].extend([
'--enable-pic',
'--cc=clang',
'--cxx=clang++',
'--ld=clang',
])
if target_arch != 'ia32' and target_os != 'mac':
configure_flags['Common'].append('--extra-ldflags=-fuse-ld=lld')
if target_os == 'mac':
if host_os != 'mac' and host_os != 'linux':
print('Script should be run on a Mac or Linux host.\n',
file=sys.stderr)
return 1
if host_os != 'mac':
configure_flags['Common'].extend(
SetupMacCrossCompileToolchain(target_arch))
else:
configure_flags['Common'].extend([
'--extra-ldflags=-Wl,-flat_namespace -Wl,-undefined,warning',
])
if target_arch == 'x64':
configure_flags['Common'].extend([
'--arch=x86_64',
'--extra-cflags=-m64',
'--extra-ldflags=-arch x86_64',
])
elif target_arch == 'arm64':
configure_flags['Common'].extend([
'--arch=arm64',
'--extra-cflags=-arch arm64',
'--extra-ldflags=-arch arm64',
])
else:
print('Error: Unknown target arch %r for target OS %r!' %
(target_arch, target_os),
file=sys.stderr)
if target_os == 'win':
configure_flags['Common'].extend([
'--toolchain=msvc',
'--extra-cflags=-I' +
os.path.join(FFMPEG_DIR, 'chromium/include/win'),
])
if target_arch == 'x64':
configure_flags['Common'].extend(['--target-os=win64'])
elif target_arch == 'x86':
configure_flags['Common'].extend(['--target-os=win32'])
if host_os != 'win':
configure_flags['Common'].extend(
SetupWindowsCrossCompileToolchain(target_arch))
if 'CYGWIN_NT' in platform.system():
configure_flags['Common'].extend([
'--cc=cygwin-wrapper cl',
'--ld=cygwin-wrapper link',
'--nm=cygwin-wrapper dumpbin -symbols',
'--ar=cygwin-wrapper lib',
])
configure_flags['Chrome'].extend([
'--enable-decoder=aac,h264',
'--enable-demuxer=aac',
'--enable-parser=aac,h264',
])
configure_flags['ChromeAndroid'].extend([
'--enable-demuxer=aac',
'--enable-parser=aac',
'--enable-decoder=aac',
])
def do_build_ffmpeg(branding, configure_flags):
if options.brandings and branding not in options.brandings:
print('%s skipped' % branding)
return
print('%s configure/build:' % branding)
BuildFFmpeg(target_os, target_arch, host_os, host_arch, parallel_jobs,
options.config_only, branding, configure_flags, options)
if target_os != 'android' or not target_arch in ("arm", "arm-neon"):
do_build_ffmpeg(
'Chromium', configure_flags['Common'] +
configure_flags['Chromium'] + configure_args)
do_build_ffmpeg(
'Chrome', configure_flags['Common'] + configure_flags['Chrome'] +
configure_args)
else:
do_build_ffmpeg('Chromium', configure_flags['Common'] + configure_args)
do_build_ffmpeg(
'Chrome', configure_flags['Common'] +
configure_flags['ChromeAndroid'] + configure_args)
print('Done. If desired you may copy config.h/config.asm into the '
'source/config tree using copy_config.sh.')
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))