mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
* use clang on Windows for everything but Android This pulls the Clang build from Chromium. We should eventually switch to use the Fuchsia toolchain when it is available.
436 lines
17 KiB
Python
Executable File
436 lines
17 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
|
|
|
|
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.target_os == 'fuchsia' and args.fuchsia_cpu is not None:
|
|
target_dir.append(args.fuchsia_cpu)
|
|
|
|
if args.enable_vulkan:
|
|
target_dir.append('vulkan')
|
|
|
|
return os.path.join(args.out_dir, '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
|
|
|
|
gn_args = {}
|
|
|
|
if args.bitcode:
|
|
if args.target_os != 'ios':
|
|
raise Exception('Bitcode is only supported for iOS')
|
|
if runtime_mode != 'release':
|
|
gn_args['bitcode_marker'] = True
|
|
|
|
gn_args['enable_bitcode'] = args.bitcode
|
|
|
|
# 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 dependency.
|
|
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_wuffs'] = True
|
|
gn_args['skia_use_expat'] = args.target_os == 'android'
|
|
gn_args['skia_use_fontconfig'] = args.enable_fontconfig
|
|
gn_args['flutter_use_fontconfig'] = args.enable_fontconfig
|
|
gn_args['flutter_enable_skshaper'] = args.enable_skshaper
|
|
if args.enable_skshaper:
|
|
gn_args['skia_use_icu'] = True
|
|
gn_args['is_official_build'] = True # Disable Skia test utilities.
|
|
gn_args['dart_component_kind'] = 'static_library' # Always link Dart in statically.
|
|
gn_args['is_debug'] = args.unoptimized
|
|
gn_args['android_full_debug'] = args.target_os == 'android' and args.unoptimized
|
|
if args.clang is None:
|
|
# Android gen_snapshot currently isn't buildable with clang on Windows.
|
|
# For everything else, default to clang.
|
|
gn_args['is_clang'] = not (sys.platform.startswith(('cygwin', 'win')) and
|
|
args.target_os == 'android')
|
|
else:
|
|
gn_args['is_clang'] = args.clang
|
|
|
|
if args.target_os == 'android' or args.target_os == 'ios':
|
|
gn_args['skia_gl_standard'] = 'gles'
|
|
else:
|
|
# We explicitly don't want to pick GL because we run GLES tests using SwiftShader.
|
|
gn_args['skia_gl_standard'] = ''
|
|
|
|
if not sys.platform.startswith(('cygwin', 'win')):
|
|
gn_args['use_clang_static_analyzer'] = args.clang_static_analyzer
|
|
|
|
gn_args['embedder_for_target'] = args.embedder_for_target
|
|
|
|
gn_args['enable_coverage'] = args.coverage
|
|
|
|
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
|
|
|
|
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
|
|
elif args.target_os is not None:
|
|
gn_args['target_os'] = args.target_os
|
|
|
|
gn_args['dart_lib_export_symbols'] = False
|
|
|
|
if runtime_mode == 'debug':
|
|
gn_args['dart_runtime_mode'] = 'develop'
|
|
elif runtime_mode == 'jit_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.full_dart_debug:
|
|
gn_args['dart_debug'] = True
|
|
gn_args['dart_debug_optimization_level'] = '0'
|
|
|
|
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
|
|
elif args.target_os == 'fuchsia':
|
|
gn_args['target_cpu'] = args.fuchsia_cpu
|
|
else:
|
|
# Building host artifacts
|
|
gn_args['target_cpu'] = 'x64'
|
|
|
|
# DBC is not supported anymore.
|
|
if args.interpreter:
|
|
raise Exception('--interpreter is no longer needed on any supported platform.')
|
|
gn_args['dart_target_arch'] = gn_args['target_cpu']
|
|
|
|
if sys.platform.startswith(('cygwin', '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 on x86.
|
|
if gn_args['target_cpu'] == 'x86':
|
|
gn_args['host_cpu'] = 'x86'
|
|
|
|
gn_args['flutter_runtime_mode'] = runtime_mode
|
|
|
|
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
|
|
|
|
goma_dir = os.environ.get('GOMA_DIR')
|
|
goma_home_dir = os.path.join(os.getenv('HOME', ''), 'goma')
|
|
|
|
# GOMA has a different default (home) path on gWindows.
|
|
if not os.path.exists(goma_home_dir) and sys.platform.startswith(('cygwin', 'win')):
|
|
goma_home_dir = os.path.join('c:\\', 'src', 'goma', 'goma-win64')
|
|
|
|
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
|
|
|
|
# Enable Metal on non-simulator iOS builds.
|
|
if args.target_os == 'ios' and not args.simulator:
|
|
gn_args['skia_use_metal'] = True
|
|
gn_args['shell_enable_metal'] = True
|
|
# Bitcode enabled builds using the current version of the toolchain leak
|
|
# C++ symbols decorated with the availability attribute. Disable these
|
|
# attributes in release modes till the toolchain is updated.
|
|
gn_args['skia_enable_api_available_macro'] = args.runtime_mode != "release"
|
|
|
|
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
|
|
|
|
# The buildroot currently isn't set up to support Vulkan in the
|
|
# Windows ANGLE build, so disable it regardless of enable_vulkan's value.
|
|
if sys.platform.startswith(('cygwin', 'win')):
|
|
gn_args['angle_enable_vulkan'] = False
|
|
|
|
# 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
|
|
|
|
# Whether to build trained Dart SDK snapshots of dart2js and dartdevc,
|
|
# including the web sdk kernel and source files.
|
|
if args.target_os is None:
|
|
# dart_platform_sdk is not declared for Android targets.
|
|
gn_args['dart_platform_sdk'] = not args.full_dart_sdk
|
|
gn_args['full_dart_sdk'] = args.full_dart_sdk
|
|
|
|
# Desktop embeddings can have more dependencies than the engine library,
|
|
# which can be problematic in some build environments (e.g., building on
|
|
# Linux will bring in pkg-config dependencies at generation time). These
|
|
# flags allow preventing those those targets from being part of the build
|
|
# tree.
|
|
gn_args['enable_desktop_embeddings'] = not args.disable_desktop_embeddings
|
|
if args.build_glfw_shell is not None:
|
|
gn_args['build_glfw_shell'] = args.build_glfw_shell
|
|
|
|
gn_args['stripped_symbols'] = args.stripped
|
|
|
|
if args.msan:
|
|
gn_args['is_msan'] = True
|
|
|
|
if args.asan:
|
|
gn_args['is_asan'] = True
|
|
|
|
if args.tsan:
|
|
gn_args['is_tsan'] = True
|
|
|
|
if args.lsan:
|
|
gn_args['is_lsan'] = True
|
|
|
|
if args.ubsan:
|
|
gn_args['is_ubsan'] = True
|
|
|
|
if args.enable_vulkan_validation_layers:
|
|
if args.target_os is not 'fuchsia':
|
|
print('Vulkan validation layers are currently only supported on Fuchsia targets.')
|
|
sys.exit(1)
|
|
gn_args['enable_vulkan_validation_layers'] = True
|
|
|
|
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', 'jit_release'], default='debug')
|
|
parser.add_argument('--interpreter', default=False, action='store_true')
|
|
parser.add_argument('--dart-debug', default=False, action='store_true', help='Enables assertions in the Dart VM. ' +
|
|
'Does not affect optimization levels. If you need to disable optimizations in Dart, use --full-dart-debug')
|
|
parser.add_argument('--full-dart-debug', default=False, action='store_true', help='Implies --dart-debug ' +
|
|
'and also disables optimizations in the Dart VM making it easier to step through VM code in the debugger.')
|
|
|
|
parser.add_argument('--target-os', type=str, choices=['android', 'ios', 'linux', 'fuchsia'])
|
|
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('--fuchsia', dest='target_os', action='store_const', const='fuchsia')
|
|
parser.add_argument('--linux-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'])
|
|
parser.add_argument('--fuchsia-cpu', type=str, choices=['x64', 'arm64'], default = 'x64')
|
|
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', action='store_const', const=True)
|
|
parser.add_argument('--no-clang', dest='clang', action='store_const', const=False)
|
|
|
|
parser.add_argument('--clang-static-analyzer', default=False, action='store_true')
|
|
parser.add_argument('--no-clang-static-analyzer', dest='clang_static_analyzer', 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('--operator-new-alignment', dest='operator_new_alignment', type=str, default=None)
|
|
|
|
parser.add_argument('--enable-vulkan', action='store_true', default=False)
|
|
|
|
parser.add_argument('--enable-fontconfig', action='store_true', default=False)
|
|
parser.add_argument('--enable-skshaper', action='store_true', default=False)
|
|
parser.add_argument('--enable-vulkan-validation-layers', action='store_true', default=False)
|
|
|
|
parser.add_argument('--embedder-for-target', dest='embedder_for_target', action='store_true', default=False)
|
|
|
|
parser.add_argument('--coverage', default=False, action='store_true')
|
|
|
|
parser.add_argument('--out-dir', default='', type=str)
|
|
|
|
parser.add_argument('--full-dart-sdk', default=False, action='store_true',
|
|
help='include trained dart2js and dartdevc snapshots. Enable only on steps that create an SDK')
|
|
parser.add_argument('--no-full-dart-sdk', dest='full_dart_sdk', action='store_false')
|
|
|
|
parser.add_argument('--ide', default='', type=str,
|
|
help='The IDE files to generate using GN. Use `gn gen help` and look for the --ide flag to' +
|
|
' see supported IDEs. If this flag is not specified, a platform specific default is selected.')
|
|
|
|
parser.add_argument('--disable-desktop-embeddings', default=False, action='store_true',
|
|
help='Do not include desktop embeddings in the build.')
|
|
parser.add_argument('--build-glfw-shell', action='store_const', const=True,
|
|
help='Build the GLFW shell on supported platforms where it is not built by default.')
|
|
parser.add_argument('--no-build-glfw-shell', dest='build_glfw_shell', action='store_const', const=False,
|
|
help='Do not build the GLFW shell on platforms where it is built by default.')
|
|
|
|
parser.add_argument('--bitcode', default=False, action='store_true',
|
|
help='Enable bitcode for iOS targets. On debug runtime modes, this will be a marker only.')
|
|
|
|
parser.add_argument('--stripped', default=True, action='store_true',
|
|
help='Strip debug symbols from the output. This defaults to true and has no effect on iOS.')
|
|
parser.add_argument('--no-stripped', dest='stripped', action='store_false')
|
|
|
|
# Sanitizers.
|
|
parser.add_argument('--asan', default=False, action='store_true')
|
|
parser.add_argument('--lsan', default=False, action='store_true')
|
|
parser.add_argument('--msan', default=False, action='store_true')
|
|
parser.add_argument('--tsan', default=False, action='store_true')
|
|
parser.add_argument('--ubsan', default=False, action='store_true')
|
|
|
|
return parser.parse_args(args)
|
|
|
|
def main(argv):
|
|
args = parse_args(argv)
|
|
|
|
exe = '.exe' if sys.platform.startswith(('cygwin', 'win')) else ''
|
|
|
|
command = [
|
|
'%s/flutter/third_party/gn/gn%s' % (SRC_ROOT, exe),
|
|
'gen',
|
|
'--check',
|
|
]
|
|
|
|
if args.ide != '':
|
|
command.append('--ide=%s' % args.ide)
|
|
elif sys.platform == 'darwin':
|
|
# On the Mac, generate an Xcode project by default.
|
|
command.append('--ide=xcode')
|
|
elif sys.platform.startswith('win'):
|
|
# On Windows, generate a Visual Studio project.
|
|
command.append('--ide=vs')
|
|
|
|
gn_args = to_command_line(to_gn_args(args))
|
|
out_dir = get_out_dir(args)
|
|
command.append(out_dir)
|
|
command.append('--args=%s' % ' '.join(gn_args))
|
|
print "Generating GN files in: %s" % out_dir
|
|
try:
|
|
gn_call_result = subprocess.call(command, cwd=SRC_ROOT)
|
|
except subprocess.CalledProcessError as exc:
|
|
print "Failed to generate gn files: ", exc.returncode, exc.output
|
|
sys.exit(1)
|
|
|
|
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',
|
|
]
|
|
|
|
try:
|
|
contents = subprocess.check_output(compile_cmd_gen_cmd, cwd=SRC_ROOT)
|
|
except subprocess.CalledProcessError as exc:
|
|
print "Failed to run ninja: ", exc.returncode, exc.output
|
|
sys.exit(1)
|
|
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))
|