OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
6 # | 6 # |
7 | 7 |
8 import optparse | 8 import optparse |
9 import os | 9 import os |
10 import shutil | 10 import shutil |
11 import subprocess | 11 import subprocess |
12 import sys | 12 import sys |
13 import utils | 13 import utils |
14 | 14 |
15 HOST_OS = utils.GuessOS() | 15 HOST_OS = utils.GuessOS() |
16 HOST_CPUS = utils.GuessCpus() | 16 HOST_CPUS = utils.GuessCpus() |
17 armcompilerlocation = '/opt/codesourcery/arm-2009q1' | 17 armcompilerlocation = '/opt/codesourcery/arm-2009q1' |
| 18 SCRIPT_DIR = os.path.dirname(sys.argv[0]) |
| 19 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) |
| 20 THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party') |
18 | 21 |
19 def BuildOptions(): | 22 def BuildOptions(): |
20 result = optparse.OptionParser() | 23 result = optparse.OptionParser() |
21 result.add_option("-m", "--mode", | 24 result.add_option("-m", "--mode", |
22 help='Build variants (comma-separated).', | 25 help='Build variants (comma-separated).', |
23 metavar='[all,debug,release]', | 26 metavar='[all,debug,release]', |
24 default='debug') | 27 default='debug') |
25 result.add_option("-v", "--verbose", | 28 result.add_option("-v", "--verbose", |
26 help='Verbose output.', | 29 help='Verbose output.', |
27 default=False, action="store_true") | 30 default=False, action="store_true") |
28 result.add_option("--arch", | 31 result.add_option("--arch", |
29 help='Target architectures (comma-separated).', | 32 help='Target architectures (comma-separated).', |
30 metavar='[all,ia32,x64,simarm,arm]', | 33 metavar='[all,ia32,x64,simarm,arm]', |
31 default=utils.GuessArchitecture()) | 34 default=utils.GuessArchitecture()) |
| 35 result.add_option("--os", |
| 36 help='Target OSs (comma-separated).', |
| 37 metavar='[all,host,android]', |
| 38 default='host') |
32 result.add_option("-j", | 39 result.add_option("-j", |
33 help='The number of parallel jobs to run.', | 40 help='The number of parallel jobs to run.', |
34 metavar=HOST_CPUS, | 41 metavar=HOST_CPUS, |
35 default=str(HOST_CPUS)) | 42 default=str(HOST_CPUS)) |
36 result.add_option("--devenv", | 43 result.add_option("--devenv", |
37 help='Path containing devenv.com on Windows', | 44 help='Path containing devenv.com on Windows', |
38 default='C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Common7\\ID
E') | 45 default='C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Common7\\ID
E') |
39 return result | 46 return result |
40 | 47 |
41 | 48 |
42 def ProcessOptions(options): | 49 def ProcessOsOption(os): |
| 50 if os == 'host': |
| 51 return HOST_OS |
| 52 return os |
| 53 |
| 54 |
| 55 def ProcessOptions(options, args): |
43 if options.arch == 'all': | 56 if options.arch == 'all': |
44 options.arch = 'ia32,x64' | 57 options.arch = 'ia32,x64' |
45 if options.mode == 'all': | 58 if options.mode == 'all': |
46 options.mode = 'release,debug' | 59 options.mode = 'release,debug' |
| 60 if options.os == 'all': |
| 61 options.os = 'host,android' |
47 options.mode = options.mode.split(',') | 62 options.mode = options.mode.split(',') |
48 options.arch = options.arch.split(',') | 63 options.arch = options.arch.split(',') |
| 64 options.os = options.os.split(',') |
49 for mode in options.mode: | 65 for mode in options.mode: |
50 if not mode in ['debug', 'release']: | 66 if not mode in ['debug', 'release']: |
51 print "Unknown mode %s" % mode | 67 print "Unknown mode %s" % mode |
52 return False | 68 return False |
53 for arch in options.arch: | 69 for arch in options.arch: |
54 if not arch in ['ia32', 'x64', 'simarm', 'arm']: | 70 if not arch in ['ia32', 'x64', 'simarm', 'arm']: |
55 print "Unknown arch %s" % arch | 71 print "Unknown arch %s" % arch |
56 return False | 72 return False |
| 73 options.os = [ProcessOsOption(os) for os in options.os] |
| 74 for os in options.os: |
| 75 if not os in ['android', 'freebsd', 'linux', 'macos', 'win32']: |
| 76 print "Unknown os %s" % os |
| 77 return False |
| 78 if os != HOST_OS: |
| 79 if os != 'android': |
| 80 print "Unsupported target os %s" % os |
| 81 return False |
| 82 if not HOST_OS in ['linux']: |
| 83 print ("Cross-compilation to %s is not supported on host os %s." |
| 84 % (os, HOST_OS)) |
| 85 return False |
| 86 if not arch in ['ia32']: |
| 87 print ("Cross-compilation to %s is not supported for architecture %s." |
| 88 % (os, arch)) |
| 89 return False |
| 90 # We have not yet tweaked the v8 dart build to work with the Android |
| 91 # NDK/SDK, so don't try to build it. |
| 92 if args == []: |
| 93 print "For android builds you must specify a target, such as 'dart'." |
| 94 return False |
| 95 if 'v8' in args: |
| 96 print "The v8 target is not supported for android builds." |
| 97 return False |
57 return True | 98 return True |
58 | 99 |
59 | 100 |
60 def setTools(arch): | 101 def SetTools(arch, toolchainprefix): |
61 if arch == 'arm': | 102 toolsOverride = None |
| 103 if arch == 'arm' and toolchainprefix == None: |
| 104 toolchainprefix = armcompilerlocation + "/bin/arm-none-linux-gnueabi" |
| 105 if toolchainprefix: |
62 toolsOverride = { | 106 toolsOverride = { |
63 "CC" : armcompilerlocation + "/bin/arm-none-linux-gnueabi-gcc", | 107 "CC" : toolchainprefix + "-gcc", |
64 "CXX" : armcompilerlocation + "/bin/arm-none-linux-gnueabi-g++", | 108 "CXX" : toolchainprefix + "-g++", |
65 "AR" : armcompilerlocation + "/bin/arm-none-linux-gnueabi-ar", | 109 "AR" : toolchainprefix + "-ar", |
66 "LINK": armcompilerlocation + "/bin/arm-none-linux-gnueabi-g++", | 110 "LINK": toolchainprefix + "-g++", |
67 "NM" : armcompilerlocation + "/bin/arm-none-linux-gnueabi-nm", | 111 "NM" : toolchainprefix + "-nm", |
68 } | 112 } |
69 return toolsOverride | 113 return toolsOverride |
| 114 |
| 115 |
| 116 def CheckDirExists(path, docstring): |
| 117 if not os.path.isdir(path): |
| 118 raise Exception('Could not find %s directory %s' |
| 119 % (docstring, path)) |
| 120 |
| 121 |
| 122 def SetCrossCompilationEnvironment(host_os, target_os, target_arch, old_path): |
| 123 global THIRD_PARTY_ROOT |
| 124 if host_os not in ['linux']: |
| 125 raise Exception('Unsupported host os %s' % host_os) |
| 126 if target_os not in ['android']: |
| 127 raise Exception('Unsupported target os %s' % target_os) |
| 128 if target_arch not in ['ia32']: |
| 129 raise Exception('Unsupported target architecture %s' % target_arch) |
| 130 |
| 131 CheckDirExists(THIRD_PARTY_ROOT, 'third party tools'); |
| 132 android_tools = os.path.join(THIRD_PARTY_ROOT, 'android_tools') |
| 133 CheckDirExists(android_tools, 'Android tools') |
| 134 android_ndk_root = os.path.join(android_tools, 'ndk') |
| 135 CheckDirExists(android_ndk_root, 'Android NDK') |
| 136 android_sdk_root = os.path.join(android_tools, 'sdk') |
| 137 CheckDirExists(android_sdk_root, 'Android SDK') |
| 138 |
| 139 os.environ['ANDROID_NDK_ROOT'] = android_ndk_root |
| 140 os.environ['ANDROID_SDK_ROOT'] = android_sdk_root |
| 141 |
| 142 toolchain_arch = 'x86-4.4.3' |
| 143 toolchain_dir = 'linux-x86' |
| 144 android_toolchain = os.path.join(android_ndk_root, |
| 145 'toolchains', toolchain_arch, |
| 146 'prebuilt', toolchain_dir, 'bin') |
| 147 CheckDirExists(android_toolchain, 'Android toolchain') |
| 148 |
| 149 os.environ['ANDROID_TOOLCHAIN'] = android_toolchain |
| 150 |
| 151 android_sdk_version = 9 |
| 152 |
| 153 android_sdk_tools = os.path.join(android_sdk_root, 'tools') |
| 154 CheckDirExists(android_sdk_tools, 'Android SDK tools') |
| 155 |
| 156 android_sdk_platform_tools = os.path.join(android_sdk_root, 'platform-tools') |
| 157 CheckDirExists(android_sdk_platform_tools, 'Android SDK platform tools') |
| 158 |
| 159 pathList = [old_path, |
| 160 android_ndk_root, |
| 161 android_sdk_tools, |
| 162 android_sdk_platform_tools, |
| 163 # for Ninja - maybe don't need? |
| 164 android_toolchain |
| 165 ] |
| 166 os.environ['PATH'] = ':'.join(pathList) |
| 167 |
| 168 gypDefinesList = [ |
| 169 'target_arch=ia32', |
| 170 'OS=%s' % target_os, |
| 171 'android_build_type=0', |
| 172 'host_os=%s' % host_os, |
| 173 'linux_fpic=1', |
| 174 'release_optimize=s', |
| 175 'linux_use_tcmalloc=0', |
| 176 'android_sdk=%s', os.path.join(android_sdk_root, 'platforms', |
| 177 'android-%d' % android_sdk_version), |
| 178 'android_sdk_tools=%s' % android_sdk_platform_tools |
| 179 ] |
| 180 |
| 181 os.environ['GYP_DEFINES'] = ' '.join(gypDefinesList) |
70 | 182 |
71 | 183 |
72 def Execute(args): | 184 def Execute(args): |
73 print "#" + ' '.join(args) | |
74 process = subprocess.Popen(args) | 185 process = subprocess.Popen(args) |
75 process.wait() | 186 process.wait() |
76 if process.returncode != 0: | 187 if process.returncode != 0: |
77 raise Error(args[0] + " failed") | 188 raise Error(args[0] + " failed") |
78 | 189 |
79 | 190 |
| 191 def GClientRunHooks(): |
| 192 Execute(['gclient', 'runhooks']) |
| 193 |
| 194 |
| 195 def RunhooksIfNeeded(host_os, mode, arch, target_os): |
| 196 build_root = utils.GetBuildRoot(host_os) |
| 197 build_cookie_path = os.path.join(build_root, 'lastHooksTargetOS.txt') |
| 198 |
| 199 old_target_os = None |
| 200 try: |
| 201 with open(build_cookie_path) as f: |
| 202 old_target_os = f.read(1024) |
| 203 except IOError as e: |
| 204 pass |
| 205 if target_os != old_target_os: |
| 206 try: |
| 207 os.mkdir(build_root) |
| 208 except OSError as e: |
| 209 pass |
| 210 with open(build_cookie_path, 'w') as f: |
| 211 f.write(target_os) |
| 212 GClientRunHooks() |
| 213 |
| 214 |
80 def CurrentDirectoryBaseName(): | 215 def CurrentDirectoryBaseName(): |
81 """Returns the name of the current directory""" | 216 """Returns the name of the current directory""" |
82 return os.path.relpath(os.curdir, start=os.pardir) | 217 return os.path.relpath(os.curdir, start=os.pardir) |
83 | 218 |
| 219 |
84 def Main(): | 220 def Main(): |
85 utils.ConfigureJava() | 221 utils.ConfigureJava() |
86 # Parse the options. | 222 # Parse the options. |
87 parser = BuildOptions() | 223 parser = BuildOptions() |
88 (options, args) = parser.parse_args() | 224 (options, args) = parser.parse_args() |
89 if not ProcessOptions(options): | 225 if not ProcessOptions(options, args): |
90 parser.print_help() | 226 parser.print_help() |
91 return 1 | 227 return 1 |
92 # Determine which targets to build. By default we build the "all" target. | 228 # Determine which targets to build. By default we build the "all" target. |
93 if len(args) == 0: | 229 if len(args) == 0: |
94 if HOST_OS == 'macos': | 230 if HOST_OS == 'macos': |
95 target = 'All' | 231 target = 'All' |
96 else: | 232 else: |
97 target = 'all' | 233 target = 'all' |
98 else: | 234 else: |
99 target = args[0] | 235 target = args[0] |
| 236 |
| 237 # Remember path |
| 238 old_path = os.environ['PATH'] |
100 # Build the targets for each requested configuration. | 239 # Build the targets for each requested configuration. |
101 for mode in options.mode: | 240 for target_os in options.os: |
102 for arch in options.arch: | 241 for mode in options.mode: |
103 build_config = utils.GetBuildConf(mode, arch) | 242 for arch in options.arch: |
104 if HOST_OS == 'macos': | 243 build_config = utils.GetBuildConf(mode, arch) |
105 project_file = 'dart.xcodeproj' | 244 if HOST_OS == 'macos': |
106 if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()): | 245 project_file = 'dart.xcodeproj' |
107 project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName() | 246 if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()): |
108 args = ['xcodebuild', | 247 project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName() |
109 '-project', | 248 args = ['xcodebuild', |
110 project_file, | 249 '-project', |
111 '-target', | 250 project_file, |
112 target, | 251 '-target', |
113 '-parallelizeTargets', | 252 target, |
114 '-configuration', | 253 '-parallelizeTargets', |
115 build_config, | 254 '-configuration', |
116 'SYMROOT=%s' % os.path.abspath('xcodebuild') | |
117 ] | |
118 elif HOST_OS == 'win32': | |
119 project_file = 'dart.sln' | |
120 if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()): | |
121 project_file = 'dart-%s.sln' % CurrentDirectoryBaseName() | |
122 if target == 'all': | |
123 args = [options.devenv + os.sep + 'devenv.com', | |
124 '/build', | |
125 build_config, | 255 build_config, |
126 project_file | 256 'SYMROOT=%s' % os.path.abspath('xcodebuild') |
127 ] | 257 ] |
| 258 elif HOST_OS == 'win32': |
| 259 project_file = 'dart.sln' |
| 260 if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()): |
| 261 project_file = 'dart-%s.sln' % CurrentDirectoryBaseName() |
| 262 if target == 'all': |
| 263 args = [options.devenv + os.sep + 'devenv.com', |
| 264 '/build', |
| 265 build_config, |
| 266 project_file |
| 267 ] |
| 268 else: |
| 269 args = [options.devenv + os.sep + 'devenv.com', |
| 270 '/build', |
| 271 build_config, |
| 272 '/project', |
| 273 target, |
| 274 project_file |
| 275 ] |
128 else: | 276 else: |
129 args = [options.devenv + os.sep + 'devenv.com', | 277 make = 'make' |
130 '/build', | 278 if HOST_OS == 'freebsd': |
131 build_config, | 279 make = 'gmake' |
132 '/project', | 280 # work around lack of flock |
133 target, | 281 os.environ['LINK'] = '$(CXX)' |
134 project_file | 282 args = [make, |
135 ] | 283 '-j', |
136 else: | 284 options.j, |
137 make = 'make' | 285 'BUILDTYPE=' + build_config, |
138 if HOST_OS == 'freebsd': | 286 ] |
139 make = 'gmake' | 287 if target_os != HOST_OS: |
140 # work around lack of flock | 288 args += ['builddir_name=' + utils.GetBuildDir(HOST_OS, target_os)] |
141 os.environ['LINK'] = '$(CXX)' | 289 if options.verbose: |
142 args = [make, | 290 args += ['V=1'] |
143 '-j', | |
144 options.j, | |
145 'BUILDTYPE=' + build_config, | |
146 ] | |
147 if options.verbose: | |
148 args += ['V=1'] | |
149 | 291 |
150 args += [target] | 292 args += [target] |
151 | 293 |
152 toolsOverride = setTools(arch) | 294 if target_os != HOST_OS: |
153 if toolsOverride: | 295 SetCrossCompilationEnvironment( |
154 for k, v in toolsOverride.iteritems(): | 296 HOST_OS, target_os, arch, old_path) |
155 args.append( k + "=" + v) | |
156 print k + " = " + v | |
157 | 297 |
158 print ' '.join(args) | 298 RunhooksIfNeeded(HOST_OS, mode, arch, target_os) |
159 process = subprocess.Popen(args) | 299 |
160 process.wait() | 300 toolchainprefix = None |
161 if process.returncode != 0: | 301 if target_os == 'android': |
162 print "BUILD FAILED" | 302 toolchainprefix = ('%s/i686-linux-android' |
163 return 1 | 303 % os.environ['ANDROID_TOOLCHAIN']) |
| 304 toolsOverride = SetTools(arch, toolchainprefix) |
| 305 if toolsOverride: |
| 306 printToolOverrides = target_os != 'android' |
| 307 for k, v in toolsOverride.iteritems(): |
| 308 args.append( k + "=" + v) |
| 309 if printToolOverrides: |
| 310 print k + " = " + v |
| 311 |
| 312 print ' '.join(args) |
| 313 process = subprocess.Popen(args) |
| 314 process.wait() |
| 315 if process.returncode != 0: |
| 316 print "BUILD FAILED" |
| 317 return 1 |
164 | 318 |
165 return 0 | 319 return 0 |
166 | 320 |
167 | 321 |
168 if __name__ == '__main__': | 322 if __name__ == '__main__': |
169 sys.exit(Main()) | 323 sys.exit(Main()) |
OLD | NEW |