blob: b54efe419b8e0565d46481f4e63a3bb2fc780d72 [file] [log] [blame]
Brian Silvermana29ebf92014-04-23 13:08:49 -05001#!/usr/bin/python3
2
3import argparse
4import sys
5import subprocess
6import re
7import os
8import os.path
9import string
10import shutil
11import errno
12
Brian Silvermanbe6cfe22014-04-27 08:06:27 -050013def aos_path():
14 return os.path.join(os.path.dirname(__file__), '..')
15
16def get_ip(device):
17 FILENAME = os.path.normpath(os.path.join(aos_path(), '..', 'output', 'ip_base.txt'))
18 if not os.access(FILENAME, os.R_OK):
19 os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
20 with open(FILENAME, 'w') as f:
21 f.write('10.9.71')
22 with open(FILENAME, 'r') as f:
23 base = f.readline()
24 if device == 'prime':
25 return base + '.179'
26 elif device == 'robot':
27 return base + '.2'
28 else:
29 raise Exception('Unknown device %s to get an IP address for.' % device)
30
Brian Silvermana9b1e5c2014-04-30 18:08:04 -070031def user_output(message):
32 print('build.py: ' + message, file=sys.stderr)
33
Brian Silvermana29ebf92014-04-23 13:08:49 -050034class Processor(object):
35 class UnknownPlatform(Exception):
36 def __init__(self, message):
37 self.message = message
38
Brian Silvermanb3d50542014-04-23 14:28:55 -050039 class Platform(object):
40 def outdir(self):
41 return os.path.join(
Brian Silvermanbe6cfe22014-04-27 08:06:27 -050042 aos_path(), '..', 'output', self.outname())
Brian Silvermanb3d50542014-04-23 14:28:55 -050043 def build_ninja(self):
44 return os.path.join(self.outdir(), 'build.ninja')
45
Brian Silvermanbe6cfe22014-04-27 08:06:27 -050046 def do_deploy(self, dry_run, command):
47 real_command = (('echo',) + command) if dry_run else command
48 subprocess.check_call(real_command, stdin=open(os.devnull, 'r'))
Brian Silvermana29ebf92014-04-23 13:08:49 -050049
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -070050 # TODO(brians): Verify that this (and its callers) catch everything from a
51 # fresh install.
52 def do_check_installed(self, other_packages):
53 all_packages = () + other_packages
54 try:
55 result = subprocess.check_output(
56 ('dpkg-query', '--show') + all_packages,
57 stdin=open(os.devnull, 'r'),
58 stderr=subprocess.STDOUT)
59 except subprocess.CalledProcessError as e:
60 user_output('Some packages not installed:\n'
61 + e.output.decode('utf-8').rstrip())
62 exit(1)
63
Brian Silvermana29ebf92014-04-23 13:08:49 -050064class CRIOProcessor(Processor):
Brian Silvermanb3d50542014-04-23 14:28:55 -050065 class Platform(Processor.Platform):
Brian Silvermana4aff562014-05-02 17:43:50 -070066 def __init__(self, debug, wind_base):
Brian Silvermanb3d50542014-04-23 14:28:55 -050067 super(CRIOProcessor.Platform, self).__init__()
68
69 self.debug = debug
Brian Silvermana4aff562014-05-02 17:43:50 -070070 self.wind_base = wind_base
Brian Silvermanb3d50542014-04-23 14:28:55 -050071
72 def __repr__(self):
73 return 'CRIOProcessor.Platform(debug=%s)' % self.debug
74 def __str__(self):
75 return 'crio%s' % ('-debug' if self.debug else '')
76
77 def outname(self):
78 return 'crio-debug' if self.debug else 'crio'
79 def os(self):
80 return 'vxworks'
81 def gyp_platform(self):
82 return 'crio'
83 def architecture(self):
84 return 'ppc'
85 def compiler(self):
86 return 'gcc'
87
Brian Silvermane48c09a2014-04-30 18:04:58 -070088 # TODO(brians): test this
Brian Silvermanbe6cfe22014-04-27 08:06:27 -050089 def deploy(self, dry_run):
90 self.do_deploy(dry_run,
91 ('ncftpput', get_ip('robot'), '/',
92 os.path.join(self.outdir(), 'lib', 'FRC_UserProgram.out')))
93
Brian Silvermana4aff562014-05-02 17:43:50 -070094 def build_env(self):
95 return {'WIND_BASE': self.wind_base}
96
Brian Silvermana29ebf92014-04-23 13:08:49 -050097 def __init__(self):
98 super(CRIOProcessor, self).__init__()
99
100 if 'WIND_BASE' in os.environ:
101 self.wind_base = os.environ['WIND_BASE']
102 else:
103 self.wind_base = '/usr/local/powerpc-wrs-vxworks/wind_base'
104
105 def parse_platforms(self, string):
Brian Silvermanb3d50542014-04-23 14:28:55 -0500106 if string is None or string == 'crio':
Brian Silvermana4aff562014-05-02 17:43:50 -0700107 return (CRIOProcessor.Platform(False, self.wind_base),)
108 elif string == 'crio-debug' or string == 'debug':
109 return (CRIOProcessor.Platform(True, self.wind_base),)
Brian Silvermanb3d50542014-04-23 14:28:55 -0500110 else:
111 raise Processor.UnknownPlatform('Unknown cRIO platform "%s".' % string)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500112
Brian Silvermanb3d50542014-04-23 14:28:55 -0500113 def extra_gyp_flags(self):
114 return ('-DWIND_BASE=%s' % self.wind_base,)
115
Brian Silvermana29ebf92014-04-23 13:08:49 -0500116 def is_crio(self): return True
117
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700118 def check_installed(self):
119 # TODO(brians): Add powerpc-wrs-vxworks (a new enough version too).
120 self.do_check_installed(
121 ('ncftp',))
122
Brian Silvermana29ebf92014-04-23 13:08:49 -0500123class PrimeProcessor(Processor):
Brian Silvermanb3d50542014-04-23 14:28:55 -0500124 class Platform(Processor.Platform):
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700125 def __init__(self, architecture, compiler, debug, sanitizer):
Brian Silvermanb3d50542014-04-23 14:28:55 -0500126 super(PrimeProcessor.Platform, self).__init__()
127
Brian Silvermana29ebf92014-04-23 13:08:49 -0500128 self.architecture = architecture
129 self.compiler = compiler
130 self.debug = debug
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700131 self.sanitizer = sanitizer
Brian Silvermana29ebf92014-04-23 13:08:49 -0500132
133 def __repr__(self):
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700134 return 'PrimeProcessor.Platform(architecture=%s, compiler=%s, debug=%s' \
135 ', sanitizer=%s)' \
136 % (self.architecture, self.compiler, self.debug, self.sanitizer)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500137 def __str__(self):
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700138 return '%s-%s%s-%s' % (self.architecture, self.compiler,
139 '-debug' if self.debug else '', self.sanitizer)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500140
141 def os(self):
142 return 'linux'
143 def gyp_platform(self):
144 return '%s-%s-%s' % (self.os(), self.architecture, self.compiler)
145
Brian Silvermana29ebf92014-04-23 13:08:49 -0500146 def outname(self):
147 return str(self)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500148
Brian Silvermane48c09a2014-04-30 18:04:58 -0700149 # TODO(brians): test this
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500150 def deploy(self, dry_run):
151 """Downloads code to the prime in a way that avoids clashing too badly with starter
152 """
153 SUM = 'md5sum'
154 TARGET_DIR = '/home/driver/robot_code/bin'
155 TEMP_DIR = '/tmp/aos_downloader'
156 TARGET = 'driver@' + get_ip('prime')
157
158 from_dir = os.path.join(self.outdir(), 'outputs')
159 sums = subprocess.check_output((SUM,) + tuple(os.listdir(from_dir)),
160 stdin=open(os.devnull, 'r'),
161 cwd=from_dir)
162 to_download = subprocess.check_output(
163 ('ssh', TARGET,
164 """rm -rf {TMPDIR} && mkdir {TMPDIR} && cd {TO_DIR}
165 && echo '{SUMS}' | {SUM} --check --quiet
166 |& grep -F FAILED | sed 's/^\\(.*\\): FAILED.*"'$'"/\\1/g'""".format(
167 TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR, SUMS=sums, SUM=SUM)))
168 if not to_download:
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700169 user_output("Nothing to download")
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500170 return
171 self.do_deploy(
172 dry_run,
173 ('scp', '-o', 'Compression yes') + to_download
174 + (('%s:%s' % (TARGET, TEMP_DIR)),))
175 if not dry_run:
176 subprocess.check_call(
177 ('ssh', TARGET,
178 """mv {TMPDIR}/* {TO_DIR}
179 && echo 'Done moving new executables into place'
180 && ionice -c 3 bash -c 'sync && sync && sync'""".format(
181 TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR)))
182
Brian Silvermana4aff562014-05-02 17:43:50 -0700183 def build_env(self):
184 r = {}
Brian Silverman47cd6f62014-05-03 10:35:52 -0700185 if self.compiler == 'clang' or self.compiler == 'gcc_4.8':
Brian Silvermana4aff562014-05-02 17:43:50 -0700186 r['LD_LIBRARY_PATH'] = '/opt/clang-3.5/lib64'
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700187 if self.sanitizer == 'address':
Brian Silvermana4aff562014-05-02 17:43:50 -0700188 r['ASAN_SYMBOLIZER_PATH'] = '/opt/clang-3.5/bin/llvm-symbolizer'
189 r['ASAN_OPTIONS'] = 'detect_leaks=1:check_initialization_order=1:strict_init_order=1'
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700190 elif self.sanitizer == 'memory':
191 r['MSAN_SYMBOLIZER_PATH'] = '/opt/clang-3.5/bin/llvm-symbolizer'
Brian Silvermana4aff562014-05-02 17:43:50 -0700192 return r
193
Brian Silverman47cd6f62014-05-03 10:35:52 -0700194 ARCHITECTURES = ('arm', 'amd64')
195 COMPILERS = ('clang', 'gcc', 'gcc_4.8')
196 SANITIZERS = ('address', 'undefined', 'integer', 'memory', 'thread', 'none')
197 SANITIZER_TEST_WARNINGS = {
198 'memory': (True,
199"""We don't have all of the libraries instrumented which leads to lots of false
200errors with msan (especially stdlibc++).
201TODO(brians): Figure out a way to deal with it."""),
202 'undefined': (False,
203"""There are several warnings in other people's code that ubsan catches.
204The following have been verified non-interesting:
205 include/c++/4.8.2/array:*: runtime error: reference binding to null pointer of type 'int'
206 This happens with ::std::array<T, 0> and it doesn't seem to cause any issues.
207 output/downloaded/eigen-3.2.1/Eigen/src/Core/util/Memory.h:782:*: runtime error: load of misaligned address 0x* for type 'const int', which requires 4 byte alignment
208 That's in the CPUID detection code which only runs on x86."""),
209 }
210 PIC_SANITIZERS = ('memory', 'thread')
Brian Silvermana29ebf92014-04-23 13:08:49 -0500211
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500212 def __init__(self, is_test, is_deploy):
Brian Silvermana29ebf92014-04-23 13:08:49 -0500213 super(Processor, self).__init__()
214
215 platforms = []
216 for architecture in PrimeProcessor.ARCHITECTURES:
217 for compiler in PrimeProcessor.COMPILERS:
218 for debug in [True, False]:
Brian Silverman47cd6f62014-05-03 10:35:52 -0700219 if architecture == 'arm' and compiler == 'gcc_4.8':
220 # We don't have a compiler to use here.
221 continue
Brian Silvermana29ebf92014-04-23 13:08:49 -0500222 platforms.append(
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700223 PrimeProcessor.Platform(architecture, compiler, debug, 'none'))
224 for sanitizer in PrimeProcessor.SANITIZERS:
Brian Silverman47cd6f62014-05-03 10:35:52 -0700225 for compiler in ('gcc_4.8', 'clang'):
226 if compiler == 'gcc_4.8' and (sanitizer == 'undefined' or
227 sanitizer == 'integer' or
228 sanitizer == 'memory'):
229 # GCC 4.8 doesn't support these sanitizers.
230 continue
231 # We already added sanitizer == 'none' above.
232 if sanitizer != 'none':
233 platforms.append(
234 PrimeProcessor.Platform('amd64', compiler, True, sanitizer))
Brian Silvermana29ebf92014-04-23 13:08:49 -0500235 self.platforms = frozenset(platforms)
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500236 if is_test:
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700237 self.default_platforms = self.select_platforms(architecture='amd64',
238 debug=True)
Brian Silverman47cd6f62014-05-03 10:35:52 -0700239 for sanitizer in PrimeProcessor.SANITIZER_TEST_WARNINGS:
240 self.default_platforms -= self.select_platforms(sanitizer=sanitizer)
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500241 elif is_deploy:
242 # TODO(brians): Switch to deploying the code built with clang.
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700243 self.default_platforms = self.select_platforms(architecture='arm',
244 compiler='gcc',
245 debug=False)
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500246 else:
247 self.default_platforms = self.select_platforms(debug=False)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500248
Brian Silvermanb3d50542014-04-23 14:28:55 -0500249 def extra_gyp_flags(self):
250 return ()
Brian Silvermana29ebf92014-04-23 13:08:49 -0500251 def is_crio(self): return False
252
253 def parse_platforms(self, string):
254 if string is None:
255 return self.default_platforms
256 r = self.default_platforms
257 for part in string.split(','):
258 if part[0] == '+':
259 r = r | self.select_platforms_string(part[1:])
260 elif part[0] == '-':
261 r = r - self.select_platforms_string(part[1:])
262 elif part[0] == '=':
263 r = self.select_platforms_string(part[1:])
264 else:
Brian Silverman7cd5ad42014-04-27 08:11:30 -0500265 selected = self.select_platforms_string(part)
266 r = r - (self.platforms - selected)
267 if not r:
268 r = selected
Brian Silvermana29ebf92014-04-23 13:08:49 -0500269 return r
270
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700271 def select_platforms(self, architecture=None, compiler=None, debug=None, sanitizer=None):
Brian Silvermana29ebf92014-04-23 13:08:49 -0500272 r = []
273 for platform in self.platforms:
274 if architecture is None or platform.architecture == architecture:
275 if compiler is None or platform.compiler == compiler:
276 if debug is None or platform.debug == debug:
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700277 if sanitizer is None or platform.sanitizer == sanitizer:
278 r.append(platform)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500279 return set(r)
280
281 def select_platforms_string(self, string):
282 r = []
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700283 architecture, compiler, debug, sanitizer = None, None, None, None
Brian Silvermana29ebf92014-04-23 13:08:49 -0500284 for part in string.split('-'):
285 if part in PrimeProcessor.ARCHITECTURES:
286 architecture = part
287 elif part in PrimeProcessor.COMPILERS:
288 compiler = part
289 elif part in ['debug', 'dbg']:
290 debug = True
291 elif part in ['release', 'nodebug', 'ndb']:
292 debug = False
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700293 elif part in PrimeProcessor.SANITIZERS:
294 sanitizer = part
Brian Silvermana29ebf92014-04-23 13:08:49 -0500295 else:
296 raise Processor.UnknownPlatform('Unknown platform string component "%s".' % part)
297 return self.select_platforms(
298 architecture=architecture,
299 compiler=compiler,
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700300 debug=debug,
301 sanitizer=sanitizer)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500302
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700303 def check_installed(self):
304 self.do_check_installed(
305 ('clang-3.5', 'gcc-4.7-arm-linux-gnueabihf',
306 'g++-4.7-arm-linux-gnueabihf', 'openssh-client'))
307
Brian Silvermana29ebf92014-04-23 13:08:49 -0500308def main():
309 class TryParsingAgain(Exception):
310 pass
311
312 class TryAgainArgumentParser(argparse.ArgumentParser):
313 def __init__(self, **kwargs):
314 super(TryAgainArgumentParser, self).__init__(**kwargs)
315
316 def error(self, message):
317 raise TryParsingAgain
318
319 def SetUpParser(parser, args):
320 def AddBuildArgs(parser):
321 parser.add_argument(
322 'target',
323 help='target to build',
324 nargs='*')
325 def AddCommonArgs(parser):
326 parser.add_argument(
327 'platforms',
328 help='platform(s) to act on',
329 nargs='?')
330
331 parser.add_argument('--processor', required=True, help='prime or crio')
332 parser.add_argument('--main_gyp', required=True, help='main .gyp file')
333 subparsers = parser.add_subparsers(dest='action_name')
334
335 build_parser = subparsers.add_parser(
336 'build',
337 help='build the code (default)')
338 AddCommonArgs(build_parser)
339 AddBuildArgs(build_parser)
340
341 clean_parser = subparsers.add_parser(
342 'clean',
343 help='remove all output directories')
344 AddCommonArgs(clean_parser)
345
346 deploy_parser = subparsers.add_parser(
347 'deploy',
348 help='build and download the code')
349 AddCommonArgs(deploy_parser)
350 AddBuildArgs(deploy_parser)
351 deploy_parser.add_argument(
352 '-n', '--dry-run',
353 help="don't actually download anything",
354 action='store_true')
355
Brian Silvermane48c09a2014-04-30 18:04:58 -0700356 tests_parser = subparsers.add_parser(
357 'tests',
358 help='run tests')
359 AddCommonArgs(tests_parser)
360 AddBuildArgs(tests_parser)
361
Brian Silvermana29ebf92014-04-23 13:08:49 -0500362 return parser.parse_args(args)
363
364 try:
365 parser = TryAgainArgumentParser()
366 args = SetUpParser(parser, sys.argv[1:])
367 except TryParsingAgain:
368 parser = argparse.ArgumentParser()
369 REQUIRED_ARGS_END = 5
370 args = SetUpParser(parser, sys.argv[1:REQUIRED_ARGS_END] + ['build'] +
371 sys.argv[(REQUIRED_ARGS_END):])
372
373 if args.processor == 'crio':
374 processor = CRIOProcessor()
375 elif args.processor == 'prime':
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500376 processor = PrimeProcessor(args.action_name == 'tests',
377 args.action_name == 'deploy')
Brian Silvermana29ebf92014-04-23 13:08:49 -0500378 else:
379 parser.exit(status=1, message='Unknown processor "%s".' % args.processor)
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700380 processor.check_installed()
Brian Silvermana29ebf92014-04-23 13:08:49 -0500381
382 if 'target' in args:
383 targets = args.target[:]
384 else:
385 targets = []
386 unknown_platform_error = None
387 try:
388 platforms = processor.parse_platforms(args.platforms)
389 except Processor.UnknownPlatform as e:
390 unknown_platform_error = e.message
391 targets.append(args.platforms)
392 platforms = processor.parse_platforms(None)
393 if not platforms:
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700394 user_output("No platforms selected!")
Brian Silvermana29ebf92014-04-23 13:08:49 -0500395 exit(1)
396
397 def download_externals(argument):
398 subprocess.check_call(
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500399 (os.path.join(aos_path(), 'build', 'download_externals.sh'),
Brian Silvermana29ebf92014-04-23 13:08:49 -0500400 argument),
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500401 stdin=open(os.devnull, 'r'))
Brian Silvermana29ebf92014-04-23 13:08:49 -0500402
403 if processor.is_crio():
404 download_externals('crio')
405 else:
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700406 to_download = set()
Brian Silvermana29ebf92014-04-23 13:08:49 -0500407 for architecture in PrimeProcessor.ARCHITECTURES:
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700408 for sanitizer in PrimeProcessor.PIC_SANITIZERS:
409 if platforms & processor.select_platforms(architecture=architecture,
410 sanitizer=sanitizer):
411 to_download.add(architecture + '-fPIC')
412 if platforms & processor.select_platforms(architecture=architecture,
413 sanitizer='none'):
414 to_download.add(architecture)
415 for download_target in to_download:
416 download_externals(download_target)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500417
418 class ToolsConfig(object):
419 def __init__(self):
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500420 self.variables = {'AOS': aos_path()}
421 with open(os.path.join(aos_path(), 'build', 'tools_config'), 'r') as f:
Brian Silvermana29ebf92014-04-23 13:08:49 -0500422 for line in f:
423 if line[0] == '#':
424 pass
425 elif line.isspace():
426 pass
427 else:
428 new_name, new_value = line.rstrip().split('=')
429 for name, value in self.variables.items():
430 new_value = new_value.replace('${%s}' % name, value)
431 self.variables[new_name] = new_value
432 def __getitem__(self, key):
433 return self.variables[key]
434
435 tools_config = ToolsConfig()
436
437 def handle_clean_error(function, path, excinfo):
438 if issubclass(OSError, excinfo[0]):
439 if excinfo[1].errno == errno.ENOENT:
440 # Who cares if the file we're deleting isn't there?
441 return
442 raise excinfo[1]
443
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700444 def need_to_run_gyp(platform):
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700445 if not os.path.exists(platform.build_ninja()):
446 return True
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700447 dirs = os.listdir(os.path.join(aos_path(), '..'))
Brian Silvermana4aff562014-05-02 17:43:50 -0700448 # Looking through these folders takes a long time and isn't useful.
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700449 dirs.remove('output')
Brian Silvermana4aff562014-05-02 17:43:50 -0700450 dirs.remove('.git')
451 return not not subprocess.check_output(
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700452 ('find',) + tuple(os.path.join(aos_path(), '..', d) for d in dirs)
453 + ('-newer', platform.build_ninja(),
454 '(', '-name', '*.gyp', '-or', '-name', '*.gypi', ')'),
Brian Silvermana4aff562014-05-02 17:43:50 -0700455 stdin=open(os.devnull, 'r'))
456
457 def env(platform):
458 build_env = dict(platform.build_env())
459 build_env['TERM'] = os.environ['TERM']
460 build_env['PATH'] = os.environ['PATH']
461 return build_env
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700462
Brian Silverman47cd6f62014-05-03 10:35:52 -0700463 to_build = []
464 for platform in platforms:
465 to_build.append(str(platform))
466 if len(to_build) > 1:
467 to_build[-1] = 'and ' + to_build[-1]
468 user_output('Building %s...' % ', '.join(to_build))
469
470 if args.action_name == 'tests':
471 for sanitizer, warning in PrimeProcessor.SANITIZER_TEST_WARNINGS.items():
472 warned_about = platforms & processor.select_platforms(sanitizer=sanitizer)
473 if warned_about:
474 user_output(warning[1])
475 if warning[0]:
476 # TODO(brians): Add a --force flag or something?
477 user_output('Refusing to run tests for sanitizer %s.' % sanitizer)
478 exit(1)
479
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700480 num = 1
Brian Silvermana29ebf92014-04-23 13:08:49 -0500481 for platform in platforms:
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700482 user_output('Building %s (%d/%d)...' % (platform, num, len(platforms)))
Brian Silvermana29ebf92014-04-23 13:08:49 -0500483 if args.action_name == 'clean':
484 shutil.rmtree(platform.outdir(), onerror=handle_clean_error)
485 else:
486 if need_to_run_gyp(platform):
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700487 user_output('Running gyp...')
Brian Silvermana29ebf92014-04-23 13:08:49 -0500488 gyp = subprocess.Popen(
489 (tools_config['GYP'],
490 '--check',
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500491 '--depth=%s' % os.path.join(aos_path(), '..'),
Brian Silvermana29ebf92014-04-23 13:08:49 -0500492 '--no-circular-check',
493 '-f', 'ninja',
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500494 '-I%s' % os.path.join(aos_path(), 'build', 'aos.gypi'),
Brian Silvermana29ebf92014-04-23 13:08:49 -0500495 '-I/dev/stdin', '-Goutput_dir=output',
496 '-DOS=%s' % platform.os(),
497 '-DPLATFORM=%s' % platform.gyp_platform(),
498 '-DARCHITECTURE=%s' % platform.architecture,
Brian Silverman47cd6f62014-05-03 10:35:52 -0700499 '-DCOMPILER=%s' % platform.compiler.split('_')[0],
500 '-DFULL_COMPILER=%s' % platform.compiler,
Brian Silvermanf0d3c782014-05-02 23:56:32 -0700501 '-DDEBUG=%s' % ('yes' if platform.debug else 'no'),
502 '-DSANITIZER=%s' % platform.sanitizer,
503 '-DSANITIZER_FPIC=%s' % ('-fPIC'
504 if platform.sanitizer in PrimeProcessor.PIC_SANITIZERS
505 else '')) +
Brian Silvermanb3d50542014-04-23 14:28:55 -0500506 processor.extra_gyp_flags() + (args.main_gyp,),
Brian Silvermana29ebf92014-04-23 13:08:49 -0500507 stdin=subprocess.PIPE)
508 gyp.communicate(("""
509{
510 'target_defaults': {
511 'configurations': {
512 '%s': {}
513 }
514 }
515}""" % platform.outname()).encode())
516 if gyp.returncode:
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700517 user_output("Running gyp failed!")
Brian Silvermana29ebf92014-04-23 13:08:49 -0500518 exit(1)
Brian Silvermanb3d50542014-04-23 14:28:55 -0500519 if processor.is_crio():
520 subprocess.check_call(
521 ('sed', '-i',
522 's/nm -gD/nm/g', platform.build_ninja()),
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500523 stdin=open(os.devnull, 'r'))
Brian Silverman47cd6f62014-05-03 10:35:52 -0700524 user_output('Done running gyp')
Brian Silvermana29ebf92014-04-23 13:08:49 -0500525 else:
Brian Silverman47cd6f62014-05-03 10:35:52 -0700526 user_output("Not running gyp")
Brian Silvermana29ebf92014-04-23 13:08:49 -0500527
528 try:
529 subprocess.check_call(
530 (tools_config['NINJA'],
531 '-C', platform.outdir()) + tuple(targets),
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500532 stdin=open(os.devnull, 'r'),
Brian Silvermana4aff562014-05-02 17:43:50 -0700533 env=env(platform))
Brian Silvermana29ebf92014-04-23 13:08:49 -0500534 except subprocess.CalledProcessError as e:
535 if unknown_platform_error is not None:
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700536 user_output(unknown_platform_error)
Brian Silvermana29ebf92014-04-23 13:08:49 -0500537 raise e
538
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500539 if args.action_name == 'deploy':
540 platform.deploy(args.dry_run)
Brian Silvermane48c09a2014-04-30 18:04:58 -0700541 elif args.action_name == 'tests':
542 dirname = os.path.join(platform.outdir(), 'tests')
543 for f in targets or os.listdir(dirname):
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700544 user_output('Running test %s...' % f)
Brian Silvermana4aff562014-05-02 17:43:50 -0700545 subprocess.check_call(
546 os.path.join(dirname, f),
547 env=env(platform))
Brian Silvermana9b1e5c2014-04-30 18:08:04 -0700548 user_output('Test %s succeeded' % f)
Brian Silvermanbe6cfe22014-04-27 08:06:27 -0500549
Brian Silvermanc2d8e5a2014-05-01 18:33:12 -0700550 user_output('Done building %s (%d/%d)' % (platform, num, len(platforms)))
551 num += 1
Brian Silvermana29ebf92014-04-23 13:08:49 -0500552
553if __name__ == '__main__':
554 main()