|  | #!/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 subprocess | 
|  | 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() | 
|  | GN = os.path.join(DART_ROOT, 'buildtools', 'gn') | 
|  |  | 
|  | # Environment variables for default settings. | 
|  | DART_USE_TOOLCHAIN = "DART_USE_TOOLCHAIN"  # Use instread 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()] | 
|  |  | 
|  |  | 
|  | def HostCpuForArch(arch): | 
|  | if arch in ['ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64']: | 
|  | return 'x86' | 
|  | if arch in [ | 
|  | 'x64', 'arm64', 'simarm64', 'arm_x64', 'x64c', 'arm64c', 'simarm64c' | 
|  | ]: | 
|  | return 'x64' | 
|  |  | 
|  |  | 
|  | # The C compiler's target. | 
|  | def TargetCpuForArch(arch, target_os): | 
|  | if arch in ['ia32', 'simarm', 'simarmv6']: | 
|  | return 'x86' | 
|  | if arch in ['x64', 'simarm64', 'simarm_x64', 'x64c', 'simarm64c']: | 
|  | return 'x64' | 
|  | if arch == 'arm_x64': | 
|  | return 'arm' | 
|  | if arch == 'arm64c': | 
|  | return 'arm64' | 
|  | return arch | 
|  |  | 
|  |  | 
|  | # The Dart compiler's target. | 
|  | def DartTargetCpuForArch(arch): | 
|  | if arch in ['ia32']: | 
|  | return 'ia32' | 
|  | if arch in ['x64', 'x64c']: | 
|  | return 'x64' | 
|  | if arch in ['arm', 'simarm', 'simarm_x64', 'arm_x64']: | 
|  | return 'arm' | 
|  | if arch in ['armv6', 'simarmv6']: | 
|  | return 'armv6' | 
|  | if arch in ['arm64', 'simarm64', 'arm64c', 'simarm64c']: | 
|  | return 'arm64' | 
|  | return arch | 
|  |  | 
|  |  | 
|  | def IsCompressedPointerArch(arch): | 
|  | return arch in ['x64c', 'arm64c', 'simarm64c'] | 
|  |  | 
|  |  | 
|  | 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 | 
|  | # Our Debian Jesse sysroot doesn't work with GCC 9 | 
|  | if not gn_args['is_clang']: | 
|  | return False | 
|  | # Our Debian Jesse sysroot has incorrect annotations on realloc. | 
|  | if gn_args['is_ubsan']: | 
|  | return False | 
|  | # Otherwise use the sysroot. | 
|  | return True | 
|  |  | 
|  |  | 
|  | def ToGnArgs(args, mode, arch, target_os, sanitizer, verify_sdk_hash): | 
|  | gn_args = {} | 
|  |  | 
|  | host_os = HostOsForGn(HOST_OS) | 
|  | if target_os == 'host': | 
|  | gn_args['target_os'] = host_os | 
|  | else: | 
|  | gn_args['target_os'] = target_os | 
|  |  | 
|  | gn_args['host_cpu'] = HostCpuForArch(arch) | 
|  | gn_args['target_cpu'] = TargetCpuForArch(arch, target_os) | 
|  | 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) | 
|  | 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 | 
|  |  | 
|  | gn_args['bssl_use_clang_integrated_as'] = True | 
|  |  | 
|  | # Use tcmalloc only when targeting Linux and when not using ASAN. | 
|  | gn_args['dart_use_tcmalloc'] = ((gn_args['target_os'] == 'linux') and | 
|  | sanitizer == 'none') | 
|  |  | 
|  | 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 | 
|  | elif gn_args['target_cpu'] == 'armv6': | 
|  | floatabi = 'softfp' if args.arm_float_abi == '' else args.arm_float_abi | 
|  | gn_args['target_cpu'] = 'arm' | 
|  | gn_args['arm_version'] = 6 | 
|  | gn_args['arm_float_abi'] = floatabi | 
|  |  | 
|  | 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['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_precompiled_runtime_stripped_binary'] = ( | 
|  | 'exe.stripped/dart_precompiled_runtime_product') | 
|  | gn_args['gen_snapshot_stripped_binary'] = ( | 
|  | 'exe.stripped/gen_snapshot_product') | 
|  |  | 
|  | # Setup the user-defined sysroot. | 
|  | if UseSysroot(args, gn_args): | 
|  | gn_args['dart_use_debian_sysroot'] = True | 
|  | else: | 
|  | sysroot = TargetSysroot(args) | 
|  | if sysroot: | 
|  | gn_args['target_sysroot'] = ParseStringMap(arch, sysroot) | 
|  |  | 
|  | toolchain = ToolchainPrefix(args) | 
|  | if toolchain: | 
|  | gn_args['toolchain_prefix'] = ParseStringMap(arch, toolchain) | 
|  |  | 
|  | goma_dir = os.environ.get('GOMA_DIR') | 
|  | # Search for goma in depot_tools in path | 
|  | goma_depot_tools_dir = None | 
|  | for path in os.environ.get('PATH', '').split(os.pathsep): | 
|  | if os.path.basename(path) == 'depot_tools': | 
|  | cipd_bin = os.path.join(path, '.cipd_bin') | 
|  | if os.path.isfile(os.path.join(cipd_bin, 'gomacc')): | 
|  | goma_depot_tools_dir = cipd_bin | 
|  | break | 
|  | # Otherwise use goma from home directory. | 
|  | # TODO(whesse): Remove support for goma installed in home directory. | 
|  | # Goma will only be distributed through depot_tools. | 
|  | 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 goma_depot_tools_dir: | 
|  | gn_args['use_goma'] = True | 
|  | gn_args['goma_dir'] = goma_depot_tools_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 gn_args['target_os'] == 'mac' and gn_args['use_goma']: | 
|  | gn_args['mac_use_goma_rbe'] = True | 
|  |  | 
|  | # 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 | 
|  |  | 
|  | return gn_args | 
|  |  | 
|  |  | 
|  | def ProcessOsOption(os_name): | 
|  | if os_name == 'host': | 
|  | return HOST_OS | 
|  | return os_name | 
|  |  | 
|  |  | 
|  | def ProcessOptions(args): | 
|  | if args.arch == 'all': | 
|  | args.arch = 'ia32,x64,simarm,simarm64,x64c,simarm64c' | 
|  | 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): | 
|  | if not arch in AVAILABLE_ARCHS: | 
|  | # Normalise to lower case form to make it less case-picky. | 
|  | arch_lower = arch.lower() | 
|  | if arch_lower in AVAILABLE_ARCHS: | 
|  | args.arch[i] = arch_lower | 
|  | continue | 
|  | print("Unknown arch %s" % arch) | 
|  | return False | 
|  | 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' | 
|  | ]: | 
|  | 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', 'armv6', 'arm64', 'x64c', | 
|  | 'arm64c' | 
|  | ]: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported for architecture %s." | 
|  | % (os_name, arch)) | 
|  | return False | 
|  | elif os_name == 'fuchsia': | 
|  | if HOST_OS != 'linux': | 
|  | 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']: | 
|  | print( | 
|  | "Cross-compilation to %s is not supported for architecture %s." | 
|  | % (os_name, arch)) | 
|  | 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 | 
|  | 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('--goma', help='Use goma', action='store_true') | 
|  | parser.add_argument('--no-goma', | 
|  | help='Disable goma', | 
|  | dest='goma', | 
|  | action='store_false') | 
|  | parser.set_defaults(goma=True) | 
|  |  | 
|  | parser.add_argument('--verify-sdk-hash', | 
|  | help='Enable SDK hash checks (default)', | 
|  | 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=True) | 
|  |  | 
|  | 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('--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') | 
|  |  | 
|  |  | 
|  | 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]', | 
|  | 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") | 
|  |  | 
|  |  | 
|  | 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 BuildGnCommand(args, mode, arch, target_os, sanitizer, out_dir): | 
|  | gn = os.path.join(DART_ROOT, 'buildtools', | 
|  | 'gn.exe' if utils.IsWindows() else '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)) | 
|  | 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): | 
|  | 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) | 
|  | 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) | 
|  | 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 Main(argv): | 
|  | starttime = time.time() | 
|  |  | 
|  | args = parse_args(argv) | 
|  | if args is None: | 
|  | return 1 | 
|  |  | 
|  | 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)) |