OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The Dart project authors. All rights reserved. | 2 # Copyright 2016 The Dart project authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import argparse | 6 import argparse |
| 7 import multiprocessing |
| 8 import os |
7 import subprocess | 9 import subprocess |
8 import sys | 10 import sys |
9 import os | 11 import time |
10 import utils | 12 import utils |
11 | 13 |
12 HOST_OS = utils.GuessOS() | 14 HOST_OS = utils.GuessOS() |
13 HOST_ARCH = utils.GuessArchitecture() | 15 HOST_ARCH = utils.GuessArchitecture() |
14 HOST_CPUS = utils.GuessCpus() | |
15 SCRIPT_DIR = os.path.dirname(sys.argv[0]) | 16 SCRIPT_DIR = os.path.dirname(sys.argv[0]) |
16 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) | 17 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) |
17 | 18 |
18 def get_out_dir(args): | 19 |
19 return utils.GetBuildRoot(HOST_OS, args.mode, args.arch, args.os) | 20 def get_out_dir(mode, arch, target_os): |
| 21 return utils.GetBuildRoot(HOST_OS, mode, arch, target_os) |
| 22 |
20 | 23 |
21 def to_command_line(gn_args): | 24 def to_command_line(gn_args): |
22 def merge(key, value): | 25 def merge(key, value): |
23 if type(value) is bool: | 26 if type(value) is bool: |
24 return '%s=%s' % (key, 'true' if value else 'false') | 27 return '%s=%s' % (key, 'true' if value else 'false') |
25 return '%s="%s"' % (key, value) | 28 return '%s="%s"' % (key, value) |
26 return [merge(x, y) for x, y in gn_args.iteritems()] | 29 return [merge(x, y) for x, y in gn_args.iteritems()] |
27 | 30 |
| 31 |
28 def host_cpu_for_arch(arch): | 32 def host_cpu_for_arch(arch): |
29 if arch in ['ia32', 'arm', 'armv6', 'armv5te', 'mips', | 33 if arch in ['ia32', 'arm', 'armv6', 'armv5te', 'mips', |
30 'simarm', 'simarmv6', 'simarmv5te', 'simmips', 'simdbc']: | 34 'simarm', 'simarmv6', 'simarmv5te', 'simmips', 'simdbc']: |
31 return 'x86' | 35 return 'x86' |
32 if arch in ['x64', 'arm64', 'simarm64', 'simdbc64']: | 36 if arch in ['x64', 'arm64', 'simarm64', 'simdbc64']: |
33 return 'x64' | 37 return 'x64' |
34 | 38 |
35 def target_cpu_for_arch(arch, os): | 39 |
| 40 def target_cpu_for_arch(arch, target_os): |
36 if arch in ['ia32', 'simarm', 'simarmv6', 'simarmv5te', 'simmips']: | 41 if arch in ['ia32', 'simarm', 'simarmv6', 'simarmv5te', 'simmips']: |
37 return 'x86' | 42 return 'x86' |
38 if arch in ['simarm64']: | 43 if arch in ['simarm64']: |
39 return 'x64' | 44 return 'x64' |
40 if arch == 'mips': | 45 if arch == 'mips': |
41 return 'mipsel' | 46 return 'mipsel' |
42 if arch == 'simdbc': | 47 if arch == 'simdbc': |
43 return 'arm' if os == 'android' else 'x86' | 48 return 'arm' if target_os == 'android' else 'x86' |
44 if arch == 'simdbc64': | 49 if arch == 'simdbc64': |
45 return 'arm64' if os == 'android' else 'x64' | 50 return 'arm64' if target_os == 'android' else 'x64' |
46 return arch | 51 return arch |
47 | 52 |
48 def host_os_for_gn(os): | 53 |
49 if os.startswith('macos'): | 54 def host_os_for_gn(host_os): |
| 55 if host_os.startswith('macos'): |
50 return 'mac' | 56 return 'mac' |
51 if os.startswith('win'): | 57 if host_os.startswith('win'): |
52 return 'win' | 58 return 'win' |
53 return os | 59 return host_os |
54 | 60 |
55 def to_gn_args(args): | 61 |
| 62 def to_gn_args(args, mode, arch, target_os): |
56 gn_args = {} | 63 gn_args = {} |
57 | 64 |
58 host_os = host_os_for_gn(HOST_OS) | 65 host_os = host_os_for_gn(HOST_OS) |
59 if args.os == 'host': | 66 if target_os == 'host': |
60 gn_args['target_os'] = host_os | 67 gn_args['target_os'] = host_os |
61 else: | 68 else: |
62 gn_args['target_os'] = args.os | 69 gn_args['target_os'] = target_os |
63 | 70 |
64 gn_args['dart_target_arch'] = args.arch | 71 gn_args['dart_target_arch'] = arch |
65 gn_args['target_cpu'] = target_cpu_for_arch(args.arch, args.os) | 72 gn_args['target_cpu'] = target_cpu_for_arch(arch, target_os) |
66 gn_args['host_cpu'] = host_cpu_for_arch(args.arch) | 73 gn_args['host_cpu'] = host_cpu_for_arch(arch) |
67 | 74 |
68 # TODO(zra): This is for the observatory, which currently builds using the | 75 # TODO(zra): This is for the observatory, which currently builds using the |
69 # checked-in sdk. If/when the observatory no longer builds with the | 76 # checked-in sdk. If/when the observatory no longer builds with the |
70 # checked-in sdk, this can be removed. | 77 # checked-in sdk, this can be removed. |
71 pub = 'pub' | 78 pub = 'pub' |
72 if host_os == 'win': | 79 if host_os == 'win': |
73 pub = pub + ".bat" | 80 pub = pub + ".bat" |
74 gn_args['dart_host_pub_exe'] = os.path.join( | 81 gn_args['dart_host_pub_exe'] = os.path.join( |
75 DART_ROOT, 'tools', 'sdks', host_os, 'dart-sdk', 'bin', pub) | 82 DART_ROOT, 'tools', 'sdks', host_os, 'dart-sdk', 'bin', pub) |
76 | 83 |
77 # For Fuchsia support, the default is to not compile in the root | 84 # For Fuchsia support, the default is to not compile in the root |
78 # certificates. | 85 # certificates. |
79 gn_args['dart_use_fallback_root_certificates'] = True | 86 gn_args['dart_use_fallback_root_certificates'] = True |
80 | 87 |
81 gn_args['dart_zlib_path'] = "//runtime/bin/zlib" | 88 gn_args['dart_zlib_path'] = "//runtime/bin/zlib" |
82 | 89 |
83 gn_args['dart_use_tcmalloc'] = gn_args['target_os'] == 'linux' | 90 gn_args['dart_use_tcmalloc'] = gn_args['target_os'] == 'linux' |
84 | 91 |
85 gn_args['is_debug'] = args.mode == 'debug' | 92 gn_args['is_debug'] = mode == 'debug' |
86 gn_args['is_release'] = args.mode == 'release' | 93 gn_args['is_release'] = mode == 'release' |
87 gn_args['is_product'] = args.mode == 'product' | 94 gn_args['is_product'] = mode == 'product' |
88 gn_args['dart_debug'] = args.mode == 'debug' | 95 gn_args['dart_debug'] = mode == 'debug' |
89 | 96 |
90 # This setting is only meaningful for Flutter. Standalone builds of the VM | 97 # This setting is only meaningful for Flutter. Standalone builds of the VM |
91 # should leave this set to 'develop', which causes the build to defer to | 98 # should leave this set to 'develop', which causes the build to defer to |
92 # 'is_debug', 'is_release' and 'is_product'. | 99 # 'is_debug', 'is_release' and 'is_product'. |
93 gn_args['dart_runtime_mode'] = 'develop' | 100 gn_args['dart_runtime_mode'] = 'develop' |
94 | 101 |
95 if host_os == 'win': | 102 if host_os == 'win': |
96 gn_args['is_clang'] = False | 103 gn_args['is_clang'] = False |
97 else: | 104 else: |
98 gn_args['is_clang'] = args.clang and args.os not in ['android'] | 105 gn_args['is_clang'] = args.clang and args.os not in ['android'] |
(...skipping 11 matching lines...) Expand all Loading... |
110 gn_args['goma_dir'] = goma_dir | 117 gn_args['goma_dir'] = goma_dir |
111 elif args.goma and os.path.exists(goma_home_dir): | 118 elif args.goma and os.path.exists(goma_home_dir): |
112 gn_args['use_goma'] = True | 119 gn_args['use_goma'] = True |
113 gn_args['goma_dir'] = goma_home_dir | 120 gn_args['goma_dir'] = goma_home_dir |
114 else: | 121 else: |
115 gn_args['use_goma'] = False | 122 gn_args['use_goma'] = False |
116 gn_args['goma_dir'] = None | 123 gn_args['goma_dir'] = None |
117 | 124 |
118 return gn_args | 125 return gn_args |
119 | 126 |
| 127 |
| 128 def process_os_option(os_name): |
| 129 if os_name == 'host': |
| 130 return HOST_OS |
| 131 return os_name |
| 132 |
| 133 |
| 134 def process_options(args): |
| 135 if args.arch == 'all': |
| 136 args.arch = 'ia32,x64,simarm,simarm64,simmips,simdbc64' |
| 137 if args.mode == 'all': |
| 138 args.mode = 'debug,release,product' |
| 139 if args.os == 'all': |
| 140 args.os = 'host,android' |
| 141 args.mode = args.mode.split(',') |
| 142 args.arch = args.arch.split(',') |
| 143 args.os = args.os.split(',') |
| 144 for mode in args.mode: |
| 145 if not mode in ['debug', 'release', 'product']: |
| 146 print "Unknown mode %s" % mode |
| 147 return False |
| 148 for arch in args.arch: |
| 149 archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6', |
| 150 'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64', |
| 151 'simdbc', 'simdbc64', 'armsimdbc'] |
| 152 if not arch in archs: |
| 153 print "Unknown arch %s" % arch |
| 154 return False |
| 155 oses = [process_os_option(os_name) for os_name in args.os] |
| 156 for os_name in oses: |
| 157 if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']: |
| 158 print "Unknown os %s" % os_name |
| 159 return False |
| 160 if os_name != HOST_OS: |
| 161 if os_name != 'android': |
| 162 print "Unsupported target os %s" % os_name |
| 163 return False |
| 164 if not HOST_OS in ['linux']: |
| 165 print ("Cross-compilation to %s is not supported on host os %s." |
| 166 % (os_name, HOST_OS)) |
| 167 return False |
| 168 if not arch in ['ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64', 'mips', |
| 169 'simdbc', 'simdbc64']: |
| 170 print ("Cross-compilation to %s is not supported for architecture %s." |
| 171 % (os_name, arch)) |
| 172 return False |
| 173 return True |
| 174 |
| 175 |
120 def parse_args(args): | 176 def parse_args(args): |
121 args = args[1:] | 177 args = args[1:] |
122 parser = argparse.ArgumentParser(description='A script run` gn gen`.') | 178 parser = argparse.ArgumentParser(description='A script to run `gn gen`.') |
123 | 179 |
| 180 parser.add_argument("-v", "--verbose", |
| 181 help='Verbose output.', |
| 182 default=False, action="store_true") |
124 parser.add_argument('--mode', '-m', | 183 parser.add_argument('--mode', '-m', |
125 type=str, | 184 type=str, |
126 choices=['debug', 'release', 'product'], | 185 help='Build variants (comma-separated).', |
| 186 metavar='[all,debug,release,product]', |
127 default='debug') | 187 default='debug') |
128 parser.add_argument('--os', | 188 parser.add_argument('--os', |
129 type=str, | 189 type=str, |
130 choices=['host', 'android'], | 190 help='Target OSs (comma-separated).', |
| 191 metavar='[all,host,android]', |
131 default='host') | 192 default='host') |
132 parser.add_argument('--arch', '-a', | 193 parser.add_argument('--arch', '-a', |
133 type=str, | 194 type=str, |
134 choices=['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6', | 195 help='Target architectures (comma-separated).', |
135 'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64', | 196 metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,' |
136 'simdbc', 'simdbc64'], | 197 'simmips,mips,simarm64,arm64,simdbc,armsimdbc]', |
137 default='x64') | 198 default='x64') |
| 199 parser.add_argument('--goma', |
| 200 help='Use goma', |
| 201 default=True, |
| 202 action='store_true') |
| 203 parser.add_argument('--no-goma', |
| 204 help='Disable goma', |
| 205 dest='goma', |
| 206 action='store_false') |
| 207 parser.add_argument('--clang', |
| 208 help='Use Clang', |
| 209 default=True, |
| 210 action='store_true') |
| 211 parser.add_argument('--no-clang', |
| 212 help='Disable Clang', |
| 213 dest='clang', |
| 214 action='store_false') |
| 215 parser.add_argument('--target-sysroot', '-s', |
| 216 type=str, |
| 217 help='Path to the toolchain sysroot') |
| 218 parser.add_argument('--toolchain-prefix', '-t', |
| 219 type=str, |
| 220 help='Path to the toolchain prefix') |
| 221 parser.add_argument('--workers', '-w', |
| 222 type=int, |
| 223 help='Number of simultaneous GN invocations', |
| 224 dest='workers', |
| 225 default=multiprocessing.cpu_count()) |
138 | 226 |
139 parser.add_argument('--goma', default=True, action='store_true') | 227 options = parser.parse_args(args) |
140 parser.add_argument('--no-goma', dest='goma', action='store_false') | 228 if not process_options(options): |
| 229 parser.print_help() |
| 230 return None |
| 231 return options |
141 | 232 |
142 parser.add_argument('--clang', default=True, action='store_true') | |
143 parser.add_argument('--no-clang', dest='clang', action='store_false') | |
144 | 233 |
145 parser.add_argument('--target-sysroot', '-s', type=str) | 234 def run_command(command): |
146 parser.add_argument('--toolchain-prefix', '-t', type=str) | 235 try: |
| 236 subprocess.check_output( |
| 237 command, cwd=DART_ROOT, stderr=subprocess.STDOUT) |
| 238 return 0 |
| 239 except subprocess.CalledProcessError as e: |
| 240 return ("Command failed: " + ' '.join(command) + "\n" + |
| 241 "output: " + e.output) |
147 | 242 |
148 return parser.parse_args(args) | |
149 | 243 |
150 def main(argv): | 244 def main(argv): |
| 245 starttime = time.time() |
151 args = parse_args(argv) | 246 args = parse_args(argv) |
152 | 247 |
153 if sys.platform.startswith(('cygwin', 'win')): | 248 if sys.platform.startswith(('cygwin', 'win')): |
154 subdir = 'win' | 249 subdir = 'win' |
155 elif sys.platform == 'darwin': | 250 elif sys.platform == 'darwin': |
156 subdir = 'mac' | 251 subdir = 'mac' |
157 elif sys.platform.startswith('linux'): | 252 elif sys.platform.startswith('linux'): |
158 subdir = 'linux64' | 253 subdir = 'linux64' |
159 else: | 254 else: |
160 raise Error('Unknown platform: ' + sys.platform) | 255 print 'Unknown platform: ' + sys.platform |
| 256 return 1 |
161 | 257 |
162 command = [ | 258 commands = [] |
163 '%s/buildtools/%s/gn' % (DART_ROOT, subdir), | 259 for target_os in args.os: |
164 'gen', | 260 for mode in args.mode: |
165 '--check' | 261 for arch in args.arch: |
166 ] | 262 command = [ |
167 gn_args = to_command_line(to_gn_args(args)) | 263 '%s/buildtools/%s/gn' % (DART_ROOT, subdir), |
168 out_dir = get_out_dir(args) | 264 'gen', |
169 print "gn gen --check in %s" % out_dir | 265 '--check' |
170 command.append(out_dir) | 266 ] |
171 command.append('--args=%s' % ' '.join(gn_args)) | 267 gn_args = to_command_line(to_gn_args(args, mode, arch, target_os)) |
172 return subprocess.call(command, cwd=DART_ROOT) | 268 out_dir = get_out_dir(mode, arch, target_os) |
| 269 if args.verbose: |
| 270 print "gn gen --check in %s" % out_dir |
| 271 command.append(out_dir) |
| 272 command.append('--args=%s' % ' '.join(gn_args)) |
| 273 commands.append(command) |
| 274 |
| 275 pool = multiprocessing.Pool(args.workers) |
| 276 results = pool.map(run_command, commands, chunksize=1) |
| 277 for r in results: |
| 278 if r != 0: |
| 279 print r.strip() |
| 280 return 1 |
| 281 |
| 282 endtime = time.time() |
| 283 if args.verbose: |
| 284 print "GN Time: " + str(endtime - starttime) + " seconds" |
| 285 return 0 |
| 286 |
173 | 287 |
174 if __name__ == '__main__': | 288 if __name__ == '__main__': |
175 sys.exit(main(sys.argv)) | 289 sys.exit(main(sys.argv)) |
OLD | NEW |