|  | #!/usr/bin/env python3 | 
|  | # Copyright 2016 The Dart project 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 os | 
|  | import platform | 
|  | import subprocess | 
|  | import socket | 
|  | import sys | 
|  | import time | 
|  | import utils | 
|  |  | 
|  | HOST_OS = utils.GuessOS() | 
|  | HOST_ARCH = utils.GuessArchitecture() | 
|  | SCRIPT_DIR = os.path.dirname(sys.argv[0]) | 
|  | DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) | 
|  | AVAILABLE_ARCHS = utils.ARCH_FAMILY.keys() | 
|  |  | 
|  | # Environment variables for default settings. | 
|  | DART_USE_TOOLCHAIN = "DART_USE_TOOLCHAIN"  # Use instead of --toolchain-prefix | 
|  | DART_USE_SYSROOT = "DART_USE_SYSROOT"  # Use instead of --target-sysroot | 
|  | DART_USE_CRASHPAD = "DART_USE_CRASHPAD"  # Use instead of --use-crashpad | 
|  | # use instead of --platform-sdk | 
|  | DART_MAKE_PLATFORM_SDK = "DART_MAKE_PLATFORM_SDK" | 
|  |  | 
|  | DART_GN_ARGS = "DART_GN_ARGS" | 
|  |  | 
|  |  | 
|  | def ToolchainPrefix(args): | 
|  | if args.toolchain_prefix: | 
|  | return args.toolchain_prefix | 
|  | return os.environ.get(DART_USE_TOOLCHAIN) | 
|  |  | 
|  |  | 
|  | def TargetSysroot(args): | 
|  | if args.target_sysroot: | 
|  | return args.target_sysroot | 
|  | return os.environ.get(DART_USE_SYSROOT) | 
|  |  | 
|  |  | 
|  | def MakePlatformSDK(): | 
|  | return DART_MAKE_PLATFORM_SDK in os.environ | 
|  |  | 
|  |  | 
|  | def GetGNArgs(args): | 
|  | if args.gn_args != None: | 
|  | return args.gn_args | 
|  | args = os.environ.get(DART_GN_ARGS) or "" | 
|  | return args.split() | 
|  |  | 
|  |  | 
|  | def GetOutDir(mode, arch, target_os, sanitizer): | 
|  | return utils.GetBuildRoot(HOST_OS, mode, arch, target_os, sanitizer) | 
|  |  | 
|  |  | 
|  | def ToCommandLine(gn_args): | 
|  |  | 
|  | def merge(key, value): | 
|  | if type(value) is bool: | 
|  | return '%s=%s' % (key, 'true' if value else 'false') | 
|  | elif type(value) is int: | 
|  | return '%s=%d' % (key, value) | 
|  | return '%s="%s"' % (key, value) | 
|  |  | 
|  | return [merge(x, y) for x, y in gn_args.items()] | 
|  |  | 
|  |  | 
|  | # The C compiler's target under the host toolchain (DART_HOST_ARCH_***). | 
|  | def HostCpuForArch(arch): | 
|  | arch = arch.split("_")[-1] | 
|  |  | 
|  | # For each target architecture, we prefer in descending order | 
|  | # - using the same architecture for the host (supports all architectures) | 
|  | # - using a host architecture with the same word size (supports arm and riscv, which have simulators) | 
|  | # - using a host architecture with a different word size (supports only AOT and only 32-bit target on 64-bit host) | 
|  | if arch in ['ia32']: | 
|  | candidates = ['x86'] | 
|  | elif arch in ['x64', 'x64c', 'simx64', 'simx64c']: | 
|  | candidates = ['x64', 'arm64'] | 
|  | elif arch in ['arm', 'simarm']: | 
|  | candidates = ['arm', 'x86', 'riscv32', 'arm64', 'x64', 'riscv64'] | 
|  | elif arch in ['arm64', 'arm64c', 'simarm64', 'simarm64c']: | 
|  | candidates = ['arm64', 'x64', 'riscv64'] | 
|  | elif arch in ['riscv32', 'simriscv32']: | 
|  | candidates = ['riscv32', 'arm', 'x86', 'riscv64', 'arm64', 'x64'] | 
|  | elif arch in ['riscv64', 'simriscv64']: | 
|  | candidates = ['riscv64', 'arm64', 'x64'] | 
|  | else: | 
|  | raise Exception("Unknown Dart architecture: %s" % arch) | 
|  |  | 
|  | available = utils.HostArchitectures() | 
|  | for candidate in candidates: | 
|  | if candidate in available: | 
|  | return candidate | 
|  |  | 
|  | raise Exception( | 
|  | "Failed to find a C host architecture for %s. Need one of %s but only %s are available." | 
|  | % (arch, candidates, available)) | 
|  |  | 
|  |  | 
|  | # The C compiler's target under the target toolchain (DART_HOST_ARCH_***). | 
|  | def TargetCpuForArch(arch): | 
|  | # Real target architectures | 
|  | if arch.startswith('ia32'): | 
|  | return 'x86' | 
|  | elif arch.startswith('x64'): | 
|  | return 'x64' | 
|  | elif arch.startswith('arm64'): | 
|  | return 'arm64' | 
|  | elif arch.startswith('arm'): | 
|  | return 'arm' | 
|  | elif arch.startswith('riscv32'): | 
|  | return 'riscv32' | 
|  | elif arch.startswith('riscv64'): | 
|  | return 'riscv64' | 
|  |  | 
|  | # Simulators | 
|  | if arch.endswith('_x64'): | 
|  | return 'x64' | 
|  | elif arch.endswith('_arm64'): | 
|  | return 'arm64' | 
|  | elif arch.endswith('_riscv64'): | 
|  | return 'riscv64' | 
|  | elif arch in ['simarm', 'simriscv32']: | 
|  | candidates = ['arm', 'riscv32', 'x86'] | 
|  | elif arch in ['simx64', 'simx64c', 'simarm64', 'simarm64c', 'simriscv64']: | 
|  | candidates = ['arm64', 'riscv64', 'x64'] | 
|  | else: | 
|  | raise Exception("Unknown Dart architecture: %s" % arch) | 
|  |  | 
|  | available = utils.HostArchitectures() | 
|  | for candidate in candidates: | 
|  | if candidate in available: | 
|  | return candidate | 
|  |  | 
|  | raise Exception( | 
|  | "Failed to find a C target architecture for %s. Need one of %s but only %s are available." | 
|  | % (arch, candidates, available)) | 
|  |  | 
|  |  | 
|  | # The Dart compiler's target (DART_TARGET_ARCH_***) | 
|  | def DartTargetCpuForArch(arch): | 
|  | arch = arch.split("_")[0] | 
|  | if arch.startswith("sim"): | 
|  | arch = arch[3:] | 
|  | if arch.endswith("c"): | 
|  | arch = arch[:-1] | 
|  | return arch | 
|  |  | 
|  |  | 
|  | def IsCompressedPointerArch(arch): | 
|  | return "64c" in arch | 
|  |  | 
|  |  | 
|  | def HostOsForGn(host_os): | 
|  | if host_os.startswith('macos'): | 
|  | return 'mac' | 
|  | if host_os.startswith('win'): | 
|  | return 'win' | 
|  | return host_os | 
|  |  | 
|  |  | 
|  | # Where string_map is formatted as X1=Y1,X2=Y2 etc. | 
|  | # If key is X1, returns Y1. | 
|  | def ParseStringMap(key, string_map): | 
|  | for m in string_map.split(','): | 
|  | l = m.split('=') | 
|  | if l[0] == key: | 
|  | return l[1] | 
|  | return None | 
|  |  | 
|  |  | 
|  | def UseSysroot(args, gn_args): | 
|  | # Don't try to use a Linux sysroot if we aren't on Linux. | 
|  | if gn_args['target_os'] != 'linux' and HOST_OS != 'linux': | 
|  | return False | 
|  | # Don't use the sysroot if we're given another sysroot. | 
|  | if TargetSysroot(args): | 
|  | return False | 
|  | # Don't use the sysroot if we're given another toolchain. | 
|  | if not gn_args['is_clang']: | 
|  | return False | 
|  | # Fuchsia's Linux sysroot doesn't support RISCV32 | 
|  | if gn_args['target_cpu'] in ['riscv32']: | 
|  | return False | 
|  | # Otherwise use the sysroot. | 
|  | return True | 
|  |  | 
|  |  | 
|  | def ToGnArgs(args, mode, arch, target_os, sanitizer, verify_sdk_hash, | 
|  | git_version): | 
|  | gn_args = {} | 
|  |  | 
|  | host_os = HostOsForGn(HOST_OS) | 
|  | if target_os == 'host': | 
|  | gn_args['target_os'] = host_os | 
|  | elif target_os == 'ios_simulator': | 
|  | gn_args['target_os'] = 'ios' | 
|  | gn_args['use_ios_simulator'] = True | 
|  | else: | 
|  | gn_args['target_os'] = target_os | 
|  |  | 
|  | gn_args['host_cpu'] = HostCpuForArch(arch) | 
|  | gn_args['target_cpu'] = TargetCpuForArch(arch) | 
|  | gn_args['dart_target_arch'] = DartTargetCpuForArch(arch) | 
|  | gn_args['dart_use_compressed_pointers'] = IsCompressedPointerArch(arch) | 
|  |  | 
|  | # Configure Crashpad library if it is used. | 
|  | gn_args['dart_use_crashpad'] = ((args.use_crashpad or | 
|  | DART_USE_CRASHPAD in os.environ) and | 
|  | gn_args['target_cpu'] in ['x86', 'x64']) | 
|  | if gn_args['dart_use_crashpad']: | 
|  | # Tell Crashpad's BUILD files which checkout layout to use. | 
|  | gn_args['crashpad_dependencies'] = 'dart' | 
|  |  | 
|  | if DartTargetCpuForArch(arch) != HostCpuForArch(arch): | 
|  | # Training an app-jit snapshot under a simulator is slow. Use script | 
|  | # snapshots instead. | 
|  | gn_args['dart_snapshot_kind'] = 'kernel' | 
|  | else: | 
|  | gn_args['dart_snapshot_kind'] = 'app-jit' | 
|  |  | 
|  | # We only want the fallback root certs in the standalone VM on | 
|  | # Linux and Windows. | 
|  | if gn_args['target_os'] in ['linux', 'win']: | 
|  | gn_args['dart_use_fallback_root_certificates'] = True | 
|  |  | 
|  | if gn_args['target_os'] == 'linux': | 
|  | if gn_args['target_cpu'] == 'arm': | 
|  | # Default to -mfloat-abi=hard and -mfpu=neon for arm on Linux as we're | 
|  | # specifying a gnueabihf compiler in //build/toolchain/linux/BUILD.gn. | 
|  | floatabi = 'hard' if args.arm_float_abi == '' else args.arm_float_abi | 
|  | gn_args['arm_version'] = 7 | 
|  | gn_args['arm_float_abi'] = floatabi | 
|  | gn_args['arm_use_neon'] = True | 
|  |  | 
|  | gn_args['is_debug'] = mode == 'debug' | 
|  | gn_args['is_release'] = mode == 'release' | 
|  | gn_args['is_product'] = mode == 'product' | 
|  | gn_args['dart_debug'] = mode == 'debug' | 
|  |  | 
|  | # This setting is only meaningful for Flutter. Standalone builds of the VM | 
|  | # should leave this set to 'develop', which causes the build to defer to | 
|  | # 'is_debug', 'is_release' and 'is_product'. | 
|  | if mode == 'product': | 
|  | gn_args['dart_runtime_mode'] = 'release' | 
|  | else: | 
|  | gn_args['dart_runtime_mode'] = 'develop' | 
|  |  | 
|  | gn_args['exclude_kernel_service'] = args.exclude_kernel_service | 
|  |  | 
|  | gn_args['is_clang'] = args.clang | 
|  |  | 
|  | enable_code_coverage = args.code_coverage and gn_args['is_clang'] | 
|  | gn_args['dart_vm_code_coverage'] = enable_code_coverage | 
|  |  | 
|  | gn_args['dart_dynamic_modules'] = args.dart_dynamic_modules | 
|  |  | 
|  | gn_args['is_asan'] = sanitizer == 'asan' | 
|  | gn_args['is_lsan'] = sanitizer == 'lsan' | 
|  | gn_args['is_msan'] = sanitizer == 'msan' | 
|  | gn_args['is_tsan'] = sanitizer == 'tsan' | 
|  | gn_args['is_ubsan'] = sanitizer == 'ubsan' | 
|  | gn_args['is_qemu'] = args.use_qemu | 
|  |  | 
|  | if not args.platform_sdk: | 
|  | gn_args['dart_platform_sdk'] = args.platform_sdk | 
|  |  | 
|  | # We don't support stripping on Windows | 
|  | if host_os != 'win': | 
|  | gn_args['dart_stripped_binary'] = 'exe.stripped/dart' | 
|  | gn_args['dart_aotruntime_stripped_binary'] = ( | 
|  | 'exe.stripped/dartaotruntime_product') | 
|  | gn_args['gen_snapshot_stripped_binary'] = ( | 
|  | 'exe.stripped/gen_snapshot_product') | 
|  | gn_args['analyze_snapshot_binary'] = ('exe.stripped/analyze_snapshot') | 
|  | gn_args['wasm_opt_stripped_binary'] = 'exe.stripped/wasm-opt' | 
|  |  | 
|  | # Setup the user-defined sysroot. | 
|  | if UseSysroot(args, gn_args): | 
|  | gn_args['dart_sysroot'] = 'debian' | 
|  | else: | 
|  | sysroot = TargetSysroot(args) | 
|  | if sysroot: | 
|  | gn_args['target_sysroot'] = ParseStringMap(arch, sysroot) | 
|  |  | 
|  | toolchain = ToolchainPrefix(args) | 
|  | if toolchain: | 
|  | for arch in ['ia32', 'x64', 'arm', 'arm64', 'riscv32', 'riscv64']: | 
|  | prefix = ParseStringMap(arch, toolchain) | 
|  | if prefix != None: | 
|  | gn_args[arch + '_toolchain_prefix'] = prefix | 
|  |  | 
|  | gn_args['use_rbe'] = args.rbe | 
|  |  | 
|  | if args.rbe_expensive_exec_strategy: | 
|  | gn_args[ | 
|  | 'rbe_expensive_exec_strategy'] = args.rbe_expensive_exec_strategy | 
|  |  | 
|  | # Code coverage requires -O0 to be set. | 
|  | if enable_code_coverage: | 
|  | gn_args['dart_debug_optimization_level'] = 0 | 
|  | gn_args['debug_optimization_level'] = 0 | 
|  | elif args.debug_opt_level: | 
|  | gn_args['dart_debug_optimization_level'] = args.debug_opt_level | 
|  | gn_args['debug_optimization_level'] = args.debug_opt_level | 
|  |  | 
|  | gn_args['verify_sdk_hash'] = verify_sdk_hash | 
|  | gn_args['dart_version_git_info'] = git_version | 
|  |  | 
|  | if args.codesigning_identity != '': | 
|  | gn_args['codesigning_identity'] = args.codesigning_identity | 
|  |  | 
|  | return gn_args | 
|  |  | 
|  |  | 
|  | def ProcessOsOption(os_name): | 
|  | if os_name == 'host': | 
|  | return HOST_OS | 
|  | return os_name | 
|  |  | 
|  |  | 
|  | def ProcessOptions(args): | 
|  | if args.verify_sdk_hash == None: | 
|  | args.verify_sdk_hash = not args.rbe | 
|  | if args.git_version == None: | 
|  | args.git_version = not args.rbe | 
|  | if args.arch == 'all': | 
|  | if platform.system() == 'Darwin': | 
|  | # Targeting 32 bits not supported on MacOS. | 
|  | # See HostArchitectures in utils.py. | 
|  | args.arch = 'x64,simarm64,x64c,simarm64c,simriscv64' | 
|  | else: | 
|  | args.arch = 'ia32,x64,simarm,simarm64,x64c,simarm64c,simriscv32,simriscv64' | 
|  | if args.mode == 'all': | 
|  | args.mode = 'debug,release,product' | 
|  | if args.os == 'all': | 
|  | args.os = 'host,android,fuchsia' | 
|  | if args.sanitizer == 'all': | 
|  | args.sanitizer = 'none,asan,lsan,msan,tsan,ubsan' | 
|  | args.mode = args.mode.split(',') | 
|  | args.arch = args.arch.split(',') | 
|  | args.os = args.os.split(',') | 
|  | args.sanitizer = args.sanitizer.split(',') | 
|  | for mode in args.mode: | 
|  | if not mode in ['debug', 'release', 'product']: | 
|  | print("Unknown mode %s" % mode) | 
|  | return False | 
|  | for i, arch in enumerate(args.arch): | 
|  | args.arch[i] = arch.lower() | 
|  | oses = [ProcessOsOption(os_name) for os_name in args.os] | 
|  | for os_name in oses: | 
|  | if not os_name in [ | 
|  | 'android', 'freebsd', 'linux', 'macos', 'win32', 'fuchsia', | 
|  | 'ios', 'ios_simulator' | 
|  | ]: | 
|  | print("Unknown os %s" % os_name) | 
|  | return False | 
|  | if os_name == 'android': | 
|  | if not HOST_OS in ['linux', 'macos']: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported on host os %s." % | 
|  | (os_name, HOST_OS)) | 
|  | return False | 
|  | if not arch in [ | 
|  | 'ia32', | 
|  | 'x64', | 
|  | 'arm', | 
|  | 'arm_x64', | 
|  | 'arm64', | 
|  | 'x64c', | 
|  | 'arm64c', | 
|  | 'riscv64', | 
|  | ]: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported for architecture %s." | 
|  | % (os_name, arch)) | 
|  | return False | 
|  | elif os_name == 'fuchsia': | 
|  | if not HOST_OS in ['linux', 'macos']: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported on host os %s." % | 
|  | (os_name, HOST_OS)) | 
|  | return False | 
|  | if not arch in ['x64', 'arm64', 'x64c', 'arm64c', 'riscv64']: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported for architecture %s." | 
|  | % (os_name, arch)) | 
|  | return False | 
|  | elif os_name == 'ios' or os_name == 'ios_simulator': | 
|  | if not HOST_OS in ['macos']: | 
|  | print(f'Target os {os_name} is only supported on macOS') | 
|  | return False | 
|  | elif os_name != HOST_OS: | 
|  | print("Unsupported target os %s" % os_name) | 
|  | return False | 
|  | if HOST_OS != 'win' and args.use_crashpad: | 
|  | print("Crashpad is only supported on Windows") | 
|  | return False | 
|  | if not args.rbe and \ | 
|  | (socket.getfqdn().endswith('.corp.google.com') or | 
|  | socket.getfqdn().endswith('.c.googlers.com')): | 
|  | print('You can speed up your build by following: go/dart-rbe') | 
|  | old_rbe_cfg = 'win-intel.cfg' if HOST_OS == 'win32' else 'linux-intel.cfg' | 
|  | new_rbe_cfg = 'windows.cfg' if HOST_OS == 'win32' else 'unix.cfg' | 
|  | if os.environ.get('RBE_cfg') == os.path.join(os.getcwd(), 'build', 'rbe', | 
|  | old_rbe_cfg): | 
|  | print(f'warning: {old_rbe_cfg} is deprecated, please update your ' | 
|  | f'RBE_cfg variable to {new_rbe_cfg} use RBE=1 instead per ' | 
|  | 'go/dart-rbe') | 
|  | return True | 
|  |  | 
|  |  | 
|  | def os_has_ide(host_os): | 
|  | return host_os.startswith('win') or host_os.startswith('mac') | 
|  |  | 
|  |  | 
|  | def ide_switch(host_os): | 
|  | if host_os.startswith('win'): | 
|  | return '--ide=vs' | 
|  | elif host_os.startswith('mac'): | 
|  | return '--ide=xcode' | 
|  | else: | 
|  | return '--ide=json' | 
|  |  | 
|  |  | 
|  | def AddCommonGnOptionArgs(parser): | 
|  | """Adds arguments that will change the default GN arguments.""" | 
|  |  | 
|  | parser.add_argument('--rbe', help='Use rbe', action='store_true') | 
|  | parser.add_argument('--no-rbe', | 
|  | help='Disable rbe', | 
|  | dest='rbe', | 
|  | action='store_false') | 
|  | parser.set_defaults(rbe=os.environ.get('RBE') == '1' or \ | 
|  | os.environ.get('DART_RBE') == '1' or \ | 
|  | os.environ.get('RBE_cfg') != None) | 
|  | parser.add_argument('--rbe-expensive-exec-strategy', | 
|  | default=os.environ.get('RBE_exec_strategy'), | 
|  | help='Strategy for expensive RBE compilations', | 
|  | type=str) | 
|  |  | 
|  | # Disable git hashes when remote compiling to ensure cache hits of the final | 
|  | # output artifacts when nothing has changed. | 
|  | parser.add_argument('--verify-sdk-hash', | 
|  | help='Enable SDK hash checks', | 
|  | dest='verify_sdk_hash', | 
|  | action='store_true') | 
|  | parser.add_argument('-nvh', | 
|  | '--no-verify-sdk-hash', | 
|  | help='Disable SDK hash checks', | 
|  | dest='verify_sdk_hash', | 
|  | action='store_false') | 
|  | parser.set_defaults(verify_sdk_hash=None) | 
|  |  | 
|  | parser.add_argument('--git-version', | 
|  | help='Enable git commit in version', | 
|  | dest='git_version', | 
|  | action='store_true') | 
|  | parser.add_argument('-ngv', | 
|  | '--no-git-version', | 
|  | help='Disable git commit in version', | 
|  | dest='git_version', | 
|  | action='store_false') | 
|  | parser.set_defaults(git_version=None) | 
|  |  | 
|  | parser.add_argument('--clang', help='Use Clang', action='store_true') | 
|  | parser.add_argument('--no-clang', | 
|  | help='Disable Clang', | 
|  | dest='clang', | 
|  | action='store_false') | 
|  | parser.set_defaults(clang=True) | 
|  |  | 
|  | parser.add_argument( | 
|  | '--platform-sdk', | 
|  | help='Directs the create_sdk target to create a smaller "Platform" SDK', | 
|  | default=MakePlatformSDK(), | 
|  | action='store_true') | 
|  | parser.add_argument('--use-crashpad', | 
|  | default=False, | 
|  | dest='use_crashpad', | 
|  | action='store_true') | 
|  | parser.add_argument('--use-qemu', | 
|  | default=False, | 
|  | dest='use_qemu', | 
|  | action='store_true') | 
|  | parser.add_argument('--exclude-kernel-service', | 
|  | help='Exclude the kernel service.', | 
|  | default=False, | 
|  | dest='exclude_kernel_service', | 
|  | action='store_true') | 
|  | parser.add_argument('--arm-float-abi', | 
|  | type=str, | 
|  | help='The ARM float ABI (soft, softfp, hard)', | 
|  | metavar='[soft,softfp,hard]', | 
|  | default='') | 
|  |  | 
|  | parser.add_argument('--code-coverage', | 
|  | help='Enable code coverage for the standalone VM', | 
|  | default=False, | 
|  | dest="code_coverage", | 
|  | action='store_true') | 
|  | parser.add_argument('--dart-dynamic-modules', | 
|  | help='Enable Dart dynamic modules.', | 
|  | default=False, | 
|  | dest='dart_dynamic_modules', | 
|  | action='store_true') | 
|  | parser.add_argument('--debug-opt-level', | 
|  | '-d', | 
|  | help='The optimization level to use for debug builds', | 
|  | type=str) | 
|  | parser.add_argument('--gn-args', | 
|  | help='Set extra GN args', | 
|  | dest='gn_args', | 
|  | action='append') | 
|  | parser.add_argument( | 
|  | '--toolchain-prefix', | 
|  | '-t', | 
|  | type=str, | 
|  | help='Comma-separated list of arch=/path/to/toolchain-prefix mappings') | 
|  | parser.add_argument('--ide', | 
|  | help='Generate an IDE file.', | 
|  | default=os_has_ide(HOST_OS), | 
|  | action='store_true') | 
|  | parser.add_argument('--export-compile-commands', | 
|  | help='Export compile_commands.json database file.', | 
|  | default=False, | 
|  | action='store_true') | 
|  | parser.add_argument( | 
|  | '--target-sysroot', | 
|  | '-s', | 
|  | type=str, | 
|  | help='Comma-separated list of arch=/path/to/sysroot mappings') | 
|  | parser.add_argument('--use-mallinfo2', | 
|  | help='Use mallinfo2 to collect malloc stats.', | 
|  | default=False, | 
|  | dest='use_mallinfo2', | 
|  | action='store_true') | 
|  | parser.add_argument('--codesigning-identity', | 
|  | help='Sign executables using the given identity.', | 
|  | default='', | 
|  | type=str) | 
|  |  | 
|  |  | 
|  | def AddCommonConfigurationArgs(parser): | 
|  | """Adds arguments that influence which configuration will be built.""" | 
|  | parser.add_argument("-a", | 
|  | "--arch", | 
|  | type=str, | 
|  | help='Target architectures (comma-separated).', | 
|  | metavar='[all,' + ','.join(AVAILABLE_ARCHS) + ']', | 
|  | default=utils.GuessArchitecture()) | 
|  | parser.add_argument('--mode', | 
|  | '-m', | 
|  | type=str, | 
|  | help='Build variants (comma-separated).', | 
|  | metavar='[all,debug,release,product]', | 
|  | default='debug') | 
|  | parser.add_argument('--os', | 
|  | type=str, | 
|  | help='Target OSs (comma-separated).', | 
|  | metavar='[all,host,android,fuchsia,ios,ios_simulator]', | 
|  | default='host') | 
|  | parser.add_argument('--sanitizer', | 
|  | type=str, | 
|  | help='Build variants (comma-separated).', | 
|  | metavar='[all,none,asan,lsan,msan,tsan,ubsan]', | 
|  | default='none') | 
|  |  | 
|  |  | 
|  | def AddOtherArgs(parser): | 
|  | """Adds miscellaneous arguments to the parser.""" | 
|  | parser.add_argument("-v", | 
|  | "--verbose", | 
|  | help='Verbose output.', | 
|  | default=False, | 
|  | action="store_true") | 
|  | parser.add_argument("--test", | 
|  | help='Test this script.', | 
|  | default=False, | 
|  | action="store_true") | 
|  |  | 
|  |  | 
|  | def parse_args(args): | 
|  | args = args[1:] | 
|  | parser = argparse.ArgumentParser( | 
|  | description='A script to run `gn gen`.', | 
|  | formatter_class=argparse.ArgumentDefaultsHelpFormatter) | 
|  |  | 
|  | config_group = parser.add_argument_group('Configuration Related Arguments') | 
|  | AddCommonConfigurationArgs(config_group) | 
|  |  | 
|  | gn_group = parser.add_argument_group('GN Related Arguments') | 
|  | AddCommonGnOptionArgs(gn_group) | 
|  |  | 
|  | other_group = parser.add_argument_group('Other Arguments') | 
|  | AddOtherArgs(other_group) | 
|  |  | 
|  | options = parser.parse_args(args) | 
|  | if not ProcessOptions(options): | 
|  | parser.print_help() | 
|  | return None | 
|  | return options | 
|  |  | 
|  |  | 
|  | def InitializeRBE(out_dir, env): | 
|  | RBE_cfg = 'RBE_CFG' if HOST_OS == 'win32' else 'RBE_cfg' | 
|  | RBE_server_address = ('RBE_SERVER_ADDRESS' | 
|  | if HOST_OS == 'win32' else 'RBE_server_address') | 
|  | # Default RBE_cfg to the appropriate configuration file. | 
|  | if not RBE_cfg in env: | 
|  | env[RBE_cfg] = os.path.join( | 
|  | os.getcwd(), 'build', 'rbe', | 
|  | 'windows.cfg' if HOST_OS == 'win32' else 'unix.cfg') | 
|  | # Default RBE_server_address to inside the build directory. | 
|  | if not RBE_server_address in env: | 
|  | with open(env[RBE_cfg], 'r') as f: | 
|  | if not any([l.startswith('server_address') for l in f.readlines()]): | 
|  | schema = 'pipe' if HOST_OS == 'win32' else 'unix' | 
|  | socket = os.path.join(os.getcwd(), out_dir, 'reproxy.sock') | 
|  | if HOST_OS == 'win32': | 
|  | socket = socket.replace('\\', '_').replace(':', '_') | 
|  | env[RBE_server_address] = f'{schema}://{socket}' | 
|  |  | 
|  |  | 
|  | def ExecutableName(basename): | 
|  | if utils.IsWindows(): | 
|  | return f'{basename}.exe' | 
|  | return basename | 
|  |  | 
|  |  | 
|  | def BuildGnCommand(args, mode, arch, target_os, sanitizer, out_dir): | 
|  | if utils.IsWindows(): | 
|  | gn = os.path.join(DART_ROOT, 'buildtools', 'win', 'gn.exe') | 
|  | else: | 
|  | gn = os.path.join(DART_ROOT, 'buildtools', 'gn') | 
|  | if not os.path.isfile(gn): | 
|  | raise Exception("Couldn't find the gn binary at path: " + gn) | 
|  |  | 
|  | # TODO(infra): Re-enable --check. Many targets fail to use | 
|  | # public_deps to re-expose header files to their dependents. | 
|  | # See dartbug.com/32364 | 
|  | command = [gn, 'gen', out_dir] | 
|  | gn_args = ToCommandLine( | 
|  | ToGnArgs(args, mode, arch, target_os, sanitizer, args.verify_sdk_hash, | 
|  | args.git_version)) | 
|  | gn_args += GetGNArgs(args) | 
|  | if args.ide: | 
|  | command.append(ide_switch(HOST_OS)) | 
|  | if args.export_compile_commands: | 
|  | command.append('--export-compile-commands') | 
|  | command.append('--args=%s' % ' '.join(gn_args)) | 
|  |  | 
|  | return command | 
|  |  | 
|  |  | 
|  | def RunGnOnConfiguredConfigurations(args, env={}): | 
|  | initialized_rbe = False | 
|  | commands = [] | 
|  | for target_os in args.os: | 
|  | for mode in args.mode: | 
|  | for arch in args.arch: | 
|  | for sanitizer in args.sanitizer: | 
|  | out_dir = GetOutDir(mode, arch, target_os, sanitizer) | 
|  | if args.rbe and not initialized_rbe: | 
|  | InitializeRBE(out_dir, env) | 
|  | initialized_rbe = True | 
|  | commands.append( | 
|  | BuildGnCommand(args, mode, arch, target_os, sanitizer, | 
|  | out_dir)) | 
|  | if args.verbose: | 
|  | print("gn gen --check in %s" % out_dir) | 
|  |  | 
|  | active_commands = [] | 
|  |  | 
|  | def cleanup(command): | 
|  | print("Command failed: " + ' '.join(command)) | 
|  | for (_, process) in active_commands: | 
|  | process.terminate() | 
|  |  | 
|  | for command in commands: | 
|  | try: | 
|  | process = subprocess.Popen(command, cwd=DART_ROOT, env=env) | 
|  | active_commands.append([command, process]) | 
|  | except Exception as e: | 
|  | print('Error: %s' % e) | 
|  | cleanup(command) | 
|  | return 1 | 
|  | while active_commands: | 
|  | time.sleep(0.1) | 
|  | for active_command in active_commands: | 
|  | (command, process) = active_command | 
|  | if process.poll() is not None: | 
|  | active_commands.remove(active_command) | 
|  | if process.returncode != 0: | 
|  | cleanup(command) | 
|  | return 1 | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | def ExpectEquals(actual, expected): | 
|  | if actual != expected: | 
|  | raise Exception(f"Actual: {actual} Expected: {expected}") | 
|  |  | 
|  |  | 
|  | def RunTests(): | 
|  | host_arch = utils.HostArchitectures()[0] | 
|  | host_arch_or_x64 = host_arch | 
|  | if 'x64' in utils.HostArchitectures(): | 
|  | # Rosetta means 'x64' may be built directly. | 
|  | host_arch_or_x64 = 'x64' | 
|  |  | 
|  | ExpectEquals(HostCpuForArch("arm64"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("arm64c"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("simarm64"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("simarm64_x64"), host_arch_or_x64) | 
|  | ExpectEquals(HostCpuForArch("simarm64_arm64"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("simarm64_riscv64"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("x64"), host_arch_or_x64) | 
|  | ExpectEquals(HostCpuForArch("simx64"), host_arch_or_x64) | 
|  | ExpectEquals(HostCpuForArch("simx64_x64"), host_arch_or_x64) | 
|  | ExpectEquals(HostCpuForArch("simx64_arm64"), host_arch) | 
|  | ExpectEquals(HostCpuForArch("simx64_riscv64"), host_arch) | 
|  |  | 
|  | ExpectEquals(TargetCpuForArch("arm64"), "arm64") | 
|  | ExpectEquals(TargetCpuForArch("arm64c"), "arm64") | 
|  | ExpectEquals(TargetCpuForArch("simarm64"), host_arch) | 
|  | ExpectEquals(TargetCpuForArch("simarm64_x64"), "x64") | 
|  | ExpectEquals(TargetCpuForArch("simarm64_arm64"), "arm64") | 
|  | ExpectEquals(TargetCpuForArch("simarm64_riscv64"), "riscv64") | 
|  | ExpectEquals(TargetCpuForArch("x64"), "x64") | 
|  | ExpectEquals(TargetCpuForArch("simx64"), host_arch) | 
|  | ExpectEquals(TargetCpuForArch("simx64_x64"), "x64") | 
|  | ExpectEquals(TargetCpuForArch("simx64_arm64"), "arm64") | 
|  | ExpectEquals(TargetCpuForArch("simx64_riscv64"), "riscv64") | 
|  |  | 
|  | ExpectEquals(DartTargetCpuForArch("arm64"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("arm64c"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("simarm64"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("simarm64_x64"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("simarm64_arm64"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("simarm64_riscv64"), "arm64") | 
|  | ExpectEquals(DartTargetCpuForArch("x64"), "x64") | 
|  | ExpectEquals(DartTargetCpuForArch("simx64"), "x64") | 
|  | ExpectEquals(DartTargetCpuForArch("simx64_x64"), "x64") | 
|  | ExpectEquals(DartTargetCpuForArch("simx64_arm64"), "x64") | 
|  | ExpectEquals(DartTargetCpuForArch("simx64_riscv64"), "x64") | 
|  |  | 
|  | ExpectEquals(IsCompressedPointerArch("arm64c"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("simarm64c"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("simarm64c_x64"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("x64c"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("simx64c"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("simx64c_x64"), True) | 
|  | ExpectEquals(IsCompressedPointerArch("arm64"), False) | 
|  | ExpectEquals(IsCompressedPointerArch("simarm64"), False) | 
|  | ExpectEquals(IsCompressedPointerArch("simarm64_x64"), False) | 
|  | ExpectEquals(IsCompressedPointerArch("x64"), False) | 
|  | ExpectEquals(IsCompressedPointerArch("simx64"), False) | 
|  | ExpectEquals(IsCompressedPointerArch("simx64_x64"), False) | 
|  |  | 
|  | # Our Android bots: | 
|  | ExpectEquals(HostCpuForArch("arm64c"), host_arch) | 
|  | ExpectEquals(TargetCpuForArch("arm64c"), 'arm64') | 
|  | ExpectEquals(DartTargetCpuForArch("arm64c"), 'arm64') | 
|  | ExpectEquals(HostCpuForArch("arm_x64"), host_arch_or_x64) | 
|  | ExpectEquals(TargetCpuForArch("arm_x64"), 'arm') | 
|  | ExpectEquals(DartTargetCpuForArch("arm_x64"), 'arm') | 
|  |  | 
|  |  | 
|  | def Main(argv): | 
|  | starttime = time.time() | 
|  |  | 
|  | args = parse_args(argv) | 
|  | if args is None: | 
|  | return 1 | 
|  |  | 
|  | if args.test: | 
|  | RunTests() | 
|  | print("Tests passed.") | 
|  | return 0 | 
|  |  | 
|  | result = RunGnOnConfiguredConfigurations(args) | 
|  |  | 
|  | if args.verbose: | 
|  | endtime = time.time() | 
|  | print("GN Time: %.3f seconds" % (endtime - starttime)) | 
|  |  | 
|  | return result | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(Main(sys.argv)) |