mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Background: Some allocators (tcmalloc) don't provide alignment guarantees that match clang's default expectations, which causes crashes when using clang compiled binary with such allocators. For example clang can produce movaps instructions to initialize newly allocated object - which would crash if result of ::operator new() is not 16 bytes aligned.
323 lines
11 KiB
Python
Executable File
323 lines
11 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2013 The Flutter Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import argparse
|
|
import subprocess
|
|
import sys
|
|
import os
|
|
|
|
SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
def get_out_dir(args):
|
|
if args.target_os is not None:
|
|
target_dir = [args.target_os]
|
|
else:
|
|
target_dir = ['host']
|
|
|
|
runtime_mode = args.runtime_mode
|
|
if args.dynamic and runtime_mode in ['profile', 'release']:
|
|
target_dir.append('dynamic')
|
|
|
|
target_dir.append(args.runtime_mode)
|
|
|
|
if args.simulator:
|
|
target_dir.append('sim')
|
|
|
|
if args.unoptimized:
|
|
target_dir.append('unopt')
|
|
|
|
if args.target_os != 'ios' and args.interpreter:
|
|
target_dir.append('interpreter')
|
|
|
|
if args.android_cpu != 'arm':
|
|
target_dir.append(args.android_cpu)
|
|
|
|
if args.ios_cpu != 'arm64':
|
|
target_dir.append(args.ios_cpu)
|
|
|
|
if args.linux_cpu is not None:
|
|
target_dir.append(args.linux_cpu)
|
|
|
|
if args.enable_vulkan:
|
|
target_dir.append('vulkan')
|
|
|
|
return os.path.join('out', '_'.join(target_dir))
|
|
|
|
def to_command_line(gn_args):
|
|
def merge(key, value):
|
|
if type(value) is bool:
|
|
return '%s=%s' % (key, 'true' if value else 'false')
|
|
return '%s="%s"' % (key, value)
|
|
return [merge(x, y) for x, y in gn_args.iteritems()]
|
|
|
|
def cpu_for_target_arch(arch):
|
|
if arch in ['ia32', 'arm', 'armv6', 'armv5te', 'mips',
|
|
'simarm', 'simarmv6', 'simarmv5te', 'simmips', 'simdbc',
|
|
'armsimdbc']:
|
|
return 'x86'
|
|
if arch in ['x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64']:
|
|
return 'x64'
|
|
|
|
def to_gn_args(args):
|
|
if args.simulator:
|
|
if args.target_os == 'android':
|
|
raise Exception('--simulator is not supported on Android')
|
|
elif args.target_os == 'ios':
|
|
if args.runtime_mode != 'debug':
|
|
raise Exception('iOS simulator only supports the debug runtime mode')
|
|
|
|
if args.target_os != 'android' and args.enable_vulkan:
|
|
raise Exception('--enable-vulkan is only supported on Android')
|
|
|
|
runtime_mode = args.runtime_mode
|
|
if args.dynamic and runtime_mode in ['profile', 'release']:
|
|
runtime_mode = 'dynamic_' + runtime_mode
|
|
|
|
gn_args = {}
|
|
|
|
# Skia GN args.
|
|
gn_args['skia_enable_flutter_defines'] = True # Enable Flutter API guards in Skia.
|
|
gn_args['skia_use_dng_sdk'] = False # RAW image handling.
|
|
gn_args['skia_use_sfntly'] = False # PDF handling depedency.
|
|
gn_args['skia_enable_pdf'] = False # PDF handling.
|
|
gn_args['skia_use_x11'] = False # Never add the X11 dependency (only takes effect on Linux).
|
|
gn_args['skia_use_expat'] = args.target_os == 'android'
|
|
gn_args['skia_use_fontconfig'] = False # Use the custom font manager instead.
|
|
gn_args['is_official_build'] = True # Disable Skia test utilities.
|
|
|
|
gn_args['is_debug'] = args.unoptimized
|
|
gn_args['android_full_debug'] = args.target_os == 'android' and args.unoptimized
|
|
gn_args['is_clang'] = not sys.platform.startswith(('cygwin', 'win'))
|
|
|
|
gn_args['embedder_for_target'] = args.embedder_for_target
|
|
|
|
if args.operator_new_alignment is not None:
|
|
gn_args['operator_new_alignment'] = args.operator_new_alignment
|
|
|
|
enable_lto = args.lto
|
|
if args.unoptimized:
|
|
# There is no point in enabling LTO in unoptimized builds.
|
|
enable_lto = False
|
|
|
|
if not sys.platform.startswith('win'):
|
|
# The GN arg is not available in the windows toolchain.
|
|
gn_args['enable_lto'] = enable_lto
|
|
|
|
aot = not runtime_mode in ['debug', 'dynamic_profile', 'dynamic_release']
|
|
if args.target_os == 'android':
|
|
gn_args['target_os'] = 'android'
|
|
elif args.target_os == 'ios':
|
|
gn_args['target_os'] = 'ios'
|
|
gn_args['use_ios_simulator'] = args.simulator
|
|
if not args.simulator:
|
|
aot = True
|
|
elif args.target_os is not None:
|
|
gn_args['target_os'] = args.target_os
|
|
else:
|
|
aot = False
|
|
|
|
gn_args['dart_lib_export_symbols'] = False
|
|
|
|
if runtime_mode == 'debug':
|
|
gn_args['dart_runtime_mode'] = 'develop'
|
|
elif runtime_mode == 'dynamic_profile':
|
|
gn_args['dart_runtime_mode'] = 'profile'
|
|
elif runtime_mode == 'dynamic_release':
|
|
gn_args['dart_runtime_mode'] = 'release'
|
|
else:
|
|
gn_args['dart_runtime_mode'] = runtime_mode
|
|
|
|
if args.dart_debug:
|
|
gn_args['dart_debug'] = True
|
|
|
|
if args.target_os == 'android':
|
|
gn_args['target_cpu'] = args.android_cpu
|
|
elif args.target_os == 'ios':
|
|
if args.simulator:
|
|
gn_args['target_cpu'] = 'x64'
|
|
else:
|
|
gn_args['target_cpu'] = args.ios_cpu
|
|
elif args.target_os == 'linux':
|
|
gn_args['target_cpu'] = args.linux_cpu
|
|
else:
|
|
# Building host artifacts
|
|
gn_args['target_cpu'] = 'x64'
|
|
|
|
# On iOS Devices, use the Dart bytecode interpreter so we don't incur
|
|
# snapshotting and linking costs of the precompiler during development.
|
|
# We can still use the JIT on the simulator though.
|
|
can_use_dbc = runtime_mode in ['debug', 'dynamic_profile', 'dynamic_release']
|
|
use_dbc = args.target_os == 'ios' and not args.simulator and can_use_dbc
|
|
# Use dbc if it is requested on the command line and supported by the
|
|
# requested runtime mode.
|
|
if args.interpreter and not can_use_dbc:
|
|
raise Exception('--interpreter not supported with --runtime-mode=' + runtime_mode)
|
|
use_dbc = use_dbc or (args.interpreter and can_use_dbc)
|
|
if use_dbc:
|
|
gn_args['dart_target_arch'] = 'dbc'
|
|
else:
|
|
gn_args['dart_target_arch'] = gn_args['target_cpu']
|
|
|
|
# No cross-compilation on Windows (for now).
|
|
if sys.platform.startswith(('cygwin', 'win')):
|
|
if 'target_os' in gn_args:
|
|
gn_args['target_os'] = 'win'
|
|
if 'target_cpu' in gn_args:
|
|
gn_args['target_cpu'] = cpu_for_target_arch(gn_args['target_cpu'])
|
|
|
|
if args.target_os is None:
|
|
if sys.platform.startswith(('cygwin', 'win')):
|
|
gn_args['dart_use_fallback_root_certificates'] = True
|
|
|
|
|
|
gn_args['dart_custom_version_for_pub'] = 'flutter'
|
|
|
|
# Make sure host_cpu matches the bit width of target_cpu.
|
|
target_is_32_bit = gn_args['target_cpu'] == 'arm' or gn_args['target_cpu'] == 'x86'
|
|
if target_is_32_bit:
|
|
gn_args["host_cpu"] = "x86"
|
|
|
|
gn_args['flutter_runtime_mode'] = runtime_mode
|
|
gn_args['flutter_aot'] = aot
|
|
|
|
if args.target_sysroot:
|
|
gn_args['target_sysroot'] = args.target_sysroot
|
|
gn_args['custom_sysroot'] = args.target_sysroot
|
|
|
|
if args.target_toolchain:
|
|
gn_args['custom_toolchain'] = args.target_toolchain
|
|
|
|
if args.target_triple:
|
|
gn_args['custom_target_triple'] = args.target_triple
|
|
|
|
if args.toolchain_prefix:
|
|
gn_args['toolchain_prefix'] = args.toolchain_prefix
|
|
|
|
goma_dir = os.environ.get('GOMA_DIR')
|
|
goma_home_dir = os.path.join(os.getenv('HOME', ''), 'goma')
|
|
if args.goma and goma_dir:
|
|
gn_args['use_goma'] = True
|
|
gn_args['goma_dir'] = goma_dir
|
|
elif args.goma and os.path.exists(goma_home_dir):
|
|
gn_args['use_goma'] = True
|
|
gn_args['goma_dir'] = goma_home_dir
|
|
else:
|
|
gn_args['use_goma'] = False
|
|
gn_args['goma_dir'] = None
|
|
|
|
if args.enable_vulkan:
|
|
# Enable vulkan in the Flutter shell.
|
|
gn_args['shell_enable_vulkan'] = True
|
|
# Configure Skia for Vulkan support.
|
|
gn_args['skia_use_vulkan'] = True
|
|
|
|
# We should not need a special case for x86, but this seems to introduce text relocations
|
|
# even with -fPIC everywhere.
|
|
# gn_args['enable_profiling'] = args.runtime_mode != 'release' and args.android_cpu != 'x86'
|
|
|
|
if args.arm_float_abi:
|
|
gn_args['arm_float_abi'] = args.arm_float_abi
|
|
|
|
return gn_args
|
|
|
|
def parse_args(args):
|
|
args = args[1:]
|
|
parser = argparse.ArgumentParser(description='A script run` gn gen`.')
|
|
|
|
parser.add_argument('--unoptimized', default=False, action='store_true')
|
|
|
|
parser.add_argument('--runtime-mode', type=str, choices=['debug', 'profile', 'release'], default='debug')
|
|
parser.add_argument('--dynamic', default=False, action='store_true')
|
|
parser.add_argument('--interpreter', default=False, action='store_true')
|
|
parser.add_argument('--dart-debug', default=False, action='store_true')
|
|
|
|
parser.add_argument('--target-os', type=str, choices=['android', 'ios', 'linux'])
|
|
parser.add_argument('--android', dest='target_os', action='store_const', const='android')
|
|
parser.add_argument('--android-cpu', type=str, choices=['arm', 'x64', 'x86', 'arm64'], default='arm')
|
|
parser.add_argument('--ios', dest='target_os', action='store_const', const='ios')
|
|
parser.add_argument('--ios-cpu', type=str, choices=['arm', 'arm64'], default='arm64')
|
|
parser.add_argument('--simulator', action='store_true', default=False)
|
|
parser.add_argument('--linux-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'])
|
|
parser.add_argument('--arm-float-abi', type=str, choices=['hard', 'soft', 'softfp'])
|
|
|
|
parser.add_argument('--goma', default=True, action='store_true')
|
|
parser.add_argument('--no-goma', dest='goma', action='store_false')
|
|
|
|
parser.add_argument('--lto', default=True, action='store_true')
|
|
parser.add_argument('--no-lto', dest='lto', action='store_false')
|
|
|
|
parser.add_argument('--clang', default=True, action='store_true')
|
|
parser.add_argument('--no-clang', dest='clang', action='store_false')
|
|
|
|
parser.add_argument('--target-sysroot', type=str)
|
|
parser.add_argument('--target-toolchain', type=str)
|
|
parser.add_argument('--target-triple', type=str)
|
|
parser.add_argument('--toolchain-prefix', type=str)
|
|
parser.add_argument('--operator-new-alignment', dest='operator_new_alignment', type=str, default=None)
|
|
|
|
parser.add_argument('--enable-vulkan', action='store_true', default=False)
|
|
|
|
parser.add_argument('--embedder-for-target', dest='embedder_for_target', action='store_true', default=False)
|
|
|
|
return parser.parse_args(args)
|
|
|
|
def main(argv):
|
|
args = parse_args(argv)
|
|
|
|
if sys.platform.startswith(('cygwin', 'win')):
|
|
subdir = 'win'
|
|
elif sys.platform == 'darwin':
|
|
subdir = 'mac-x64'
|
|
elif sys.platform.startswith('linux'):
|
|
subdir = 'linux-x64'
|
|
else:
|
|
raise Error('Unknown platform: ' + sys.platform)
|
|
|
|
command = [
|
|
'%s/buildtools/%s/gn' % (SRC_ROOT, subdir),
|
|
'gen',
|
|
'--check',
|
|
]
|
|
|
|
if sys.platform == 'darwin':
|
|
# On the Mac, also generate Xcode projects for ease of editing.
|
|
command.append('--ide=xcode')
|
|
|
|
if sys.platform.startswith('win'):
|
|
# On Windows, also generate Visual Studio project for ease of editing.
|
|
command.append('--ide=vs')
|
|
|
|
gn_args = to_command_line(to_gn_args(args))
|
|
out_dir = get_out_dir(args)
|
|
print "gn gen --check in %s" % out_dir
|
|
command.append(out_dir)
|
|
command.append('--args=%s' % ' '.join(gn_args))
|
|
gn_call_result = subprocess.call(command, cwd=SRC_ROOT)
|
|
|
|
if gn_call_result == 0:
|
|
# Generate/Replace the compile commands database in out.
|
|
compile_cmd_gen_cmd = [
|
|
'ninja',
|
|
'-C',
|
|
out_dir,
|
|
'-t',
|
|
'compdb',
|
|
'cc',
|
|
'cxx',
|
|
'objc',
|
|
'objcxx',
|
|
'asm',
|
|
]
|
|
|
|
contents = subprocess.check_output(compile_cmd_gen_cmd, cwd=SRC_ROOT)
|
|
compile_commands = open('%s/out/compile_commands.json' % SRC_ROOT, 'w+')
|
|
compile_commands.write(contents)
|
|
compile_commands.close()
|
|
|
|
return gn_call_result
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv))
|