Files
engine/tools/gn
T
James Clarke ff484d4f69 [Windows] Alternative Windows shell platform implementation (#9835)
Start work on flutter/flutter#30726 by adding an alternative win32 shell platform implementation for Windows that is not based on GLFW and that uses LIBANGLE for rendering and native win32 windowing and input. This change does not replace the GLFW implementation but rather runs side by side with it producing a secondary flutter_windows_win32.dll artifact. The following items must be added to attain parity with the GLFW implementation:
- Custom task scheduling
- Support for keyboard modifier keys
- Async texture uploads
- Correct high DPI handling on Windows versions < 1703
and will be added in subsequent changes.
2019-08-14 15:52:52 -07:00

404 lines
15 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.target_os == 'fuchsia' and args.fuchsia_cpu is not None:
target_dir.append(args.fuchsia_cpu)
if args.enable_vulkan:
target_dir.append('vulkan')
if args.enable_metal:
target_dir.append('metal')
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')
if args.target_os != 'ios' and args.enable_metal:
raise Exception('--enable-metal is only supported on iOS')
runtime_mode = args.runtime_mode
if args.dynamic and runtime_mode in ['profile', 'release']:
runtime_mode = 'dynamic_' + runtime_mode
gn_args = {}
if args.bitcode:
if args.target_os != 'ios':
raise Exception('Bitcode is only supported for iOS')
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
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
gn_args['is_clang'] = not sys.platform.startswith(('cygwin', 'win'))
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 == '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.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
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')
# 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
if args.enable_metal:
gn_args['skia_use_metal'] = True
gn_args['shell_enable_metal'] = True
gn_args['ios_deployment_target'] = '11'
gn_args['allow_deprecated_api_calls'] = True
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
if sys.platform == 'darwin':
gn_args['mac_sdk_path'] = args.mac_sdk_path
if args.build_glfw_shell:
gn_args['build_glfw_shell'] = True
if gn_args['mac_sdk_path'] == '':
gn_args['mac_sdk_path'] = os.getenv('FLUTTER_MAC_SDK_PATH', '')
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', help='Enables assertsion 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', default=True, action='store_true')
parser.add_argument('--no-clang', dest='clang', action='store_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('--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('--enable-metal', 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('--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('--mac-sdk-path', default='', type=str,
help='On the mac, the SDK is inferred from the Xcode location unless this flag is specified. ' +
' Setting the FLUTTER_MAC_SDK_PATH environment variable achieves the same effect.')
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('--build-glfw-shell', dest='build_glfw_shell', default=False, action='store_true',
help='Force building the GLFW shell on desktop platforms where it is not built by default.')
parser.add_argument('--bitcode', default=False, action='store_true',
help='Enable bitcode for iOS targets.')
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))