2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
14 sys.path.append("./common")
15 sys.path.append('../third_party')
17 from SCons.Errors import UserError
18 from SCons.Script import GetBuildFailures
23 SCons.Warnings.warningAsException()
25 sys.path.append("tools")
29 import pynacl.platform
31 # turning garbage collection off reduces startup time by 10%
38 def PrintFinalReport():
39 """This function is run just before scons exits and dumps various reports.
41 # Note, these global declarations are not strictly necessary
46 if pre_base_env.Bit('target_stats'):
49 print 'COMMAND EXECUTION REPORT'
51 for k in sorted(CMD_COUNTER.keys()):
52 print "%4d %s" % (CMD_COUNTER[k], k)
56 print 'ENVIRONMENT USAGE REPORT'
58 for k in sorted(ENV_COUNTER.keys()):
59 print "%4d %s" % (ENV_COUNTER[k], k)
62 for failure in GetBuildFailures():
63 for node in Flatten(failure.node):
65 # If this wasn't a test, "GetTestName" will return raw_name.
66 'test_name': GetTestName(node),
67 'raw_name': str(node.path),
68 'errstr': failure.errstr
71 json_path = ARGUMENTS.get('json_build_results_output_file')
73 with open(json_path, 'w') as f:
74 json.dump(failures, f, sort_keys=True, indent=2)
81 print 'ERROR REPORT: %d failures' % len(failures)
84 for failure in failures:
85 test_name = failure['test_name']
86 if test_name != failure['raw_name']:
87 test_name = '%s (%s)' % (test_name, failure['raw_name'])
88 print "%s failed: %s\n" % (test_name, failure['errstr'])
91 def VerboseConfigInfo(env):
92 "Should we print verbose config information useful for bug reports"
93 if '--help' in sys.argv: return False
94 if env.Bit('prebuilt') or env.Bit('built_elsewhere'): return False
95 return env.Bit('sysinfo')
100 # NOTE BitFromArgument(...) implicitly defines additional ACCEPTABLE_ARGUMENTS.
101 ACCEPTABLE_ARGUMENTS = set([
102 # TODO: add comments what these mean
103 # TODO: check which ones are obsolete
104 #### ASCII SORTED ####
105 # Use a destination directory other than the default "scons-out".
109 # Limit bandwidth of browser tester
111 # Location to download Chromium binaries to and/or read them from.
112 'chrome_binaries_dir',
113 # used for chrome_browser_tests: path to the browser
114 'chrome_browser_path',
115 # A comma-separated list of test names to disable by excluding the
116 # tests from a test suite. For example, 'small_tests
117 # disable_tests=run_hello_world_test' will run small_tests without
118 # including hello_world_test. Note that if a test listed here
119 # does not exist you will not get an error or a warning.
121 # used for chrome_browser_tests: path to a pre-built browser plugin.
122 'force_ppapi_plugin',
123 # force emulator use by tests
125 # force sel_ldr use by tests
127 # force irt image used by tests
129 # generate_ninja=FILE enables a Ninja backend for SCons. This writes a
130 # .ninja build file to FILE describing all of SCons' build targets.
132 # Path to a JSON file for machine-readable output.
133 'json_build_results_output_file',
134 # Replacement memcheck command for overriding the DEPS-in memcheck
135 # script. May have commas to separate separate shell args. There
136 # is no quoting, so this implies that this mechanism will fail if
137 # the args actually need to have commas. See
138 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
139 # the discussion of why this argument is needed.
141 # If the replacement memcheck command only works for trusted code,
142 # set memcheck_trusted_only to non-zero.
143 'memcheck_trusted_only',
144 # When building with MSan, this can be set to values 0 (fastest, least
145 # useful reports) through 2 (slowest, most useful reports). Default is 1.
146 'msan_track_origins',
147 # colon-separated list of linker flags, e.g. "-lfoo:-Wl,-u,bar".
149 # colon-separated list of pnacl bcld flags, e.g. "-lfoo:-Wl,-u,bar".
150 # Not using nacl_linkflags since that gets clobbered in some tests.
153 # Run tests under this tool (e.g. valgrind, tsan, strace, etc).
154 # If the tool has options, pass them after comma: 'tool,--opt1,--opt2'.
155 # NB: no way to use tools the names or the args of
156 # which contains a comma.
158 # More args for the tool.
159 'run_under_extra_args',
160 # Multiply timeout values by this number.
162 # test_wrapper specifies a wrapper program such as
163 # tools/run_test_via_ssh.py, which runs tests on a remote host
164 # using rsync and SSH. Example usage:
165 # ./scons run_hello_world_test platform=arm force_emulator= \
166 # test_wrapper="./tools/run_test_via_ssh.py --host=armbox --subdir=tmp"
168 # Replacement tsan command for overriding the DEPS-in tsan
169 # script. May have commas to separate separate shell args. There
170 # is no quoting, so this implies that this mechanism will fail if
171 # the args actually need to have commas. See
172 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
173 # the discussion of why this argument is needed.
175 # Run browser tests under this tool. See
176 # tools/browser_tester/browsertester/browserlauncher.py for tool names.
178 # activates buildbot-specific presets
180 # Where to install header files for public consumption.
182 # Where to install libraries for public consumption.
184 # Where to install trusted-code binaries for public (SDK) consumption.
186 # Where a Breakpad build output directory is for optional Breakpad testing.
187 'breakpad_tools_dir',
188 # Allows overriding of the nacl newlib toolchain directory.
190 # Allows override of the nacl glibc toolchain directory.
192 # Allows override of the pnacl newlib toolchain directory.
194 # Allows overriding the version number in the toolchain's
195 # FEATURE_VERSION file. This is used for PNaCl ABI compatibility
197 'toolchain_feature_version',
201 # Overly general to provide compatibility with existing build bots, etc.
202 # In the future it might be worth restricting the values that are accepted.
203 _TRUE_STRINGS = set(['1', 'true', 'yes'])
204 _FALSE_STRINGS = set(['0', 'false', 'no'])
207 # Converts a string representing a Boolean value, of some sort, into an actual
208 # Boolean value. Python's built in type coercion does not work because
209 # bool('False') == True
210 def StringValueToBoolean(value):
211 # ExpandArguments may stick non-string values in ARGUMENTS. Be accommodating.
212 if isinstance(value, bool):
215 if not isinstance(value, basestring):
216 raise Exception("Expecting a string but got a %s" % repr(type(value)))
218 if value.lower() in _TRUE_STRINGS:
220 elif value.lower() in _FALSE_STRINGS:
223 raise Exception("Cannot convert '%s' to a Boolean value" % value)
226 def GetBinaryArgumentValue(arg_name, default):
227 if not isinstance(default, bool):
228 raise Exception("Default value for '%s' must be a Boolean" % arg_name)
229 if arg_name not in ARGUMENTS:
231 return StringValueToBoolean(ARGUMENTS[arg_name])
234 # name is the name of the bit
235 # arg_name is the name of the command-line argument, if it differs from the bit
236 def BitFromArgument(env, name, default, desc, arg_name=None):
237 # In most cases the bit name matches the argument name
241 DeclareBit(name, desc)
242 assert arg_name not in ACCEPTABLE_ARGUMENTS, repr(arg_name)
243 ACCEPTABLE_ARGUMENTS.add(arg_name)
245 if GetBinaryArgumentValue(arg_name, default):
251 # SetUpArgumentBits declares binary command-line arguments and converts them to
252 # bits. For example, one of the existing declarations would result in the
253 # argument "bitcode=1" causing env.Bit('bitcode') to evaluate to true.
254 # NOTE Command-line arguments are a SCons-ism that is separate from
255 # command-line options. Options are prefixed by "-" or "--" whereas arguments
256 # are not. The function SetBitFromOption can be used for options.
257 # NOTE This function must be called before the bits are used
258 # NOTE This function must be called after all modifications of ARGUMENTS have
259 # been performed. See: ExpandArguments
260 def SetUpArgumentBits(env):
261 BitFromArgument(env, 'bitcode', default=False,
262 desc='We are building bitcode')
264 BitFromArgument(env, 'translate_fast', default=False,
265 desc='When using pnacl TC (bitcode=1) use accelerated translation step')
267 BitFromArgument(env, 'built_elsewhere', default=False,
268 desc='The programs have already been built by another system')
270 BitFromArgument(env, 'skip_trusted_tests', default=False,
271 desc='Only run untrusted tests - useful for translator testing'
272 ' (also skips tests of the IRT itself')
274 BitFromArgument(env, 'nacl_pic', default=False,
275 desc='generate position indepent code for (P)NaCl modules')
277 BitFromArgument(env, 'nacl_static_link', default=not env.Bit('nacl_glibc'),
278 desc='Whether to use static linking instead of dynamic linking '
279 'for building NaCl executables during tests. '
280 'For nacl-newlib, the default is 1 (static linking). '
281 'For nacl-glibc, the default is 0 (dynamic linking).')
283 BitFromArgument(env, 'nacl_disable_shared', default=not env.Bit('nacl_glibc'),
284 desc='Do not build shared versions of libraries. '
285 'For nacl-newlib, the default is 1 (static libraries only). '
286 'For nacl-glibc, the default is 0 (both static and shared libraries).')
288 # Defaults on when --verbose is specified.
289 # --verbose sets 'brief_comstr' to False, so this looks a little strange
290 BitFromArgument(env, 'target_stats', default=not GetOption('brief_comstr'),
291 desc='Collect and display information about which commands are executed '
292 'during the build process')
294 BitFromArgument(env, 'werror', default=True,
295 desc='Treat warnings as errors (-Werror)')
297 BitFromArgument(env, 'disable_nosys_linker_warnings', default=False,
298 desc='Disable warning mechanism in src/untrusted/nosys/warning.h')
300 BitFromArgument(env, 'naclsdk_validate', default=True,
301 desc='Verify the presence of the SDK')
303 BitFromArgument(env, 'running_on_valgrind', default=False,
304 desc='Compile and test using valgrind')
306 BitFromArgument(env, 'enable_tmpfs_redirect_var', default=False,
307 desc='Allow redirecting tmpfs location for shared memory '
308 '(by default, /dev/shm is used)')
310 BitFromArgument(env, 'pp', default=False,
311 desc='Enable pretty printing')
313 # Defaults on when --verbose is specified
314 # --verbose sets 'brief_comstr' to False, so this looks a little strange
315 BitFromArgument(env, 'sysinfo', default=not GetOption('brief_comstr'),
316 desc='Print verbose system information')
318 BitFromArgument(env, 'disable_flaky_tests', default=False,
319 desc='Do not run potentially flaky tests - used on Chrome bots')
321 BitFromArgument(env, 'use_sandboxed_translator', default=False,
322 desc='use pnacl sandboxed translator for linking (not available for arm)')
324 BitFromArgument(env, 'pnacl_generate_pexe', default=env.Bit('bitcode'),
325 desc='use pnacl to generate pexes and translate in a separate step')
327 BitFromArgument(env, 'translate_in_build_step', default=True,
328 desc='Run translation during build phase (e.g. if do_not_run_tests=1)')
330 BitFromArgument(env, 'pnacl_unsandboxed', default=False,
331 desc='Translate pexe to an unsandboxed, host executable')
333 BitFromArgument(env, 'nonsfi_nacl', default=False,
334 desc='Use Non-SFI Mode instead of the original SFI Mode. This uses '
335 'nonsfi_loader instead of sel_ldr, and it tells the PNaCl toolchain '
336 'to translate pexes to Non-SFI nexes.')
338 BitFromArgument(env, 'use_newlib_nonsfi_loader', default=True,
339 desc='Test nonsfi_loader linked against NaCl newlib instead of the one '
340 'linked against host libc. This flag makes sense only with '
343 BitFromArgument(env, 'browser_headless', default=False,
344 desc='Where possible, set up a dummy display to run the browser on '
345 'when running browser tests. On Linux, this runs the browser through '
346 'xvfb-run. This Scons does not need to be run with an X11 display '
347 'and we do not open a browser window on the user\'s desktop. '
348 'Unfortunately there is no equivalent on Mac OS X.')
350 BitFromArgument(env, 'disable_crash_dialog', default=True,
351 desc='Disable Windows\' crash dialog box, which Windows pops up when a '
352 'process exits with an unhandled fault. Windows enables this by '
353 'default for processes launched from the command line or from the '
354 'GUI. Our default is to disable it, because the dialog turns crashes '
355 'into hangs on Buildbot, and our test suite includes various crash '
358 BitFromArgument(env, 'do_not_run_tests', default=False,
359 desc='Prevents tests from running. This lets SCons build the files needed '
360 'to run the specified test(s) without actually running them. This '
361 'argument is a counterpart to built_elsewhere.')
363 BitFromArgument(env, 'no_gdb_tests', default=False,
364 desc='Prevents GDB tests from running. If GDB is not available, you can '
365 'test everything else by specifying this flag.')
367 BitFromArgument(env, 'validator_ragel', default=True,
368 desc='Use the R-DFA validator instead of the original validators.')
370 # TODO(shcherbina): add support for other golden-based tests, not only
371 # run_x86_*_validator_testdata_tests.
372 BitFromArgument(env, 'regenerate_golden', default=False,
373 desc='When running golden-based tests, instead of comparing results '
374 'save actual output as golden data.')
376 BitFromArgument(env, 'x86_64_zero_based_sandbox', default=False,
377 desc='Use the zero-address-based x86-64 sandbox model instead of '
378 'the r15-based model.')
380 BitFromArgument(env, 'android', default=False,
381 desc='Build for Android target')
383 BitFromArgument(env, 'arm_hard_float', default=True,
384 desc='Build for hard float ARM ABI')
386 BitFromArgument(env, 'skip_nonstable_bitcode', default=False,
387 desc='Skip tests involving non-stable bitcode')
389 #########################################################################
391 # This is for generating a testing library for use within private test
392 # enuminsts, where we want to compare and test different validators.
394 BitFromArgument(env, 'ncval_testing', default=False,
395 desc='EXPERIMENTAL: Compile validator code for testing within enuminsts')
397 # PNaCl sanity checks
398 if ((env.Bit('pnacl_generate_pexe') or env.Bit('use_sandboxed_translator'))
399 and not env.Bit('bitcode')):
400 raise UserError("pnacl_generate_pexe and use_sandboxed_translator"
401 " don't make sense without bitcode")
403 def CheckArguments():
404 for key in ARGUMENTS:
405 if key not in ACCEPTABLE_ARGUMENTS:
406 raise UserError('bad argument: %s' % key)
409 # Sets a command line argument. Dies if an argument with this name is already
411 def SetArgument(key, value):
412 print ' %s=%s' % (key, str(value))
414 raise UserError('ERROR: %s redefined' % (key, ))
415 ARGUMENTS[key] = value
417 # Expands "macro" command line arguments.
418 def ExpandArguments():
419 if ARGUMENTS.get('buildbot') == 'memcheck':
420 print 'buildbot=memcheck expands to the following arguments:'
421 SetArgument('run_under',
422 ARGUMENTS.get('memcheck_command',
423 'src/third_party/valgrind/memcheck.sh') +
424 ',--error-exitcode=1')
425 SetArgument('scale_timeout', 20)
426 SetArgument('running_on_valgrind', True)
427 elif ARGUMENTS.get('buildbot') == 'tsan':
428 print 'buildbot=tsan expands to the following arguments:'
429 SetArgument('run_under',
430 ARGUMENTS.get('tsan_command',
431 'src/third_party/valgrind/tsan.sh') +
432 ',--nacl-untrusted,--error-exitcode=1,' +
433 '--suppressions=src/third_party/valgrind/tests.supp')
434 SetArgument('scale_timeout', 20)
435 SetArgument('running_on_valgrind', True)
436 elif ARGUMENTS.get('buildbot') == 'tsan-trusted':
437 print 'buildbot=tsan-trusted expands to the following arguments:'
438 SetArgument('run_under',
439 ARGUMENTS.get('tsan_command',
440 'src/third_party/valgrind/tsan.sh') +
441 ',--error-exitcode=1,' +
442 '--suppressions=src/third_party/valgrind/tests.supp')
443 SetArgument('scale_timeout', 20)
444 SetArgument('running_on_valgrind', True)
445 elif ARGUMENTS.get('buildbot') == 'memcheck-browser-tests':
446 print 'buildbot=memcheck-browser-tests expands to the following arguments:'
447 SetArgument('browser_test_tool', 'memcheck')
448 SetArgument('scale_timeout', 20)
449 SetArgument('running_on_valgrind', True)
450 elif ARGUMENTS.get('buildbot') == 'tsan-browser-tests':
451 print 'buildbot=tsan-browser-tests expands to the following arguments:'
452 SetArgument('browser_test_tool', 'tsan')
453 SetArgument('scale_timeout', 20)
454 SetArgument('running_on_valgrind', True)
455 elif ARGUMENTS.get('buildbot'):
456 raise UserError('ERROR: unexpected argument buildbot="%s"' % (
457 ARGUMENTS.get('buildbot'), ))
461 def GetTargetPlatform():
462 return pynacl.platform.GetArch3264(ARGUMENTS.get('platform', 'x86-32'))
464 def GetBuildPlatform():
465 return pynacl.platform.GetArch3264()
468 environment_list = []
470 # Base environment for both nacl and non-nacl variants.
472 if ARGUMENTS.get('DESTINATION_ROOT') is not None:
473 kwargs['DESTINATION_ROOT'] = ARGUMENTS.get('DESTINATION_ROOT')
474 pre_base_env = Environment(
475 # Use the environment that scons was run in to run scons invoked commands.
476 # This allows in things like externally provided PATH, PYTHONPATH.
477 ENV = os.environ.copy(),
478 tools = ['component_setup'],
479 # SOURCE_ROOT is one leave above the native_client directory.
480 SOURCE_ROOT = Dir('#/..').abspath,
481 # Publish dlls as final products (to staging).
482 COMPONENT_LIBRARY_PUBLISH = True,
484 # Use workaround in special scons version.
486 LIBS_DO_SUBST = True,
488 # Select where to find coverage tools.
489 COVERAGE_MCOV = '../third_party/lcov/bin/mcov',
490 COVERAGE_GENHTML = '../third_party/lcov/bin/genhtml',
495 if 'generate_ninja' in ARGUMENTS:
496 import pynacl.scons_to_ninja
497 pynacl.scons_to_ninja.GenerateNinjaFile(
498 pre_base_env, dest_file=ARGUMENTS['generate_ninja'])
501 breakpad_tools_dir = ARGUMENTS.get('breakpad_tools_dir')
502 if breakpad_tools_dir is not None:
503 pre_base_env['BREAKPAD_TOOLS_DIR'] = pre_base_env.Dir(
504 os.path.abspath(breakpad_tools_dir))
508 DeclareBit('clang', 'Use clang to build trusted code')
509 pre_base_env.SetBitFromOption('clang', False)
512 'Use AddressSanitizer to build trusted code (implies --clang)')
513 pre_base_env.SetBitFromOption('asan', False)
514 if pre_base_env.Bit('asan'):
515 pre_base_env.SetBits('clang')
518 'Use MemorySanitizer to build trusted code (implies --clang)')
519 pre_base_env.SetBitFromOption('msan', False)
520 if pre_base_env.Bit('msan'):
521 pre_base_env.SetBits('clang')
524 DeclareBit('coverage_enabled', 'The build should be instrumented to generate'
525 'coverage information')
527 # If the environment variable BUILDBOT_BUILDERNAME is set, we can determine
528 # if we are running in a VM by the lack of a '-bare-' (aka bare metal) in the
529 # bot name. Otherwise if the builder name is not set, then assume real HW.
530 DeclareBit('running_on_vm', 'Returns true when environment is running in a VM')
531 builder = os.environ.get('BUILDBOT_BUILDERNAME')
532 if builder and builder.find('-bare-') == -1:
533 pre_base_env.SetBits('running_on_vm')
535 pre_base_env.ClearBits('running_on_vm')
537 DeclareBit('nacl_glibc', 'Use nacl-glibc for building untrusted code')
538 pre_base_env.SetBitFromOption('nacl_glibc', False)
540 # This function should be called ASAP after the environment is created, but
541 # after ExpandArguments.
542 SetUpArgumentBits(pre_base_env)
544 # Register PrintFinalReport only after SetUpArgumentBits since it references
545 # bits that get declared in SetUpArgumentBits
546 atexit.register(PrintFinalReport)
548 def DisableCrashDialog():
549 if sys.platform == 'win32':
552 # The double call is to preserve existing flags, as discussed at
553 # http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
554 new_flags = win32con.SEM_NOGPFAULTERRORBOX
555 existing_flags = win32api.SetErrorMode(new_flags)
556 win32api.SetErrorMode(existing_flags | new_flags)
558 if pre_base_env.Bit('disable_crash_dialog'):
561 # We want to pull CYGWIN setup in our environment or at least set flag
562 # nodosfilewarning. It does not do anything when CYGWIN is not involved
563 # so let's do it in all cases.
564 pre_base_env['ENV']['CYGWIN'] = os.environ.get('CYGWIN', 'nodosfilewarning')
566 # Note: QEMU_PREFIX_HOOK may influence test runs and sb translator invocations
567 pre_base_env['ENV']['QEMU_PREFIX_HOOK'] = os.environ.get('QEMU_PREFIX_HOOK', '')
569 # Allow the zero-based sandbox model to run insecurely.
570 # TODO(arbenson): remove this once binutils bug is fixed (see
571 # src/trusted/service_runtime/arch/x86_64/sel_addrspace_posix_x86_64.c)
572 if pre_base_env.Bit('x86_64_zero_based_sandbox'):
573 pre_base_env['ENV']['NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX'] = 1
575 if pre_base_env.Bit('werror'):
576 werror_flags = ['-Werror']
580 # Allow variadic macros
581 werror_flags = werror_flags + ['-Wno-variadic-macros']
583 if pre_base_env.Bit('clang'):
584 # Allow 'default' label in switch even when all enumeration cases
586 werror_flags += ['-Wno-covered-switch-default']
587 # Allow C++11 extensions (for "override")
588 werror_flags += ['-Wno-c++11-extensions']
591 # Method to make sure -pedantic, etc, are not stripped from the
592 # default env, since occasionally an engineer will be tempted down the
593 # dark -- but wide and well-trodden -- path of expediency and stray
594 # from the path of correctness.
596 def EnsureRequiredBuildWarnings(env):
597 if (env.Bit('linux') or env.Bit('mac')) and not env.Bit('android'):
598 required_env_flags = set(['-pedantic', '-Wall'] + werror_flags)
599 ccflags = set(env.get('CCFLAGS'))
601 if not required_env_flags.issubset(ccflags):
602 raise UserError('required build flags missing: '
603 + ' '.join(required_env_flags.difference(ccflags)))
605 # windows get a pass for now
608 pre_base_env.AddMethod(EnsureRequiredBuildWarnings)
610 # Expose MakeTempDir and MakeTempFile to scons scripts
611 def MakeEmptyFile(env, **kwargs):
612 fd, path = test_lib.MakeTempFile(env, **kwargs)
616 pre_base_env.AddMethod(test_lib.MakeTempDir)
617 pre_base_env.AddMethod(MakeEmptyFile)
619 # Method to add target suffix to name.
620 def NaClTargetArchSuffix(env, name):
621 return name + '_' + env['TARGET_FULLARCH'].replace('-', '_')
623 pre_base_env.AddMethod(NaClTargetArchSuffix)
626 # Generic Test Wrapper
628 # Add list of Flaky or Bad tests to skip per platform. A
629 # platform is defined as build type
630 # <BUILD_TYPE>-<SUBARCH>
635 # This is a list of tests that do not yet pass when using nacl-glibc.
636 # TODO(mseaborn): Enable more of these tests!
637 nacl_glibc_skiplist = set([
638 # Struct layouts differ.
640 # Syscall wrappers not implemented yet.
643 # Fails because clock() is not hooked up.
644 'run_timefuncs_test',
645 # Needs further investigation.
647 # This test fails with nacl-glibc: glibc reports an internal
648 # sanity check failure in free().
649 # TODO(robertm): This needs further investigation.
650 'run_ppapi_event_test',
651 'run_srpc_ro_file_test',
652 'run_ppapi_geturl_valid_test',
653 'run_ppapi_geturl_invalid_test',
654 # http://code.google.com/p/chromium/issues/detail?id=108131
655 # we would need to list all of the glibc components as
656 # web accessible resources in the extensions's manifest.json,
657 # not just the nexe and nmf file.
658 'run_ppapi_extension_mime_handler_browser_test',
660 nacl_glibc_skiplist.update(['%s_irt' % test for test in nacl_glibc_skiplist])
662 # Whitelist of tests to run for Non-SFI Mode. Note that typos here will
663 # not be caught automatically!
664 # TODO(mseaborn): Eventually we should run all of small_tests instead of
666 nonsfi_test_whitelist = set([
667 'run_clock_get_test',
673 'run_hello_world_test',
674 'run_irt_futex_test',
675 'run_malloc_realloc_calloc_free_test',
677 'run_nanosleep_test',
681 'run_sigaction_test',
684 'run_stack_alignment_test',
690 # If a test is not in one of these suites, it will probally not be run on a
691 # regular basis. These are the suites that will be run by the try bot or that
692 # a large number of users may run by hand.
693 MAJOR_TEST_SUITES = set([
697 # Tests using the pepper plugin, only run with chrome
698 # TODO(ncbray): migrate pepper_browser_tests to chrome_browser_tests
699 'pepper_browser_tests',
700 # Lightweight browser tests
701 'chrome_browser_tests',
703 'memcheck_bot_tests',
705 # Special testing environment for testing comparing x86 validators.
707 # Environment for validator difference testing
708 'validator_diff_tests',
709 # Subset of tests enabled for Non-SFI Mode.
713 # These are the test suites we know exist, but aren't run on a regular basis.
714 # These test suites are essentially shortcuts that run a specific subset of the
716 ACCEPTABLE_TEST_SUITES = set([
718 'dynamic_load_tests',
719 'eh_tests', # Tests for C++ exception handling
720 'exception_tests', # Tests for hardware exception handling
727 'sel_ldr_sled_tests',
730 'validator_modeling',
732 # Special testing of the decoder for the ARM validator.
736 # Under --mode=nacl_irt_test we build variants of numerous tests normally
737 # built under --mode=nacl. The test names and suite names for these
738 # variants are set (in IrtTestAddNodeToTestSuite, below) by appending _irt
739 # to the names used for the --mode=nacl version of the same tests.
740 MAJOR_TEST_SUITES |= set([name + '_irt'
741 for name in MAJOR_TEST_SUITES])
742 ACCEPTABLE_TEST_SUITES |= set([name + '_irt'
743 for name in ACCEPTABLE_TEST_SUITES])
745 # The major test suites are also acceptable names. Suite names are checked
746 # against this set in order to catch typos.
747 ACCEPTABLE_TEST_SUITES.update(MAJOR_TEST_SUITES)
750 def ValidateTestSuiteNames(suite_name, node_name):
751 if node_name is None:
752 node_name = '<unknown>'
754 # Prevent a silent failiure - strings are iterable!
755 if not isinstance(suite_name, (list, tuple)):
756 raise Exception("Test suites for %s should be specified as a list, "
757 "not as a %s: %s" % (node_name, type(suite_name).__name__,
761 raise Exception("No test suites are specified for %s. Set the 'broken' "
762 "parameter on AddNodeToTestSuite in the cases where there's a known "
763 "issue and you don't want the test to run" % (node_name,))
765 # Make sure each test is in at least one test suite we know will run
766 major_suites = set(suite_name).intersection(MAJOR_TEST_SUITES)
768 raise Exception("None of the test suites %s for %s are run on a "
769 "regular basis" % (repr(suite_name), node_name))
771 # Make sure a wierd test suite hasn't been inadvertantly specified
773 if s not in ACCEPTABLE_TEST_SUITES:
774 raise Exception("\"%s\" is not a known test suite. Either this is "
775 "a typo for %s, or it should be added to ACCEPTABLE_TEST_SUITES in "
776 "SConstruct" % (s, node_name))
778 BROKEN_TEST_COUNT = 0
781 def GetPlatformString(env):
782 build = env['BUILD_TYPE']
784 # If we are testing 'NACL' we really need the trusted info
785 if build=='nacl' and 'TRUSTED_ENV' in env:
786 trusted_env = env['TRUSTED_ENV']
787 build = trusted_env['BUILD_TYPE']
788 subarch = trusted_env['BUILD_SUBARCH']
790 subarch = env['BUILD_SUBARCH']
792 # Build the test platform string
793 return build + '-' + subarch
795 pre_base_env.AddMethod(GetPlatformString)
798 tests_to_disable_qemu = set([
799 # These tests do not work under QEMU but do work on ARM hardware.
801 # You should use the is_broken argument in preference to adding
802 # tests to this list.
804 # TODO(dschuff) some of these tests appear to work with the new QEMU.
806 # http://code.google.com/p/nativeclient/issues/detail?id=2437
807 # Note, for now these tests disable both the irt and non-irt variants
808 'run_atomic_ops_test', # still broken with qemu 2012/06/12
809 'run_atomic_ops_nexe_test',
810 'run_egyptian_cotton_test', # still broken with qemu 2012/06/12
811 'run_many_threads_sequential_test',
812 'run_mmap_atomicity_test', # still broken with qemu 2012/06/12
813 # http://code.google.com/p/nativeclient/issues/detail?id=2142
814 'run_nacl_semaphore_test',
815 'run_nacl_tls_unittest',
816 # subprocess needs to also have qemu prefix, which isn't supported
817 'run_subprocess_test',
818 # The next 2 tests seem flaky on QEMU
819 'run_srpc_manifest_file_test',
820 'run_srpc_message_untrusted_test',
821 'run_thread_stack_alloc_test',
822 'run_thread_suspension_test',
824 'run_dynamic_modify_test',
825 # qemu has bugs that make TestCatchingFault flaky (see
826 # http://code.google.com/p/nativeclient/issues/detail?id=3239), and
827 # we don't particularly need to measure performance under qemu.
828 'run_performance_test',
831 tests_to_disable = set()
832 if ARGUMENTS.get('disable_tests', '') != '':
833 tests_to_disable.update(ARGUMENTS['disable_tests'].split(','))
836 def ShouldSkipTest(env, node_name):
837 if (env.Bit('skip_trusted_tests')
838 and (env['NACL_BUILD_FAMILY'] == 'TRUSTED'
839 or env['NACL_BUILD_FAMILY'] == 'UNTRUSTED_IRT')):
842 if env.Bit('do_not_run_tests'):
843 # This hack is used for pnacl testing where we might build tests
844 # without running them on one bot and then transfer and run them on another.
845 # The skip logic only takes the first bot into account e.g. qemu
846 # restrictions, while it really should be skipping based on the second
847 # bot. By simply disabling the skipping completely we work around this.
850 # There are no known-to-fail tests any more, but this code is left
851 # in so that if/when we port to a new architecture or add a test
852 # that is known to fail on some platform(s), we can continue to have
853 # a central location to disable tests from running. NB: tests that
854 # don't *build* on some platforms need to be omitted in another way.
856 if node_name in tests_to_disable:
859 if env.UsingEmulator():
860 if node_name in tests_to_disable_qemu:
862 # For now also disable the irt variant
863 if node_name.endswith('_irt') and node_name[:-4] in tests_to_disable_qemu:
866 # Retrieve list of tests to skip on this platform
867 skiplist = bad_build_lists.get(env.GetPlatformString(), [])
868 if node_name in skiplist:
871 if env.Bit('nacl_glibc') and node_name in nacl_glibc_skiplist:
876 pre_base_env.AddMethod(ShouldSkipTest)
879 def AddImplicitTestSuites(suite_list, node_name):
880 if node_name in nonsfi_test_whitelist:
881 suite_list = suite_list + ['nonsfi_tests']
885 def AddNodeToTestSuite(env, node, suite_name, node_name, is_broken=False,
887 global BROKEN_TEST_COUNT
889 # CommandTest can return an empty list when it silently discards a test
893 assert node_name is not None
894 test_name_regex = r'run_.*_(unit)?test.*$'
895 assert re.match(test_name_regex, node_name), (
896 'test %r does not match "run_..._test" naming convention '
897 '(precise regex is %s)' % (node_name, test_name_regex))
899 suite_name = AddImplicitTestSuites(suite_name, node_name)
900 ValidateTestSuiteNames(suite_name, node_name)
904 if is_broken or is_flaky and env.Bit('disable_flaky_tests'):
905 # Only print if --verbose is specified
906 if not GetOption('brief_comstr'):
907 print '*** BROKEN ', node_name
908 BROKEN_TEST_COUNT += 1
909 env.Alias('broken_tests', node)
910 elif env.ShouldSkipTest(node_name):
911 print '*** SKIPPING ', env.GetPlatformString(), ':', node_name
912 env.Alias('broken_tests', node)
914 env.Alias('all_tests', node)
920 env.ComponentTestOutput(node_name, node)
921 test_name = node_name
923 # This is rather shady, but the tests need a name without dots so they match
925 # TODO(ncbray) node_name should not be optional.
926 test_name = os.path.basename(str(node[0].path))
927 if test_name.endswith('.out'):
928 test_name = test_name[:-4]
929 test_name = test_name.replace('.', '_')
930 SetTestName(node, test_name)
932 pre_base_env.AddMethod(AddNodeToTestSuite)
935 def TestBindsFixedTcpPort(env, node):
936 # This tells Scons that tests that bind a fixed TCP port should not
937 # run concurrently, because they would interfere with each other.
938 # These tests are typically tests for NaCl's GDB debug stub. The
939 # dummy filename used below is an arbitrary token that just has to
940 # match across the tests.
941 SideEffect(env.File('${SCONSTRUCT_DIR}/test_binds_fixed_tcp_port'), node)
943 pre_base_env.AddMethod(TestBindsFixedTcpPort)
946 # Convenient testing aliases
947 # NOTE: work around for scons non-determinism in the following two lines
948 Alias('sel_ldr_sled_tests', [])
950 Alias('small_tests', [])
951 Alias('medium_tests', [])
952 Alias('large_tests', [])
954 Alias('small_tests_irt', [])
955 Alias('medium_tests_irt', [])
956 Alias('large_tests_irt', [])
958 Alias('pepper_browser_tests', [])
959 Alias('chrome_browser_tests', [])
961 Alias('unit_tests', 'small_tests')
962 Alias('smoke_tests', ['small_tests', 'medium_tests'])
964 if pre_base_env.Bit('nacl_glibc'):
965 Alias('memcheck_bot_tests', ['small_tests'])
966 Alias('tsan_bot_tests', ['small_tests'])
968 Alias('memcheck_bot_tests', ['small_tests', 'medium_tests', 'large_tests'])
969 Alias('tsan_bot_tests', [])
977 pre_base_env.AddMethod(Banner)
981 # Define the platforms, and use them to define the path for the
982 # scons-out directory (aka TARGET_ROOT)
984 # Various variables in the scons environment are related to this, e.g.
986 # BUILD_ARCH: (arm, mips, x86)
987 # BUILD_SUBARCH: (32, 64)
990 DeclareBit('build_x86_32', 'Building binaries for the x86-32 architecture',
991 exclusive_groups='build_arch')
992 DeclareBit('build_x86_64', 'Building binaries for the x86-64 architecture',
993 exclusive_groups='build_arch')
994 DeclareBit('build_mips32', 'Building binaries for the MIPS architecture',
995 exclusive_groups='build_arch')
996 DeclareBit('build_arm_arm', 'Building binaries for the ARM architecture',
997 exclusive_groups='build_arch')
998 DeclareBit('target_x86_32', 'Tools being built will process x86-32 binaries',
999 exclusive_groups='target_arch')
1000 DeclareBit('target_x86_64', 'Tools being built will process x86-36 binaries',
1001 exclusive_groups='target_arch')
1002 DeclareBit('target_mips32', 'Tools being built will process MIPS binaries',
1003 exclusive_groups='target_arch')
1004 DeclareBit('target_arm_arm', 'Tools being built will process ARM binaries',
1005 exclusive_groups='target_arch')
1007 # Shorthand for either the 32 or 64 bit version of x86.
1008 DeclareBit('build_x86', 'Building binaries for the x86 architecture')
1009 DeclareBit('target_x86', 'Tools being built will process x86 binaries')
1011 DeclareBit('build_arm', 'Building binaries for the arm architecture')
1012 DeclareBit('target_arm', 'Tools being built will process arm binaries')
1015 def MakeArchSpecificEnv(platform=None):
1016 env = pre_base_env.Clone()
1017 if platform is None:
1018 platform = GetTargetPlatform()
1020 arch = pynacl.platform.GetArch(platform)
1021 if pynacl.platform.IsArch64Bit(platform):
1026 env.Replace(BUILD_FULLARCH=platform)
1027 env.Replace(BUILD_ARCHITECTURE=arch)
1028 env.Replace(BUILD_SUBARCH=subarch)
1029 env.Replace(TARGET_FULLARCH=platform)
1030 env.Replace(TARGET_ARCHITECTURE=arch)
1031 env.Replace(TARGET_SUBARCH=subarch)
1033 # Example: PlatformBit('build', 'x86-32') -> build_x86_32
1034 def PlatformBit(prefix, platform):
1035 return "%s_%s" % (prefix, platform.replace('-', '_'))
1037 env.SetBits(PlatformBit('build', platform))
1038 env.SetBits(PlatformBit('target', platform))
1040 if env.Bit('build_x86_32') or env.Bit('build_x86_64'):
1041 env.SetBits('build_x86')
1042 if env.Bit('build_arm_arm'):
1043 env.SetBits('build_arm')
1045 if env.Bit('target_x86_32') or env.Bit('target_x86_64'):
1046 env.SetBits('target_x86')
1047 if env.Bit('target_arm_arm'):
1048 env.SetBits('target_arm')
1050 env.Replace(BUILD_ISA_NAME=platform)
1052 if env.Bit('target_mips32'):
1053 # This is a silent default on MIPS.
1054 env.SetBits('bitcode')
1056 # Determine where the object files go
1057 env.Replace(BUILD_TARGET_NAME=platform)
1058 # This may be changed later; see target_variant_map, below.
1059 env.Replace(TARGET_VARIANT='')
1060 env.Replace(TARGET_ROOT=
1061 '${DESTINATION_ROOT}/${BUILD_TYPE}-${BUILD_TARGET_NAME}${TARGET_VARIANT}')
1066 pre_base_env.AddMethod(lambda self: ARGUMENTS.get('running_on_valgrind'),
1067 'IsRunningUnderValgrind')
1069 DeclareBit('with_leakcheck', 'Running under Valgrind leak checker')
1071 def RunningUnderLeakCheck():
1072 run_under = ARGUMENTS.get('run_under')
1074 extra_args = ARGUMENTS.get('run_under_extra_args')
1076 run_under += extra_args
1077 if run_under.find('leak-check=full') > 0:
1081 if RunningUnderLeakCheck():
1082 pre_base_env.SetBits('with_leakcheck')
1085 def HasSuffix(item, suffix):
1086 if isinstance(item, str):
1087 return item.endswith(suffix)
1088 elif hasattr(item, '__getitem__'):
1089 return HasSuffix(item[0], suffix)
1091 return item.path.endswith(suffix)
1094 def StripSuffix(string, suffix):
1095 assert string.endswith(suffix)
1096 return string[:-len(suffix)]
1099 def DualLibrary(env, lib_name, *args, **kwargs):
1100 """Builder to build both .a and _shared.a library in one step.
1103 env: Environment in which we were called.
1104 lib_name: Library name.
1105 args: Positional arguments.
1106 kwargs: Keyword arguments.
1108 static_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.os')]
1109 shared_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.o')]
1110 # Built static library as ususal.
1111 env.ComponentLibrary(lib_name, static_objs, **kwargs)
1112 # For coverage bots, we only want one object file since two versions would
1113 # write conflicting information to the same .gdca/.gdna files.
1114 if env.Bit('coverage_enabled'): return
1115 # Build a static library using -fPIC for the .o's.
1116 if env.Bit('linux'):
1117 env_shared = env.Clone(OBJSUFFIX='.os')
1118 env_shared.Append(CCFLAGS=['-fPIC'])
1119 # -fPIE overrides -fPIC, and shared libraries should not be linked
1121 env_shared.FilterOut(CCFLAGS=['-fPIE'])
1122 env_shared.ComponentLibrary(lib_name + '_shared', shared_objs, **kwargs)
1123 # for arm trusted we usually build -static
1124 env_shared.FilterOut(LINKFLAGS=['-static'])
1126 def DualObject(env, *args, **kwargs):
1127 """Builder to build both .o and .os in one step.
1130 env: Environment in which we were called.
1131 args: Positional arguments.
1132 kwargs: Keyword arguments.
1134 # Built static library as ususal.
1135 ret = env.ComponentObject(*args, **kwargs)
1136 # For coverage bots, we only want one object file since two versions would
1137 # write conflicting information to the same .gdca/.gdna files.
1138 if env.Bit('coverage_enabled'): return ret
1139 # Build a static library using -fPIC for the .o's.
1140 if env.Bit('linux'):
1141 env_shared = env.Clone(OBJSUFFIX='.os')
1142 env_shared.Append(CCFLAGS=['-fPIC'])
1143 ret += env_shared.ComponentObject(*args, **kwargs)
1147 def AddDualLibrary(env):
1148 env.AddMethod(DualLibrary)
1149 env.AddMethod(DualObject)
1150 # For coverage bots we only build one set of objects and we always set
1151 # '-fPIC' so we do not need a "special" library.
1152 if env.Bit('coverage_enabled'):
1153 env['SHARED_LIBS_SPECIAL'] = False
1155 env['SHARED_LIBS_SPECIAL'] = env.Bit('linux')
1158 # In prebuild mode we ignore the dependencies so that stuff does
1159 # NOT get build again
1160 # Optionally ignore the build process.
1161 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
1162 pre_base_env.SetBitFromOption('prebuilt', False)
1165 # HELPERS FOR TEST INVOLVING TRUSTED AND UNTRUSTED ENV
1166 def GetEmulator(env):
1167 emulator = ARGUMENTS.get('force_emulator')
1168 if emulator is None and 'TRUSTED_ENV' in env:
1169 emulator = env['TRUSTED_ENV'].get('EMULATOR')
1172 pre_base_env.AddMethod(GetEmulator)
1174 def UsingEmulator(env):
1175 return bool(env.GetEmulator())
1177 pre_base_env.AddMethod(UsingEmulator)
1180 def GetValidator(env, validator):
1181 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1182 if 'TRUSTED_ENV' not in env:
1185 if validator is None:
1186 if env.Bit('build_arm'):
1187 validator = 'arm-ncval-core'
1188 elif env.Bit('build_mips32'):
1189 validator = 'mips-ncval-core'
1191 if env.Bit('validator_ragel'):
1192 validator = 'ncval_new'
1196 trusted_env = env['TRUSTED_ENV']
1197 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}%s${PROGSUFFIX}' %
1200 pre_base_env.AddMethod(GetValidator)
1203 # Perform os.path.abspath rooted at the directory SConstruct resides in.
1204 def SConstructAbsPath(env, path):
1205 return os.path.normpath(os.path.join(env['MAIN_DIR'], path))
1207 pre_base_env.AddMethod(SConstructAbsPath)
1210 def GetPlatformBuildTargetDir(env):
1211 # Currently we do not support any cross OS compiles, eventually the OS name
1212 # will probably be passed in through arguments.
1213 os_name = pynacl.platform.GetOS()
1215 # Currently 32/64 share the same tool build target directory. When we have
1216 # separate toolchains for each the architectures will probably have to use
1217 # the Arch3264() variant.
1218 build_arch = pynacl.platform.GetArch(GetBuildPlatform())
1220 return '%s_%s' % (os_name, build_arch)
1222 pre_base_env.AddMethod(GetPlatformBuildTargetDir)
1225 def GetToolchainDir(env, platform_build_dir=None, toolchain_name=None,
1226 target_arch=None, is_pnacl=None, lib_name=None):
1227 if platform_build_dir is None:
1228 platform_build_dir = env.GetPlatformBuildTargetDir()
1230 if toolchain_name is None:
1231 # Fill in default arguments based on environment.
1232 if is_pnacl is None:
1233 is_pnacl = env.Bit('bitcode')
1234 if lib_name is None:
1235 if is_pnacl or not env.Bit('nacl_glibc'):
1240 if target_arch is None:
1241 target_arch = pynacl.platform.GetArch(GetTargetPlatform())
1244 target_env = 'pnacl'
1246 target_env = 'nacl_%s' % target_arch
1248 # See if we have a custom toolchain directory set.
1250 toolchain_arg = 'pnacl_%s_dir' % lib_name
1252 toolchain_arg = 'nacl_%s_dir' % lib_name
1254 custom_toolchain_dir = ARGUMENTS.get(toolchain_arg, None)
1255 if custom_toolchain_dir:
1256 return env.SConstructAbsPath(custom_toolchain_dir)
1258 # Get the standard toolchain name since no directory custom was found.
1260 target_env = 'pnacl'
1262 target_env = 'nacl_%s' % target_arch
1263 toolchain_name = '%s_%s' % (target_env, lib_name)
1265 # Get the absolute path for the platform build directory and toolchain.
1266 toolchain_sub_dir = os.path.join('toolchain',
1269 return env.SConstructAbsPath(toolchain_sub_dir)
1271 pre_base_env.AddMethod(GetToolchainDir)
1275 sel_ldr = ARGUMENTS.get('force_sel_ldr')
1277 return env.File(env.SConstructAbsPath(sel_ldr))
1279 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1280 if 'TRUSTED_ENV' not in env:
1283 trusted_env = env['TRUSTED_ENV']
1284 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}sel_ldr${PROGSUFFIX}')
1286 pre_base_env.AddMethod(GetSelLdr)
1289 def GetSelLdrSeccomp(env):
1290 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1291 if 'TRUSTED_ENV' not in env:
1294 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1297 trusted_env = env['TRUSTED_ENV']
1298 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}'
1299 'sel_ldr_seccomp${PROGSUFFIX}')
1301 pre_base_env.AddMethod(GetSelLdrSeccomp)
1304 def SupportsSeccompBpfSandbox(env):
1305 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1308 # The gcov runtime does some extra calls (such as 'access') that
1309 # are not permitted by the policy.
1310 if env.Bit('coverage_enabled'):
1313 # This is a lame detection if seccomp bpf filters are supported by the kernel.
1314 # We suppose that any Linux kernel v3.2+ supports it, but it is only true
1315 # for Ubuntu kernels. Seccomp BPF filters reached the mainline at 3.5,
1316 # so this check will be wrong on some relatively old non-Ubuntu Linux distros.
1317 kernel_version = map(int, platform.release().split('.', 2)[:2])
1318 return kernel_version >= [3, 2]
1320 pre_base_env.AddMethod(SupportsSeccompBpfSandbox)
1323 def GetBootstrap(env):
1325 # Bootstrap doens't currently work with MSan. However, MSan is only
1326 # available on x86_64 where we don't need bootstrap anyway.
1328 if 'TRUSTED_ENV' in env:
1329 trusted_env = env['TRUSTED_ENV']
1330 if trusted_env.Bit('linux'):
1331 template_digits = 'X' * 16
1332 return (trusted_env.File('${STAGING_DIR}/nacl_helper_bootstrap'),
1333 ['--r_debug=0x' + template_digits,
1334 '--reserved_at_zero=0x' + template_digits])
1337 pre_base_env.AddMethod(GetBootstrap)
1339 def AddBootstrap(env, executable, args):
1340 bootstrap, bootstrap_args = env.GetBootstrap()
1341 if bootstrap is None:
1342 return [executable] + args
1344 return [bootstrap, executable] + bootstrap_args + args
1346 pre_base_env.AddMethod(AddBootstrap)
1349 def GetNonSfiLoader(env):
1350 if env.Bit('use_newlib_nonsfi_loader'):
1351 return nacl_env.GetTranslatedNexe(nacl_env.File(
1352 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}'))
1354 if 'TRUSTED_ENV' not in env:
1356 return env['TRUSTED_ENV'].File(
1357 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}')
1359 pre_base_env.AddMethod(GetNonSfiLoader)
1362 def GetIrtNexe(env, chrome_irt=False):
1363 image = ARGUMENTS.get('force_irt')
1365 return env.SConstructAbsPath(image)
1368 return nacl_irt_env.File('${STAGING_DIR}/irt.nexe')
1370 return nacl_irt_env.File('${STAGING_DIR}/irt_core.nexe')
1372 pre_base_env.AddMethod(GetIrtNexe)
1374 def ApplyTLSEdit(env, nexe_name, raw_nexe):
1375 # If the environment was built elsewhere, we do not need to apply tls_edit
1376 # since it only needs to be done during building.
1377 if env.Bit('built_elsewhere'):
1378 return env.File(nexe_name)
1380 tls_edit_exe = env['BUILD_ENV'].File('${STAGING_DIR}/tls_edit${PROGSUFFIX}')
1383 [tls_edit_exe, raw_nexe],
1384 '${SOURCES[0]} --verbose ${SOURCES[1:]} ${TARGET}')
1386 pre_base_env.AddMethod(ApplyTLSEdit)
1388 def CommandValidatorTestNacl(env, name, image,
1389 validator_flags=None,
1393 validator = env.GetValidator(validator)
1394 if validator is None:
1395 print 'WARNING: no validator found. Skipping test %s' % name
1398 if validator_flags is None:
1399 validator_flags = []
1401 if env.Bit('pnacl_generate_pexe'):
1404 command = [validator] + validator_flags + [image]
1405 return env.CommandTest(name, command, size, **extra)
1407 pre_base_env.AddMethod(CommandValidatorTestNacl)
1410 def ExtractPublishedFiles(env, target_name):
1411 run_files = ['$STAGING_DIR/' + os.path.basename(published_file.path)
1412 for published_file in env.GetPublished(target_name, 'run')]
1413 nexe = '$STAGING_DIR/%s${PROGSUFFIX}' % target_name
1414 return [env.File(file) for file in run_files + [nexe]]
1416 pre_base_env.AddMethod(ExtractPublishedFiles)
1419 # Only include the chrome side of the build if present.
1420 if os.path.exists(pre_base_env.File(
1421 '#/../ppapi/native_client/chrome_main.scons').abspath):
1422 SConscript('#/../ppapi/native_client/chrome_main.scons',
1423 exports=['pre_base_env'])
1424 enable_chrome = True
1426 def AddChromeFilesFromGroup(env, file_group):
1428 pre_base_env.AddMethod(AddChromeFilesFromGroup)
1429 enable_chrome = False
1430 DeclareBit('enable_chrome_side',
1431 'Is the chrome side present.')
1432 pre_base_env.SetBitFromOption('enable_chrome_side', enable_chrome)
1434 def ProgramNameForNmf(env, basename):
1435 """ Create an architecture-specific filename that can be used in an NMF URL.
1437 if env.Bit('pnacl_generate_pexe'):
1440 return '%s_%s' % (basename, env.get('TARGET_FULLARCH'))
1442 pre_base_env.AddMethod(ProgramNameForNmf)
1445 def SelUniversalTest(env,
1449 sel_universal_flags=None,
1451 # The dynamic linker's ability to receive arguments over IPC at
1452 # startup currently requires it to reject the plugin's first
1453 # connection, but this interferes with the sel_universal-based
1454 # testing because sel_universal does not retry the connection.
1455 # TODO(mseaborn): Fix by retrying the connection or by adding an
1456 # option to ld.so to disable its argv-over-IPC feature.
1457 if env.Bit('nacl_glibc') and not env.Bit('nacl_static_link'):
1460 # TODO(petarj): Sel_universal hangs on qemu-mips. Enable when fixed.
1461 if env.Bit('target_mips32') and env.UsingEmulator():
1464 if sel_universal_flags is None:
1465 sel_universal_flags = []
1467 # When run under qemu, sel_universal must sneak in qemu to the execv
1468 # call that spawns sel_ldr.
1469 if env.UsingEmulator():
1470 sel_universal_flags.append('--command_prefix')
1471 sel_universal_flags.append(env.GetEmulator())
1473 if 'TRUSTED_ENV' not in env:
1475 sel_universal = env['TRUSTED_ENV'].File(
1476 '${STAGING_DIR}/${PROGPREFIX}sel_universal${PROGSUFFIX}')
1478 # Point to sel_ldr using an environment variable.
1479 sel_ldr = env.GetSelLdr()
1481 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1483 kwargs.setdefault('osenv', []).append('NACL_SEL_LDR=' + sel_ldr.abspath)
1484 bootstrap, _ = env.GetBootstrap()
1485 if bootstrap is not None:
1486 kwargs['osenv'].append('NACL_SEL_LDR_BOOTSTRAP=%s' % bootstrap.abspath)
1488 node = CommandSelLdrTestNacl(env,
1492 loader=sel_universal,
1493 sel_ldr_flags=sel_universal_flags,
1494 skip_bootstrap=True,
1496 if not env.Bit('built_elsewhere'):
1497 env.Depends(node, sel_ldr)
1498 if bootstrap is not None:
1499 env.Depends(node, bootstrap)
1502 pre_base_env.AddMethod(SelUniversalTest)
1505 def MakeNaClLogOption(env, target):
1506 """ Make up a filename related to the [target], for use with NACLLOG.
1507 The file should end up in the build directory (scons-out/...).
1509 # NOTE: to log to the source directory use file.srcnode().abspath instead.
1510 # See http://www.scons.org/wiki/File%28%29
1511 return env.File(target + '.nacllog').abspath
1513 pre_base_env.AddMethod(MakeNaClLogOption)
1515 def MakeVerboseExtraOptions(env, target, log_verbosity, extra):
1516 """ Generates **extra options that will give access to service runtime logs,
1517 at a given log_verbosity. Slips the options into the given extra dict. """
1518 log_file = env.MakeNaClLogOption(target)
1519 extra['log_file'] = log_file
1520 extra_env = ['NACLLOG=%s' % log_file,
1521 'NACLVERBOSITY=%d' % log_verbosity]
1522 extra['osenv'] = extra.get('osenv', []) + extra_env
1524 pre_base_env.AddMethod(MakeVerboseExtraOptions)
1526 def ShouldUseVerboseOptions(env, extra):
1527 """ Heuristic for setting up Verbose NACLLOG options. """
1528 return ('process_output_single' in extra or
1529 'log_golden' in extra)
1531 pre_base_env.AddMethod(ShouldUseVerboseOptions)
1534 DeclareBit('tests_use_irt', 'Non-browser tests also load the IRT image', False)
1536 # Bit to be set by individual test/nacl.scons files that need to opt out.
1537 DeclareBit('nonstable_bitcode', 'Tests use non-stable bitcode features', False)
1540 def GetFinalizedPexe(env, pexe):
1541 """ Prep and finalize the ABI for a given pexe if needed.
1543 if not env.Bit('pnacl_generate_pexe') or env.Bit('nonstable_bitcode'):
1546 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1547 # file instead. There are currently some canned nexe tests in build.scons.
1548 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1551 # Otherwise, finalize during the build step, since there is no finalize tool
1552 # that can run on triggered bots such as the ARM HW bots.
1553 pexe_name = pexe.abspath
1554 final_name = StripSuffix(pexe_name, '.nonfinal.pexe') + '.final.pexe'
1555 # Make sure the pexe doesn't get removed by the fake builders when
1558 node = env.Command(target=final_name, source=[pexe_name],
1559 action=[Action('${PNACLFINALIZECOM}',
1560 '${PNACLFINALIZECOMSTR}')])
1561 assert len(node) == 1, node
1564 pre_base_env.AddMethod(GetFinalizedPexe)
1567 # Translate the given pexe.
1568 def GetTranslatedNexe(env, pexe):
1569 # First finalize the pexe.
1570 pexe = GetFinalizedPexe(env, pexe)
1572 # Then check if we need to translate.
1573 # Check if we started with a pexe, so there is actually a translation step.
1574 if not env.Bit('pnacl_generate_pexe'):
1577 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1578 # file instead. There are currently some canned nexe tests in build.scons.
1579 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1582 # Often there is a build step (do_not_run_tests=1) and a test step
1583 # (which is run with -j1). Normally we want to translate in the build step
1584 # so we can translate in parallel. However when we do sandboxed translation
1585 # on arm hw, we do the build step on x86 and translation on arm, so we have
1586 # to force the translation to be done in the test step. Hence,
1587 # we check the bit 'translate_in_build_step' / check if we are
1589 if not env.Bit('translate_in_build_step') and env.Bit('do_not_run_tests'):
1592 pexe_name = pexe.abspath
1593 # Tidy up the suffix (remove the .final.pexe or .nonfinal.pexe),
1594 # depending on whether or not the pexe was finalized.
1595 suffix_to_strip = '.final.pexe'
1596 if not pexe_name.endswith(suffix_to_strip):
1597 suffix_to_strip = '.nonfinal.pexe'
1598 nexe_name = StripSuffix(pexe_name, suffix_to_strip) + '.nexe'
1599 # Make sure the pexe doesn't get removed by the fake builders when
1602 if env.Bit('nonstable_bitcode'):
1603 env.Append(TRANSLATEFLAGS=['--allow-llvm-bitcode-input'])
1604 node = env.Command(target=nexe_name, source=[pexe_name],
1605 action=[Action('${TRANSLATECOM}', '${TRANSLATECOMSTR}')])
1606 assert len(node) == 1, node
1609 pre_base_env.AddMethod(GetTranslatedNexe)
1612 def CommandTestFileDumpCheck(env,
1617 """Create a test that disassembles a binary (|target|) and checks for
1618 patterns in the |check_file|. Disassembly is done using |objdump_flags|.
1621 # Do not try to run OBJDUMP if 'built_elsewhere', since that *might* mean
1622 # that a toolchain is not even present. E.g., the arm hw buildbots do
1623 # not have the pnacl toolchain. We should be able to look for the host
1624 # ARM objdump though... a TODO(jvoung) for when there is time.
1625 if env.Bit('built_elsewhere'):
1627 target = env.GetTranslatedNexe(target)
1628 return env.CommandTestFileCheck(name,
1629 ['${OBJDUMP}', objdump_flags, target],
1632 pre_base_env.AddMethod(CommandTestFileDumpCheck)
1635 def CommandTestFileCheck(env, name, cmd, check_file):
1636 """Create a test that runs a |cmd| (array of strings),
1637 which is expected to print to stdout. The results
1638 of stdout will then be piped to the file_check.py tool which
1639 will search for the regexes specified in |check_file|. """
1641 return env.CommandTest(name,
1643 env.File('${SCONSTRUCT_DIR}/tools/file_check.py'),
1645 # don't run ${PYTHON} under the emulator.
1646 direct_emulation=False)
1648 pre_base_env.AddMethod(CommandTestFileCheck)
1650 def CommandSelLdrTestNacl(env, name, nexe,
1656 # True for *.nexe statically linked with glibc
1658 skip_bootstrap=False,
1659 wrapper_program_prefix=None,
1660 # e.g., [ 'python', 'time_check.py', '--' ]
1662 # Disable all sel_ldr tests for windows under coverage.
1663 # Currently several .S files block sel_ldr from being instrumented.
1664 # See http://code.google.com/p/nativeclient/issues/detail?id=831
1665 if ('TRUSTED_ENV' in env and
1666 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1667 env['TRUSTED_ENV'].Bit('windows')):
1670 # The nexe might be a pexe that needs finalization, and translation.
1671 nexe = env.GetTranslatedNexe(nexe)
1674 if args is not None:
1677 if env.Bit('pnacl_unsandboxed') or (env.Bit('nonsfi_nacl') and
1678 not env.Bit('tests_use_irt')):
1679 # Run unsandboxed executable directly, without sel_ldr.
1680 return env.CommandTest(name, command, size, **extra)
1683 if env.Bit('nonsfi_nacl'):
1684 loader = env.GetNonSfiLoader()
1686 loader = env.GetSelLdr()
1688 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1691 # Avoid problems with [] as default arguments
1692 if sel_ldr_flags is None:
1695 # Avoid modifying original list
1696 sel_ldr_flags = list(sel_ldr_flags)
1698 # Disable the validator if running a GLibC test under Valgrind.
1699 # http://code.google.com/p/nativeclient/issues/detail?id=1799
1700 if env.IsRunningUnderValgrind() and env.Bit('nacl_glibc'):
1701 sel_ldr_flags += ['-cc']
1702 # https://code.google.com/p/nativeclient/issues/detail?id=3158
1703 # We don't currently have valgrind.so for LD_PRELOAD to use. That .so
1704 # is not used for newlib.
1705 # TODO(sehr): add valgrind.so built for NaCl.
1708 # Skip platform qualification checks on configurations with known issues.
1709 if env.GetEmulator() or env.IsRunningUnderValgrind():
1710 sel_ldr_flags += ['-Q']
1712 # Skip validation if we are using the x86-64 zero-based sandbox.
1713 # TODO(arbenson): remove this once the validator supports the x86-64
1714 # zero-based sandbox model.
1715 if env.Bit('x86_64_zero_based_sandbox'):
1716 sel_ldr_flags += ['-c']
1718 # The glibc modifications only make sense for nacl_env tests.
1719 # But this function gets used by some base_env (i.e. src/trusted/...)
1720 # tests too. Don't add the --nacl_glibc changes to the command
1721 # line for those cases.
1722 if env.Bit('nacl_glibc') and env['NACL_BUILD_FAMILY'] != 'TRUSTED':
1723 if not glibc_static and not env.Bit('nacl_static_link'):
1724 command = ['${NACL_SDK_LIB}/runnable-ld.so',
1725 # Locally-built shared libraries come from ${LIB_DIR}
1726 # while toolchain-provided ones come from ${NACL_SDK_LIB}.
1727 '--library-path', '${LIB_DIR}:${NACL_SDK_LIB}'] + command
1728 # Enable file access.
1729 sel_ldr_flags += ['-a']
1731 # Turn off sandbox for mac so coverage files can be written out.
1732 if ('TRUSTED_ENV' in env and
1733 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1734 env.Bit('host_mac') and
1735 '-a' not in sel_ldr_flags):
1736 sel_ldr_flags += ['-a']
1738 if env.Bit('tests_use_irt'):
1739 sel_ldr_flags += ['-B', nacl_env.GetIrtNexe()]
1742 loader_cmd = [loader]
1744 loader_cmd = env.AddBootstrap(loader, [])
1746 if env.Bit('nonsfi_nacl'):
1747 # nonsfi_loader does not accept the same flags as sel_ldr yet, so
1748 # we ignore sel_ldr_flags here.
1749 command = [loader] + command
1751 command = loader_cmd + sel_ldr_flags + ['--'] + command
1753 if env.Bit('host_linux'):
1754 extra['using_nacl_signal_handler'] = True
1756 if env.ShouldUseVerboseOptions(extra):
1757 env.MakeVerboseExtraOptions(name, log_verbosity, extra)
1759 node = env.CommandTest(name, command, size, posix_path=True,
1760 wrapper_program_prefix=wrapper_program_prefix, **extra)
1761 if env.Bit('tests_use_irt'):
1762 env.Alias('irt_tests', node)
1765 pre_base_env.AddMethod(CommandSelLdrTestNacl)
1768 TEST_EXTRA_ARGS = ['stdin', 'log_file',
1769 'stdout_golden', 'stderr_golden', 'log_golden',
1770 'filter_regex', 'filter_inverse', 'filter_group_only',
1771 'osenv', 'arch', 'subarch', 'exit_status', 'track_cmdtime',
1772 'num_runs', 'process_output_single',
1773 'process_output_combined', 'using_nacl_signal_handler',
1774 'declares_exit_status', 'time_warning', 'time_error']
1776 TEST_TIME_THRESHOLD = {
1783 # Valgrind handles SIGSEGV in a way our testing tools do not expect.
1784 UNSUPPORTED_VALGRIND_EXIT_STATUS = ['trusted_sigabrt',
1785 'untrusted_sigill' ,
1786 'untrusted_segfault',
1787 'untrusted_sigsegv_or_equivalent',
1789 'trusted_sigsegv_or_equivalent']
1792 def GetPerfEnvDescription(env):
1793 """Return a string describing architecture, library, etc. options.
1795 This function attempts to gather a string that might inform why a performance
1796 change has occurred.
1798 description_list = [env['TARGET_FULLARCH']]
1799 # Using a list to keep the order consistent.
1800 bit_to_description = [ ('bitcode', ('pnacl', 'nnacl')),
1801 ('translate_fast', ('fast', '')),
1802 ('nacl_glibc', ('glibc', 'newlib')),
1803 ('nacl_static_link', ('static', 'dynamic')),
1805 for (bit, (descr_yes, descr_no)) in bit_to_description:
1807 additional = descr_yes
1809 additional = descr_no
1811 description_list.append(additional)
1812 return '_'.join(description_list)
1814 pre_base_env.AddMethod(GetPerfEnvDescription)
1819 def GetTestName(target):
1820 key = str(target.path)
1821 return TEST_NAME_MAP.get(key, key)
1823 pre_base_env['GetTestName'] = GetTestName
1826 def SetTestName(node, name):
1827 for target in Flatten(node):
1828 TEST_NAME_MAP[str(target.path)] = name
1831 def ApplyTestWrapperCommand(command_args, extra_deps):
1832 new_args = ARGUMENTS['test_wrapper'].split()
1833 for input_file in extra_deps:
1834 new_args.extend(['-F', input_file])
1835 for arg in command_args:
1836 if isinstance(arg, str):
1837 new_args.extend(['-a', arg])
1839 new_args.extend(['-f', arg])
1843 def CommandTest(env, name, command, size='small', direct_emulation=True,
1844 extra_deps=[], posix_path=False, capture_output=True,
1845 capture_stderr=True, wrapper_program_prefix=None,
1846 scale_timeout=None, **extra):
1847 if not name.endswith('.out') or name.startswith('$'):
1848 raise Exception('ERROR: bad test filename for test output %r' % name)
1850 if env.IsRunningUnderValgrind():
1852 elif env.Bit('asan'):
1853 skip = 'AddressSanitizer'
1856 # Valgrind tends to break crash tests by changing the exit status.
1857 # So far, tests using declares_exit_status are crash tests. If this
1858 # changes, we will have to find a way to make declares_exit_status
1859 # work with Valgrind.
1860 if (skip is not None and
1861 (extra.get('exit_status') in UNSUPPORTED_VALGRIND_EXIT_STATUS or
1862 bool(int(extra.get('declares_exit_status', 0))))):
1863 print 'Skipping death test "%s" under %s' % (name, skip)
1867 extra.setdefault('osenv', [])
1868 # Ensure that 'osenv' is a list.
1869 if isinstance(extra['osenv'], str):
1870 extra['osenv'] = [extra['osenv']]
1871 # ASan normally intercepts SIGSEGV and disables our SIGSEGV signal
1872 # handler, which interferes with various NaCl tests, including the
1873 # platform qualification test built into sel_ldr. We fix this by
1874 # telling ASan not to mess with SIGSEGV.
1875 asan_options = ['handle_segv=0']
1876 if env.Bit('host_mac') and int(platform.mac_ver()[0].split('.')[1]) < 7:
1877 # MacOS 10.6 has a bug in the libsandbox system library where it
1878 # makes a memcmp call that reads off the end of a malloc'd block.
1879 # The bug appears to be harmless, but trips an ASan report. So
1880 # tell ASan to suppress memcmp checks.
1881 asan_options.append('strict_memcmp=0')
1882 # TODO(mcgrathr): Remove this when we clean up all the crufty old
1883 # code to be leak-free.
1884 # https://code.google.com/p/nativeclient/issues/detail?id=3874
1885 asan_options.append('detect_leaks=0')
1886 # Note that the ASan runtime doesn't use : specifically as a separator.
1887 # It actually just looks for "foo=" anywhere in the string with strstr,
1888 # so any separator will do. The most obvious choices, ' ', ',', and ';'
1889 # all cause command_tester.py to split things up and get confused.
1890 extra['osenv'].append('ASAN_OPTIONS=' + ':'.join(asan_options))
1892 name = '${TARGET_ROOT}/test_results/' + name
1893 # NOTE: using the long version of 'name' helps distinguish opt vs dbg
1894 max_time = TEST_TIME_THRESHOLD[size]
1895 if 'scale_timeout' in ARGUMENTS:
1896 max_time = max_time * int(ARGUMENTS['scale_timeout'])
1898 max_time = max_time * scale_timeout
1900 if env.Bit('nacl_glibc'):
1901 suite = 'nacl_glibc'
1903 suite = 'nacl_newlib'
1904 if env.Bit('bitcode'):
1907 script_flags = ['--name', '%s.${GetTestName(TARGET)}' % suite,
1908 '--time_warning', str(max_time),
1909 '--time_error', str(10 * max_time),
1912 run_under = ARGUMENTS.get('run_under')
1914 run_under_extra_args = ARGUMENTS.get('run_under_extra_args')
1915 if run_under_extra_args:
1916 run_under = run_under + ',' + run_under_extra_args
1917 script_flags.append('--run_under')
1918 script_flags.append(run_under)
1920 emulator = env.GetEmulator()
1921 if emulator and direct_emulation:
1922 command = [emulator] + command
1924 # test wrapper should go outside of emulators like qemu, since the
1925 # test wrapper code is not emulated.
1926 if wrapper_program_prefix is not None:
1927 command = wrapper_program_prefix + command
1929 script_flags.append('--perf_env_description')
1930 script_flags.append(env.GetPerfEnvDescription())
1932 # Add architecture info.
1933 extra['arch'] = env['BUILD_ARCHITECTURE']
1934 extra['subarch'] = env['BUILD_SUBARCH']
1936 for flag_name, flag_value in extra.iteritems():
1937 assert flag_name in TEST_EXTRA_ARGS, repr(flag_name)
1938 if isinstance(flag_value, list):
1939 # Options to command_tester.py which are actually lists must not be
1940 # separated by whitespace. This stringifies the lists with a separator
1941 # char to satisfy command_tester.
1942 flag_value = command_tester.StringifyList(flag_value)
1943 # do not add --flag + |flag_name| |flag_value| if
1944 # |flag_value| is false (empty).
1946 script_flags.append('--' + flag_name)
1947 # Make sure flag values are strings (or SCons objects) when building
1948 # up the command. Right now, this only means convert ints to strings.
1949 if isinstance(flag_value, int):
1950 flag_value = str(flag_value)
1951 script_flags.append(flag_value)
1954 if not capture_output:
1955 script_flags.extend(['--capture_output', '0'])
1956 if not capture_stderr:
1957 script_flags.extend(['--capture_stderr', '0'])
1959 # Set command_tester.py's output filename. We skip this when using
1960 # test_wrapper because the run_test_via_ssh.py wrapper does not have
1961 # the ability to copy result files back from the remote host.
1962 if 'test_wrapper' not in ARGUMENTS:
1963 script_flags.extend(['--output_stamp', name])
1965 test_script = env.File('${SCONSTRUCT_DIR}/tools/command_tester.py')
1966 extra_deps = extra_deps + [env.File('${SCONSTRUCT_DIR}/tools/test_lib.py')]
1967 command = ['${PYTHON}', test_script] + script_flags + command
1968 if 'test_wrapper' in ARGUMENTS:
1969 command = ApplyTestWrapperCommand(command, extra_deps)
1970 return env.AutoDepsCommand(name, command,
1971 extra_deps=extra_deps, posix_path=posix_path,
1972 disabled=env.Bit('do_not_run_tests'))
1974 pre_base_env.AddMethod(CommandTest)
1977 def FileSizeTest(env, name, envFile, max_size=None):
1978 """FileSizeTest() returns a scons node like the other XYZTest generators.
1979 It logs the file size of envFile in a perf-buildbot-recognizable format.
1980 Optionally, it can cause a test failure if the file is larger than max_size.
1982 def doSizeCheck(target, source, env):
1983 filepath = source[0].abspath
1984 actual_size = os.stat(filepath).st_size
1985 command_tester.LogPerfResult(name,
1986 env.GetPerfEnvDescription(),
1987 '%.3f' % (actual_size / 1024.0),
1989 # Also get zipped size.
1990 nexe_file = open(filepath, 'rb')
1991 zipped_size = len(zlib.compress(nexe_file.read()))
1993 command_tester.LogPerfResult(name,
1994 'ZIPPED_' + env.GetPerfEnvDescription(),
1995 '%.3f' % (zipped_size / 1024.0),
1997 # Finally, do the size check.
1998 if max_size is not None and actual_size > max_size:
1999 # NOTE: this exception only triggers a failure for this particular test,
2000 # just like any other test failure.
2001 raise Exception("File %s larger than expected: expected up to %i, got %i"
2002 % (filepath, max_size, actual_size))
2003 # If 'built_elsewhere', the file should should have already been built.
2004 # Do not try to built it and/or its pieces.
2005 if env.Bit('built_elsewhere'):
2006 env.Ignore(name, envFile)
2007 return env.Command(name, envFile, doSizeCheck)
2009 pre_base_env.AddMethod(FileSizeTest)
2011 def StripExecutable(env, name, exe):
2012 """StripExecutable returns a node representing the stripped version of |exe|.
2013 The stripped version will be given the basename |name|.
2014 NOTE: for now this only works with the untrusted toolchain.
2015 STRIP does not appear to be a first-class citizen in SCons and
2016 STRIP has only been set to point at the untrusted toolchain.
2021 action=[Action('${STRIPCOM} ${SOURCES} -o ${TARGET}', '${STRIPCOMSTR}')])
2023 pre_base_env.AddMethod(StripExecutable)
2026 # TODO(ncbray): pretty up the log output when running this builder.
2027 def DisabledCommand(target, source, env):
2030 pre_base_env['BUILDERS']['DisabledCommand'] = Builder(action=DisabledCommand)
2033 def AutoDepsCommand(env, name, command, extra_deps=[], posix_path=False,
2035 """AutoDepsCommand() takes a command as an array of arguments. Each
2036 argument may either be:
2039 * a Scons file object, e.g. one created with env.File() or as the
2040 result of another build target.
2042 In the second case, the file is automatically declared as a
2043 dependency of this command.
2045 command = list(command)
2047 for index, arg in enumerate(command):
2048 if not isinstance(arg, str):
2049 if len(Flatten(arg)) != 1:
2050 # Do not allow this, because it would cause "deps" to get out
2051 # of sync with the indexes in "command".
2052 # See http://code.google.com/p/nativeclient/issues/detail?id=1086
2053 raise AssertionError('Argument to AutoDepsCommand() actually contains '
2054 'multiple (or zero) arguments: %r' % arg)
2056 command[index] = '${SOURCES[%d].posix}' % len(deps)
2058 command[index] = '${SOURCES[%d].abspath}' % len(deps)
2061 # If built_elsewhere, build commands are replaced by no-ops, so make sure
2062 # the targets don't get removed first
2063 if env.Bit('built_elsewhere'):
2065 env.Depends(name, extra_deps)
2068 return env.DisabledCommand(name, deps)
2070 return env.Command(name, deps, ' '.join(command))
2073 pre_base_env.AddMethod(AutoDepsCommand)
2076 def GetPrintableCommandName(cmd):
2077 """Look at the first few elements of cmd to derive a suitable command name."""
2078 cmd_tokens = cmd.split()
2079 if "python" in cmd_tokens[0] and len(cmd_tokens) >= 2:
2080 cmd_name = cmd_tokens[1]
2082 cmd_name = cmd_tokens[0].split('(')[0]
2084 # undo some pretty printing damage done by hammer
2085 cmd_name = cmd_name.replace('________','')
2086 # use file name part of a path
2087 return cmd_name.split('/')[-1]
2090 def GetPrintableEnvironmentName(env):
2091 # use file name part of a obj root path as env name
2092 return env.subst('${TARGET_ROOT}').split('/')[-1]
2094 pre_base_env.AddMethod(GetPrintableEnvironmentName)
2097 def CustomCommandPrinter(cmd, targets, source, env):
2098 # Abuse the print hook to count the commands that are executed
2099 if env.Bit('target_stats'):
2100 cmd_name = GetPrintableCommandName(cmd)
2101 env_name = env.GetPrintableEnvironmentName()
2102 CMD_COUNTER[cmd_name] = CMD_COUNTER.get(cmd_name, 0) + 1
2103 ENV_COUNTER[env_name] = ENV_COUNTER.get(env_name, 0) + 1
2106 # Our pretty printer
2108 cmd_name = GetPrintableCommandName(cmd)
2109 env_name = env.GetPrintableEnvironmentName()
2110 sys.stdout.write('[%s] [%s] %s\n' % (cmd_name, env_name,
2111 targets[0].get_path()))
2113 # The SCons default (copied from print_cmd_line in Action.py)
2114 sys.stdout.write(cmd + u'\n')
2116 if 'generate_ninja' not in ARGUMENTS:
2117 pre_base_env.Append(PRINT_CMD_LINE_FUNC=CustomCommandPrinter)
2120 def GetAbsDirArg(env, argument, target):
2121 """Fetch the named command-line argument and turn it into an absolute
2122 directory name. If the argument is missing, raise a UserError saying
2123 that the given target requires that argument be given."""
2124 dir = ARGUMENTS.get(argument)
2126 raise UserError('%s must be set when invoking %s' % (argument, target))
2127 return os.path.join(env.Dir('$MAIN_DIR').abspath, dir)
2129 pre_base_env.AddMethod(GetAbsDirArg)
2132 pre_base_env.Append(
2134 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
2135 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
2139 def MakeGTestEnv(env):
2140 # Create an environment to run unit tests using Gtest.
2141 gtest_env = env.Clone()
2143 # This became necessary for the arm cross TC v4.6
2144 # but probable applies to all new gcc TCs
2145 gtest_env.Append(LINKFLAGS=['-pthread'])
2147 # Define compile-time flag that communicates that we are compiling in the test
2148 # environment (rather than for the TCB).
2149 if gtest_env['NACL_BUILD_FAMILY'] == 'TRUSTED':
2150 gtest_env.Append(CCFLAGS=['-DNACL_TRUSTED_BUT_NOT_TCB'])
2152 # This is necessary for unittest_main.c which includes gtest/gtest.h
2153 # The problem is that gtest.h includes other files expecting the
2154 # include path to be set.
2155 gtest_env.Prepend(CPPPATH=['${SOURCE_ROOT}/testing/gtest/include'])
2157 # gtest does not compile with our stringent settings.
2158 if gtest_env.Bit('linux') or gtest_env.Bit('mac'):
2159 # "-pedantic" is because of: gtest-typed-test.h:236:46: error:
2160 # anonymous variadic macros were introduced in C99
2161 # Also, gtest does not compile successfully with "-Wundef".
2162 gtest_env.FilterOut(CCFLAGS=['-pedantic', '-Wundef'])
2163 gtest_env.FilterOut(CXXFLAGS=['-fno-rtti', '-Weffc++'])
2165 # gtest is incompatible with static linking due to obscure libstdc++
2166 # linking interactions.
2167 # See http://code.google.com/p/nativeclient/issues/detail?id=1987
2168 gtest_env.FilterOut(LINKFLAGS=['-static'])
2170 gtest_env.Prepend(LIBS=['gtest'])
2173 pre_base_env.AddMethod(MakeGTestEnv)
2175 def MakeUntrustedNativeEnv(env):
2176 native_env = nacl_env.Clone()
2177 if native_env.Bit('bitcode') and not native_env.Bit('target_mips32'):
2178 native_env = native_env.PNaClGetNNaClEnv()
2181 pre_base_env.AddMethod(MakeUntrustedNativeEnv)
2183 def MakeBaseTrustedEnv(platform=None):
2184 base_env = MakeArchSpecificEnv(platform)
2186 IS_BUILD_ENV = False,
2189 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
2190 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
2197 EXTRA_CXXFLAGS = [],
2199 CFLAGS = ['${EXTRA_CFLAGS}'],
2200 CXXFLAGS = ['${EXTRA_CXXFLAGS}'],
2202 if base_env.Bit('ncval_testing'):
2203 base_env.Append(CPPDEFINES = ['NCVAL_TESTING'])
2205 base_env.Append(BUILD_SCONSCRIPTS = [
2206 # KEEP THIS SORTED PLEASE
2207 'build/package_version/build.scons',
2208 'pynacl/build.scons',
2209 'src/nonsfi/irt/build.scons',
2210 'src/nonsfi/loader/build.scons',
2211 'src/shared/gio/build.scons',
2212 'src/shared/imc/build.scons',
2213 'src/shared/ldr/build.scons',
2214 'src/shared/platform/build.scons',
2215 'src/shared/serialization/build.scons',
2216 'src/shared/srpc/build.scons',
2217 'src/shared/utils/build.scons',
2218 'src/third_party/gtest/build.scons',
2219 'src/tools/validator_tools/build.scons',
2220 'src/trusted/cpu_features/build.scons',
2221 'src/trusted/debug_stub/build.scons',
2222 'src/trusted/desc/build.scons',
2223 'src/trusted/desc_cacheability/build.scons',
2224 'src/trusted/fault_injection/build.scons',
2225 'src/trusted/generic_container/build.scons',
2226 'src/trusted/gio/build.scons',
2227 'src/trusted/interval_multiset/build.scons',
2228 'src/trusted/manifest_name_service_proxy/build.scons',
2229 'src/trusted/nacl_base/build.scons',
2230 'src/trusted/nonnacl_util/build.scons',
2231 'src/trusted/perf_counter/build.scons',
2232 'src/trusted/platform_qualify/build.scons',
2233 'src/trusted/reverse_service/build.scons',
2234 'src/trusted/seccomp_bpf/build.scons',
2235 'src/trusted/sel_universal/build.scons',
2236 'src/trusted/service_runtime/build.scons',
2237 'src/trusted/simple_service/build.scons',
2238 'src/trusted/threading/build.scons',
2239 'src/trusted/validator/build.scons',
2240 'src/trusted/validator/driver/build.scons',
2241 'src/trusted/validator/x86/32/build.scons',
2242 'src/trusted/validator/x86/64/build.scons',
2243 'src/trusted/validator/x86/build.scons',
2244 'src/trusted/validator/x86/decoder/build.scons',
2245 'src/trusted/validator/x86/decoder/generator/build.scons',
2246 'src/trusted/validator/x86/ncval_reg_sfi/build.scons',
2247 'src/trusted/validator/x86/ncval_seg_sfi/build.scons',
2248 'src/trusted/validator/x86/ncval_seg_sfi/generator/build.scons',
2249 'src/trusted/validator/x86/testing/enuminsts/build.scons',
2250 'src/trusted/validator_arm/build.scons',
2251 'src/trusted/validator_ragel/build.scons',
2252 'src/trusted/validator_x86/build.scons',
2253 'src/trusted/weak_ref/build.scons',
2254 'tests/common/build.scons',
2255 'tests/lock_manager/build.scons',
2256 'tests/performance/build.scons',
2257 'tests/python_version/build.scons',
2258 'tests/sel_ldr_seccomp/build.scons',
2259 'tests/srpc_message/build.scons',
2260 'tests/tools/build.scons',
2261 'tests/unittests/shared/srpc/build.scons',
2262 'tests/unittests/shared/imc/build.scons',
2263 'tests/unittests/shared/platform/build.scons',
2264 'tests/unittests/trusted/asan/build.scons',
2265 'tests/unittests/trusted/bits/build.scons',
2266 'tests/unittests/trusted/platform_qualify/build.scons',
2267 'tests/unittests/trusted/service_runtime/build.scons',
2268 'toolchain_build/build.scons',
2271 base_env.AddMethod(SDKInstallBin)
2273 # The ARM and MIPS validators can be built for any target that doesn't use
2275 if not base_env.Bit('target_x86_64'):
2277 BUILD_SCONSCRIPTS = [
2278 'src/trusted/validator_mips/build.scons',
2281 base_env.AddChromeFilesFromGroup('trusted_scons_files')
2284 NACL_BUILD_FAMILY = 'TRUSTED',
2287 # Add optional scons files if present in the directory tree.
2288 if os.path.exists(pre_base_env.subst('${MAIN_DIR}/supplement/build.scons')):
2289 base_env.Append(BUILD_SCONSCRIPTS=['${MAIN_DIR}/supplement/build.scons'])
2294 # Select tests to run under coverage build.
2295 pre_base_env['COVERAGE_TARGETS'] = [
2296 'small_tests', 'medium_tests', 'large_tests',
2297 'chrome_browser_tests']
2300 pre_base_env.Help("""\
2301 ======================================================================
2303 ======================================================================
2308 * cleaning: scons -c
2310 * build mandel: scons --mode=nacl mandel.nexe
2311 * smoke test: scons --mode=nacl,opt-linux -k pp=1 smoke_tests
2313 * sel_ldr: scons --mode=opt-linux sel_ldr
2315 * build the plugin: scons --mode=opt-linux ppNaClPlugin
2316 * or: scons --mode=opt-linux src/trusted/plugin
2318 Targets to build trusted code destined for the SDK:
2319 * build trusted-code tools: scons build_bin
2320 * install trusted-code tools: scons install_bin bindir=...
2321 * These default to opt build, or add --mode=dbg-host for debug build.
2323 Targets to build untrusted code destined for the SDK:
2324 * build just libraries: scons build_lib
2325 * install just headers: scons install_headers includedir=...
2326 * install just libraries: scons install_lib libdir=...
2327 * install headers and libraries:scons install includedir=... libdir=...
2329 * dump system info: scons --mode=nacl,opt-linux dummy
2334 --prebuilt Do not build things, just do install steps
2336 --verbose Full command line logging before command execution
2338 pp=1 Use command line pretty printing (more concise output)
2340 sysinfo=1 Verbose system info printing
2342 naclsdk_validate=0 Suppress presence check of sdk
2346 Automagically generated help:
2347 -----------------------------
2351 def SetUpClang(env):
2352 env['CLANG_DIR'] = '${SOURCE_ROOT}/third_party/llvm-build/Release+Asserts/bin'
2353 env['CLANG_OPTS'] = []
2355 if not (env.Bit('host_linux') or env.Bit('host_mac')):
2356 raise UserError("ERROR: ASan is only available for Linux and Mac")
2357 env.Append(CLANG_OPTS=['-fsanitize=address',
2358 '-gline-tables-only',
2359 '-fno-omit-frame-pointer',
2360 '-DADDRESS_SANITIZER'])
2361 if env.Bit('host_mac'):
2362 # The built executables will try to find this library at runtime
2363 # in the directory containing the executable itself. In the
2364 # Chromium build, the library just gets copied into that
2365 # directory. Here, there isn't a single directory from which
2366 # all the test binaries are run (sel_ldr is run from staging/
2367 # but other trusted test binaries are run from their respective
2368 # obj/.../ directories). So instead just point the dynamic linker
2369 # at the right directory using an environment variable.
2370 clang_lib_dir = '${CLANG_DIR}/../lib/clang/*/lib/darwin'
2371 env['ENV']['DYLD_LIBRARY_PATH'] = ':'.join([dir.abspath for dir in
2372 env.Glob(clang_lib_dir)])
2373 if 'PROPAGATE_ENV' not in env:
2374 env['PROPAGATE_ENV'] = []
2375 env['PROPAGATE_ENV'].append('DYLD_LIBRARY_PATH')
2378 if not env.Bit('host_linux') or not env.Bit('build_x86_64'):
2379 raise UserError('ERROR: MSan is only available for x86-64 Linux')
2380 track_origins = ARGUMENTS.get('msan_track_origins', '1')
2381 env.Append(CLANG_OPTS=['-fsanitize=memory',
2382 '-fsanitize-memory-track-origins=%s' % track_origins,
2383 '-gline-tables-only',
2384 '-fno-omit-frame-pointer',
2385 '-DMEMORY_SANITIZER'])
2387 env['CC'] = '${CLANG_DIR}/clang ${CLANG_OPTS}'
2388 env['CXX'] = '${CLANG_DIR}/clang++ ${CLANG_OPTS}'
2389 # Make sure we find Clang-supplied libraries like -lprofile_rt
2390 # in the Clang build we use, rather than from the system.
2391 # The system-installed versions go with the system-installed Clang
2392 # and might not be compatible with the Clang we're running.
2393 env.Append(LIBPATH=['${CLANG_DIR}/../lib'])
2395 def GenerateOptimizationLevels(env):
2396 if env.Bit('clang'):
2399 # Generate debug variant.
2400 debug_env = env.Clone(tools = ['target_debug'])
2401 debug_env['OPTIMIZATION_LEVEL'] = 'dbg'
2402 debug_env['BUILD_TYPE'] = debug_env.subst('$BUILD_TYPE')
2403 debug_env['BUILD_DESCRIPTION'] = debug_env.subst('$BUILD_DESCRIPTION')
2404 AddDualLibrary(debug_env)
2405 # Add to the list of fully described environments.
2406 environment_list.append(debug_env)
2408 # Generate opt variant.
2409 opt_env = env.Clone(tools = ['target_optimized'])
2410 opt_env['OPTIMIZATION_LEVEL'] = 'opt'
2411 opt_env['BUILD_TYPE'] = opt_env.subst('$BUILD_TYPE')
2412 opt_env['BUILD_DESCRIPTION'] = opt_env.subst('$BUILD_DESCRIPTION')
2413 AddDualLibrary(opt_env)
2414 # Add to the list of fully described environments.
2415 environment_list.append(opt_env)
2417 return (debug_env, opt_env)
2420 def SDKInstallBin(env, name, node, target=None):
2421 """Add the given node to the build_bin and install_bin targets.
2422 It will be installed under the given name with the build target appended.
2423 The optional target argument overrides the setting of what that target is."""
2424 env.Alias('build_bin', node)
2425 if 'install_bin' in COMMAND_LINE_TARGETS:
2426 dir = env.GetAbsDirArg('bindir', 'install_bin')
2428 target = env['TARGET_FULLARCH'].replace('-', '_')
2429 file_name, file_ext = os.path.splitext(name)
2430 output_name = file_name + '_' + target + file_ext
2431 install_node = env.InstallAs(os.path.join(dir, output_name), node)
2432 env.Alias('install_bin', install_node)
2435 def MakeWindowsEnv(platform=None):
2436 base_env = MakeBaseTrustedEnv(platform)
2437 windows_env = base_env.Clone(
2438 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-win',
2439 BUILD_TYPE_DESCRIPTION = 'Windows ${OPTIMIZATION_LEVEL} build',
2440 tools = ['target_platform_windows'],
2441 # Windows /SAFESEH linking requires either an .sxdata section be
2442 # present or that @feat.00 be defined as a local, absolute symbol
2443 # with an odd value.
2444 ASCOM = ('$ASPPCOM /E /D__ASSEMBLER__ | '
2445 '$WINASM -defsym @feat.00=1 -o $TARGET'),
2446 PDB = '${TARGET.base}.pdb',
2447 # Strict doesn't currently work for Windows since some of the system
2448 # libraries like wsock32 are magical.
2449 LIBS_STRICT = False,
2450 TARGET_ARCH='x86_64' if base_env.Bit('build_x86_64') else 'x86',
2455 ['NACL_WINDOWS', '1'],
2457 ['NACL_LINUX', '0'],
2458 ['NACL_ANDROID', '0'],
2459 ['_WIN32_WINNT', '0x0501'],
2460 ['__STDC_LIMIT_MACROS', '1'],
2462 # WIN32 is used by ppapi
2464 # WIN32_LEAN_AND_MEAN tells windows.h to omit obsolete and rarely
2465 # used #include files. This allows use of Winsock 2.0 which otherwise
2466 # would conflict with Winsock 1.x included by windows.h.
2467 ['WIN32_LEAN_AND_MEAN', ''],
2469 LIBS = ['ws2_32', 'advapi32'],
2470 # TODO(bsy) remove 4355 once cross-repo
2471 # NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
2472 CCFLAGS = ['/EHsc', '/WX', '/wd4355', '/wd4800'],
2475 # This linker option allows us to ensure our builds are compatible with
2476 # Chromium, which uses it.
2477 if windows_env.Bit('build_x86_32'):
2478 windows_env.Append(LINKFLAGS = "/safeseh")
2480 # We use the GNU assembler (gas) on Windows so that we can use the
2481 # same .S assembly files on all platforms. Microsoft's assembler uses
2482 # a completely different syntax for x86 code.
2483 if windows_env.Bit('build_x86_64'):
2484 # This assembler only works for x86-64 code.
2485 windows_env['WINASM'] = \
2486 windows_env.File('$SOURCE_ROOT/third_party/mingw-w64/mingw/bin/'
2487 'x86_64-w64-mingw32-as.exe').abspath
2489 # This assembler only works for x86-32 code.
2490 windows_env['WINASM'] = \
2491 windows_env.File('$SOURCE_ROOT/third_party/gnu_binutils/files/'
2496 windows_optimized_env) = GenerateOptimizationLevels(MakeWindowsEnv())
2498 def MakeUnixLikeEnv(platform=None):
2499 unix_like_env = MakeBaseTrustedEnv(platform)
2500 # -Wdeclaration-after-statement is desirable because MS studio does
2501 # not allow declarations after statements in a block, and since much
2502 # of our code is portable and primarily initially tested on Linux,
2503 # it'd be nice to get the build error earlier rather than later
2504 # (building and testing on Linux is faster).
2505 # TODO(nfullagar): should we consider switching to -std=c99 ?
2506 unix_like_env.Prepend(
2509 '-Wdeclaration-after-statement',
2510 # Require defining functions as "foo(void)" rather than
2511 # "foo()" because, in C (but not C++), the latter defines a
2512 # function with unspecified arguments rather than no
2514 '-Wstrict-prototypes',
2525 '-fdiagnostics-show-option',
2526 '-fvisibility=hidden',
2527 '-fstack-protector',
2529 # NOTE: pthread is only neeeded for libppNaClPlugin.so and on arm
2531 CPPDEFINES = [['__STDC_LIMIT_MACROS', '1'],
2532 ['__STDC_FORMAT_MACROS', '1'],
2535 # Android's stlport uses __STRICT_ANSI__ to exclude "long long".
2536 # This breaks basically all C++ code that uses stlport.
2537 if not unix_like_env.Bit('android'):
2538 unix_like_env.Prepend(CXXFLAGS=['-std=c++98'])
2540 if not unix_like_env.Bit('clang'):
2541 unix_like_env.Append(CCFLAGS=['--param', 'ssp-buffer-size=4'])
2543 if unix_like_env.Bit('enable_tmpfs_redirect_var'):
2544 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '1']])
2546 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '0']])
2547 return unix_like_env
2550 def MakeMacEnv(platform=None):
2551 mac_env = MakeUnixLikeEnv(platform).Clone(
2552 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-mac',
2553 BUILD_TYPE_DESCRIPTION = 'MacOS ${OPTIMIZATION_LEVEL} build',
2554 tools = ['target_platform_mac'],
2555 # TODO(bradnelson): this should really be able to live in unix_like_env
2556 # but can't due to what the target_platform_x module is
2559 PLUGIN_SUFFIX = '.bundle',
2561 # On Mac, only the newer clang toolchains can parse some of the trusted
2562 # code's assembly syntax, so turn clang on by default.
2563 mac_env.SetBits('clang')
2565 # This should be kept in synch with mac_deployment_target
2566 # in build/common.gypi, which in turn should be kept in synch
2567 # with chromium/src/build/common.gypi.
2568 mac_deployment_target = '10.6'
2571 CCFLAGS=['-mmacosx-version-min=' + mac_deployment_target],
2572 LINKFLAGS=['-mmacosx-version-min=' + mac_deployment_target])
2574 subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
2576 CCFLAGS=[subarch_flag, '-fPIC'],
2577 ASFLAGS=[subarch_flag],
2578 LINKFLAGS=[subarch_flag, '-fPIC'],
2579 CPPDEFINES = [['NACL_WINDOWS', '0'],
2581 ['NACL_LINUX', '0'],
2582 ['NACL_ANDROID', '0'],
2583 # defining _DARWIN_C_SOURCE breaks 10.4
2584 #['_DARWIN_C_SOURCE', '1'],
2585 #['__STDC_LIMIT_MACROS', '1']
2590 (mac_debug_env, mac_optimized_env) = GenerateOptimizationLevels(MakeMacEnv())
2593 def which(cmd, paths=os.environ.get('PATH', '').split(os.pathsep)):
2595 if os.access(os.path.join(p, cmd), os.X_OK):
2600 def SetUpLinuxEnvArm(env):
2601 jail = env.GetToolchainDir(toolchain_name='arm_trusted')
2602 if env.Bit('arm_hard_float'):
2603 arm_abi = 'gnueabihf'
2606 if not platform.machine().startswith('arm'):
2607 # Allow emulation on non-ARM hosts.
2608 env.Replace(EMULATOR=jail + '/run_under_qemu_arm')
2609 if env.Bit('built_elsewhere'):
2610 def FakeInstall(dest, source, env):
2611 print 'Not installing', dest
2612 # Replace build commands with no-ops
2613 env.Replace(CC='true', CXX='true', LD='true',
2614 AR='true', RANLIB='true', INSTALL=FakeInstall)
2617 for suffix in ['', '-4.5', '-4.6']:
2618 if which('arm-linux-%s-g++%s' % (arm_abi, suffix)):
2621 if arm_suffix is None:
2622 # This doesn't bail out completely here because we cannot
2623 # tell whether scons was run with just --mode=nacl, where
2624 # none of these settings will actually be used.
2625 print 'NOTE: arm trusted TC is not installed'
2626 bad = 'ERROR-missing-arm-trusted-toolchain'
2627 env.Replace(CC=bad, CXX=bad, LD=bad)
2630 env.Replace(CC='arm-linux-%s-gcc%s' % (arm_abi, arm_suffix),
2631 CXX='arm-linux-%s-g++%s' % (arm_abi, arm_suffix),
2632 LD='arm-linux-%s-ld%s' % (arm_abi, arm_suffix),
2634 # The -rpath-link argument is needed on Ubuntu/Precise to
2635 # avoid linker warnings about missing ld.linux.so.3.
2636 # TODO(sbc): remove this once we stop supporting Precise
2637 # as a build environment.
2638 LINKFLAGS=['-Wl,-rpath-link=' + jail +
2639 '/lib/arm-linux-' + arm_abi]
2641 # Note we let the compiler choose whether it's -marm or -mthumb by
2642 # default. The hope is this will have the best chance of testing
2643 # the prevailing compilation mode used for Chromium et al.
2644 env.Prepend(CCFLAGS=['-march=armv7-a'])
2646 # get_plugin_dirname.cc has a dependency on dladdr
2647 env.Append(LIBS=['dl'])
2649 def SetUpAndroidEnv(env):
2650 env.FilterOut(CPPDEFINES=[['_LARGEFILE64_SOURCE', '1']])
2651 env.FilterOut(CPPDEFINES=[['NACL_ANDROID', '0']])
2652 env.Prepend(CPPDEFINES=[['NACL_ANDROID', '1']])
2653 android_ndk_root = os.path.join('${SOURCE_ROOT}', 'src', 'third_party',
2654 'android_tools', 'ndk')
2655 android_ndk_experimental_root = os.path.join('${SOURCE_ROOT}', 'src',
2656 'third_party', 'android_tools',
2658 android_sdk_root = os.path.join('${SOURCE_ROOT}', 'src', 'third_party',
2659 'android_tools', 'sdk')
2660 android_sdk_version = 19
2661 android_stlport_root = os.path.join(android_ndk_root, 'sources', 'cxx-stl',
2664 pynacl.platform.OS_WIN : 'win',
2665 pynacl.platform.OS_MAC: 'darwin',
2666 pynacl.platform.OS_LINUX : 'linux'
2668 host_os = ndk_host_os_map[pynacl.platform.GetOS()]
2669 android_sdk = os.path.join(android_sdk_root, 'platforms',
2670 'android-%s' % android_sdk_version)
2672 if env.Bit('build_arm'):
2673 android_ndk_target_prefix = 'arm-linux-androideabi'
2674 android_ndk_version = '4.8'
2675 android_app_abi = 'armeabi-v7a'
2676 android_ndk_sysroot = os.path.join(android_ndk_root, 'platforms',
2677 'android-14', 'arch-arm')
2678 android_ndk_lib_dir = os.path.join('usr', 'lib')
2679 android_toolchain = os.path.join(android_ndk_root, 'toolchains',
2680 'arm-linux-androideabi-4.6', 'prebuilt',
2681 '%s-x86_64' % host_os, 'bin')
2682 arch_cflags += ['-march=armv7-a', '-mfloat-abi=softfp']
2683 # TODO(sehr): add other android architecture platform settings here.
2684 android_ndk_include = os.path.join(android_ndk_sysroot, 'usr', 'include')
2685 android_ndk_lib = os.path.join(android_ndk_sysroot, android_ndk_lib_dir)
2686 android_sdk_jar = os.path.join(android_sdk, 'android.jar')
2687 android_stlport_include = os.path.join(android_stlport_root, 'stlport')
2688 android_stlport_libs_dir = os.path.join(android_stlport_root, 'libs',
2690 android_ndk_libgcc_path = os.path.join(android_toolchain, '..', 'lib', 'gcc',
2691 android_ndk_target_prefix,
2692 android_ndk_version)
2693 env.Replace(CC=os.path.join(android_toolchain,
2694 '%s-gcc' % android_ndk_target_prefix),
2695 CXX=os.path.join(android_toolchain,
2696 '%s-g++' % android_ndk_target_prefix),
2697 LD=os.path.join(android_toolchain,
2698 '%s-g++' % android_ndk_target_prefix),
2699 AR=os.path.join(android_toolchain,
2700 '%s-ar' % android_ndk_target_prefix),
2701 RANLIB=os.path.join(android_toolchain,
2702 '%s-ranlib' % android_ndk_target_prefix),
2703 READELF=os.path.join(android_toolchain,
2704 '%s-readelf' % android_ndk_target_prefix),
2705 STRIP=os.path.join(android_toolchain,
2706 '%s-strip' % android_ndk_target_prefix),
2707 EMULATOR=os.path.join(android_sdk_root, 'tools', 'emulator'),
2708 LIBPATH=['${LIB_DIR}',
2710 android_ndk_libgcc_path,
2711 os.path.join(android_stlport_root, 'libs',
2714 LIBS=['stlport_shared',
2721 # SHLINKFLAGS should not inherit options from LINKFLAGS.
2722 env.FilterOut(SHLINKFLAGS=['$LINKFLAGS'])
2723 env.Append(CCFLAGS=['--sysroot=' + android_ndk_sysroot,
2724 '-isystem=' + os.path.join(android_ndk_sysroot, 'usr',
2726 '-I%s' % android_stlport_include,
2727 '-ffunction-sections',
2729 '-fstack-protector',
2731 '-finline-limit=64',
2732 '-Wa,--noexecstack',
2735 # Due to bogus warnings on uintptr_t formats.
2738 CXXFLAGS=['-I%s' % android_stlport_include,
2739 '-I%s' % android_ndk_include,
2742 LINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2744 '-Wl,--no-undefined',
2745 # Don't export symbols from statically linked libraries.
2746 '-Wl,--exclude-libs=ALL',
2747 # crtbegin_dynamic.o should be the last item in ldflags.
2748 os.path.join(android_ndk_lib, 'crtbegin_dynamic.o'),
2750 LINKCOM=' $ANDROID_EXTRA_LIBS',
2751 ANDROID_EXTRA_LIBS=os.path.join(android_ndk_lib,
2752 'crtend_android.o'),
2753 SHLINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2755 # crtbegin_so.o should be the last item in ldflags.
2756 os.path.join(android_ndk_lib, 'crtbegin_so.o'),
2758 SHLINKCOM=' $ANDROID_EXTRA_SHLIBS',
2759 ANDROID_EXTRA_SHLIBS=os.path.join(android_ndk_lib,
2764 def SetUpLinuxEnvMips(env):
2765 jail = env.GetToolchainDir(toolchain_name='mips_trusted')
2766 if not platform.machine().startswith('mips'):
2767 # Allow emulation on non-MIPS hosts.
2768 env.Replace(EMULATOR=jail + '/run_under_qemu_mips32')
2769 if env.Bit('built_elsewhere'):
2770 def FakeInstall(dest, source, env):
2771 print 'Not installing', dest
2772 # Replace build commands with no-ops
2773 env.Replace(CC='true', CXX='true', LD='true',
2774 AR='true', RANLIB='true', INSTALL=FakeInstall)
2776 tc_dir = os.path.join(jail, 'bin')
2777 if not which(os.path.join(tc_dir, 'mipsel-linux-gnu-gcc')):
2778 raise UserError("\nERRROR: "
2779 "MIPS trusted TC is not installed - try running:\n"
2780 "tools/trusted_cross_toolchains/trusted-toolchain-creator"
2781 ".mipsel.debian.sh nacl_sdk")
2782 env.Replace(CC=os.path.join(tc_dir, 'mipsel-linux-gnu-gcc'),
2783 CXX=os.path.join(tc_dir, 'mipsel-linux-gnu-g++'),
2784 LD=os.path.join(tc_dir, 'mipsel-linux-gnu-ld'),
2786 LIBPATH=['${LIB_DIR}',
2787 jail + '/sysroot/usr/lib'],
2789 os.path.join(jail, 'ld_script_mips_trusted')]
2792 env.Append(LIBS=['rt', 'dl', 'pthread'],
2793 CCFLAGS=['-march=mips32r2'])
2795 # Makes a generic Linux development environment.
2796 # Linux development environments are used in two different ways.
2797 # 1) To produce trusted tools (e.g., sel_ldr), called TRUSTED_ENV
2798 # 2) To produce build tools (e.g., tls_edit), called BUILD_ENV
2799 def MakeGenericLinuxEnv(platform=None):
2800 linux_env = MakeUnixLikeEnv(platform).Clone(
2801 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-linux',
2802 BUILD_TYPE_DESCRIPTION = 'Linux ${OPTIMIZATION_LEVEL} build',
2803 tools = ['target_platform_linux'],
2804 # TODO(bradnelson): this should really be able to live in unix_like_env
2805 # but can't due to what the target_platform_x module is
2810 # Prepend so we can disable warnings via Append
2812 CPPDEFINES = [['NACL_WINDOWS', '0'],
2814 ['NACL_LINUX', '1'],
2815 ['NACL_ANDROID', '0'],
2816 ['_BSD_SOURCE', '1'],
2817 ['_POSIX_C_SOURCE', '199506'],
2818 ['_XOPEN_SOURCE', '600'],
2819 ['_GNU_SOURCE', '1'],
2820 ['_LARGEFILE64_SOURCE', '1'],
2825 if linux_env.Bit('build_x86_32'):
2828 LINKFLAGS = ['-m32'],
2830 elif linux_env.Bit('build_x86_64'):
2833 LINKFLAGS = ['-m64'],
2835 elif linux_env.Bit('build_arm'):
2836 SetUpLinuxEnvArm(linux_env)
2837 elif linux_env.Bit('build_mips32'):
2838 SetUpLinuxEnvMips(linux_env)
2840 Banner('Strange platform: %s' % GetTargetPlatform())
2842 # These are desireable options for every Linux platform:
2843 # _FORTIFY_SOURCE: general paranoia "hardening" option for library functions
2844 # -fPIE/-pie: create a position-independent executable
2845 # relro/now: "hardening" options for linking
2846 # noexecstack: ensure that the executable does not get a PT_GNU_STACK
2847 # header that causes the kernel to set the READ_IMPLIES_EXEC
2848 # personality flag, which disables NX page protection.
2850 CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']],
2851 LINKFLAGS=['-pie', '-Wl,-z,relro', '-Wl,-z,now', '-Wl,-z,noexecstack'],
2853 # The ARM toolchain has a linker that doesn't handle the code its
2854 # compiler generates under -fPIE.
2855 if linux_env.Bit('build_arm') or linux_env.Bit('build_mips32'):
2856 linux_env.Prepend(CCFLAGS=['-fPIC'])
2857 # TODO(mcgrathr): Temporarily punt _FORTIFY_SOURCE for ARM because
2858 # it causes a libc dependency newer than the old bots have installed.
2859 linux_env.FilterOut(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2861 linux_env.Prepend(CCFLAGS=['-fPIE'])
2863 # We always want to use the same flags for .S as for .c because
2864 # code-generation flags affect the predefines we might test there.
2865 linux_env.Replace(ASFLAGS=['${CCFLAGS}'])
2869 # Specializes a generic Linux development environment to be a trusted
2871 def MakeTrustedLinuxEnv(platform=None):
2872 linux_env = MakeGenericLinuxEnv(platform)
2873 if linux_env.Bit('android'):
2874 SetUpAndroidEnv(linux_env)
2877 (linux_debug_env, linux_optimized_env) = \
2878 GenerateOptimizationLevels(MakeTrustedLinuxEnv())
2880 # Do this before the site_scons/site_tools/naclsdk.py stuff to pass it along.
2881 pre_base_env.Append(
2882 PNACL_BCLDFLAGS = ARGUMENTS.get('pnacl_bcldflags', '').split(':'))
2885 # The nacl_env is used to build native_client modules
2886 # using a special tool chain which produces platform
2887 # independent binaries
2888 # NOTE: this loads stuff from: site_scons/site_tools/naclsdk.py
2889 nacl_env = MakeArchSpecificEnv()
2890 nacl_env = nacl_env.Clone(
2891 tools = ['naclsdk'],
2892 NACL_BUILD_FAMILY = 'UNTRUSTED',
2893 BUILD_TYPE = 'nacl',
2894 BUILD_TYPE_DESCRIPTION = 'NaCl module build',
2898 # ${SOURCE_ROOT} for #include <ppapi/...>
2904 EXTRA_CXXFLAGS = [],
2906 EXTRA_LINKFLAGS = ARGUMENTS.get('nacl_linkflags', '').split(':'),
2908 # always optimize binaries
2911 '-fomit-frame-pointer',
2912 # This makes sure unwind/backtrace info is available for
2913 # all code locations. Note build/untrusted.gypi uses it too.
2914 '-fasynchronous-unwind-tables',
2917 '-fdiagnostics-show-option',
2922 CFLAGS = ['-std=gnu99',
2924 CXXFLAGS = ['-std=gnu++98',
2928 # This magic is copied from scons-2.0.1/engine/SCons/Defaults.py
2929 # where this pattern is used for _LIBDIRFLAGS, which produces -L
2930 # switches. Here we are producing a -Wl,-rpath-link,DIR for each
2931 # element of LIBPATH, i.e. for each -LDIR produced.
2932 RPATH_LINK_FLAGS = '$( ${_concat(RPATHLINKPREFIX, LIBPATH, RPATHLINKSUFFIX,'
2933 '__env__, RDirs, TARGET, SOURCE)} $)',
2934 RPATHLINKPREFIX = '-Wl,-rpath-link,',
2935 RPATHLINKSUFFIX = '',
2938 LINKFLAGS = ['${RPATH_LINK_FLAGS}'],
2940 # These are settings for in-tree, non-browser tests to use.
2941 # They use libraries that circumvent the IRT-based implementations
2942 # in the public libraries.
2943 # Note that pthread_private is part of NONIRT_LIBS for PNaCl because
2944 # libc++ depends on it.
2945 NONIRT_LIBS = (['nacl_sys_private'] +
2946 (['pthread_private'] if nacl_env.Bit('bitcode') else [])),
2947 PTHREAD_LIBS = ['pthread_private'],
2948 DYNCODE_LIBS = ['nacl_dyncode_private'],
2949 EXCEPTION_LIBS = ['nacl_exception_private'],
2950 LIST_MAPPINGS_LIBS = ['nacl_list_mappings_private'],
2953 def UsesAbiNote(env):
2954 """Return True if using a new-style GCC with .note.NaCl.ABI.* notes.
2955 This means there will always be an RODATA segment, even if just for the note."""
2956 return env.Bit('target_arm') and not env.Bit('bitcode')
2958 nacl_env.AddMethod(UsesAbiNote)
2960 def UnderWindowsCoverage(env):
2961 """Return True if using running on coverage under windows."""
2962 if 'TRUSTED_ENV' not in env:
2964 return env['TRUSTED_ENV'].Bit('coverage_enabled') and env.Bit('host_windows')
2966 nacl_env.AddMethod(UnderWindowsCoverage)
2968 def AllowNonStableBitcode(env, allow_sb_translator=False):
2969 """ This modifies the environment to allow features that aren't part
2970 of PNaCl's stable ABI. If tests using these features should be
2971 skipped entirely, this returns False. Otherwise, on success, it
2974 if env.Bit('bitcode') and env.Bit('skip_nonstable_bitcode'):
2976 # The PNaCl sandboxed translator (for the most part) only accepts stable
2977 # bitcode, so in most cases we skip building non-stable tests.
2978 # However, there are some limited cases like debug information which
2979 # we support but do not guarantee stability. Tests targeting such cases
2980 # can opt-in to testing w/ allow_sb_translator=True.
2981 if env.Bit('use_sandboxed_translator') and not allow_sb_translator:
2983 # Change environment to skip finalization step.
2984 env.SetBits('nonstable_bitcode')
2987 nacl_env.AddMethod(AllowNonStableBitcode)
2990 def AllowInlineAssembly(env):
2991 """ This modifies the environment to allow inline assembly in
2992 untrusted code. If the environment cannot be modified to allow
2993 inline assembly, it returns False. Otherwise, on success, it
2996 if env.Bit('bitcode'):
2997 # For each architecture, we only attempt to make our inline
2998 # assembly code work with one untrusted-code toolchain. For x86,
2999 # we target GCC, but not PNaCl/Clang, because the latter's
3000 # assembly support has various quirks that we don't want to have
3001 # to debug. For ARM, we target PNaCl/Clang, because that is the
3002 # only current ARM toolchain. One day, we will have an ARM GCC
3003 # toolchain, and we will no longer need to use inline assembly
3004 # with PNaCl/Clang at all.
3005 if not (env.Bit('target_arm') or env.Bit('target_mips32')):
3007 # Inline assembly does not work in pexes.
3008 if env.Bit('pnacl_generate_pexe'):
3010 env.AddBiasForPNaCl()
3011 env.PNaClForceNative()
3014 nacl_env.AddMethod(AllowInlineAssembly)
3017 # TODO(mseaborn): Enable this unconditionally once the C code on the
3018 # Chromium side compiles successfully with this warning.
3019 if not enable_chrome:
3020 nacl_env.Append(CFLAGS=['-Wstrict-prototypes'])
3022 # This is the address at which a user executable is expected to place its
3023 # data segment in order to be compatible with the integrated runtime (IRT)
3024 # library. This address should not be changed lightly.
3025 irt_compatible_rodata_addr = 0x10000000
3026 # This is the address at which the IRT's own code will be located.
3027 # It must be below irt_compatible_rodata and leave enough space for
3028 # the code segment of the IRT. It should be as close as possible to
3029 # irt_compatible_rodata so as to leave the maximum contiguous area
3030 # available for the dynamic code loading area that falls below it.
3031 # This can be adjusted as necessary for the actual size of the IRT code.
3032 irt_code_addr = irt_compatible_rodata_addr - (6 << 20) # max 6M IRT code
3033 # This is the address at which the IRT's own data will be located. The
3034 # 32-bit sandboxes limit the address space to 1GB; the initial thread's
3035 # stack sits at the top of the address space and extends down for
3036 # NACL_DEFAULT_STACK_MAX (src/trusted/service_runtime/sel_ldr.h) below.
3037 # So this must be below there, and leave enough space for the IRT's own
3038 # data segment. It should be as high as possible so as to leave the
3039 # maximum contiguous area available for the user's data and break below.
3040 # This can be adjusted as necessary for the actual size of the IRT data
3041 # (that is RODATA, rounded up to 64k, plus writable data).
3042 # 1G (address space) - 16M (NACL_DEFAULT_STACK_MAX) - 1MB (IRT rodata+data)
3043 irt_data_addr = (1 << 30) - (16 << 20) - (1 << 20)
3046 IRT_DATA_REGION_START = '%#.8x' % irt_compatible_rodata_addr,
3047 # Load addresses of the IRT's code and data segments.
3048 IRT_BLOB_CODE_START = '%#.8x' % irt_code_addr,
3049 IRT_BLOB_DATA_START = '%#.8x' % irt_data_addr,
3052 def TestsUsePublicListMappingsLib(env):
3053 """Use the public list_mappings library for in-tree tests."""
3054 env.Replace(LIST_MAPPINGS_LIBS=['nacl_list_mappings'])
3056 def TestsUsePublicLibs(env):
3057 """Change the environment so it uses public libraries for in-tree tests."""
3058 env.Replace(NONIRT_LIBS=['pthread'] if env.Bit('bitcode') else [],
3059 PTHREAD_LIBS=['pthread'],
3060 DYNCODE_LIBS=['nacl_dyncode', 'nacl'],
3061 EXCEPTION_LIBS=['nacl_exception', 'nacl'])
3063 # glibc is incompatible with libpthread_private and libnacl_sys_private.
3064 if nacl_env.Bit('nacl_glibc'):
3065 nacl_env.Replace(NONIRT_LIBS=[],
3066 PTHREAD_LIBS=['pthread'])
3068 # These add on to those set in pre_base_env, above.
3071 # This ensures that UINT32_MAX gets defined.
3072 ['__STDC_LIMIT_MACROS', '1'],
3073 # This ensures that PRId64 etc. get defined.
3074 ['__STDC_FORMAT_MACROS', '1'],
3075 # _GNU_SOURCE ensures that strtof() gets declared.
3077 # strdup, and other common stuff
3078 ['_BSD_SOURCE', '1'],
3079 ['_POSIX_C_SOURCE', '199506'],
3080 ['_XOPEN_SOURCE', '600'],
3082 ['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3083 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ],
3085 ['NACL_WINDOWS', '0'],
3087 ['NACL_LINUX', '0'],
3088 ['NACL_ANDROID', '0'],
3092 def FixWindowsAssembler(env):
3093 if env.Bit('host_windows'):
3094 # NOTE: This is needed because Windows builds are case-insensitive.
3095 # Without this we use nacl-as, which doesn't handle include directives, etc.
3096 env.Replace(ASCOM='${CCCOM}')
3098 FixWindowsAssembler(nacl_env)
3100 # Look in the local include and lib directories before the toolchain's.
3101 nacl_env['INCLUDE_DIR'] = '${TARGET_ROOT}/include'
3102 # Remove the default $LIB_DIR element so that we prepend it without duplication.
3103 # Using PrependUnique alone would let it stay last, where we want it first.
3104 nacl_env.FilterOut(LIBPATH=['${LIB_DIR}'])
3105 nacl_env.PrependUnique(
3106 CPPPATH = ['${INCLUDE_DIR}'],
3107 LIBPATH = ['${LIB_DIR}'],
3110 if nacl_env.Bit('bitcode'):
3111 # passing -O when linking requests LTO, which does additional global
3112 # optimizations at link time
3113 nacl_env.Append(LINKFLAGS=['-O3'])
3114 if not nacl_env.Bit('nacl_glibc'):
3115 nacl_env.Append(LINKFLAGS=['-static'])
3117 if nacl_env.Bit('translate_fast'):
3118 nacl_env.Append(LINKFLAGS=['-Xlinker', '-translate-fast'])
3119 nacl_env.Append(TRANSLATEFLAGS=['-translate-fast'])
3121 # With pnacl's clang base/ code uses the "override" keyword.
3122 nacl_env.Append(CXXFLAGS=['-Wno-c++11-extensions'])
3123 # Allow extraneous semicolons. (Until these are removed.)
3124 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3125 nacl_env.Append(CCFLAGS=['-Wno-extra-semi'])
3126 # Allow unused private fields. (Until these are removed.)
3127 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3128 nacl_env.Append(CCFLAGS=['-Wno-unused-private-field'])
3130 # We use a special environment for building the IRT image because it must
3131 # always use the newlib toolchain, regardless of --nacl_glibc. We clone
3132 # it from nacl_env here, before too much other cruft has been added.
3133 # We do some more magic below to instantiate it the way we need it.
3134 nacl_irt_env = nacl_env.Clone(
3135 BUILD_TYPE = 'nacl_irt',
3136 BUILD_TYPE_DESCRIPTION = 'NaCl IRT build',
3137 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT',
3140 # Provide access to the IRT build environment from the default environment
3141 # which is needed when compiling custom IRT for testing purposes.
3142 nacl_env['NACL_IRT_ENV'] = nacl_irt_env
3144 # Since we don't build src/untrusted/pthread/nacl.scons in
3145 # nacl_irt_env, we must tell the IRT how to find the pthread.h header.
3146 nacl_irt_env.Append(CPPPATH='${MAIN_DIR}/src/untrusted/pthread')
3148 # Map certain flag bits to suffices on the build output. This needs to
3149 # happen pretty early, because it affects any concretized directory names.
3150 target_variant_map = [
3151 ('bitcode', 'pnacl'),
3152 ('translate_fast', 'fast'),
3153 ('nacl_pic', 'pic'),
3154 ('use_sandboxed_translator', 'sbtc'),
3155 ('nacl_glibc', 'glibc'),
3156 ('pnacl_generate_pexe', 'pexe'),
3157 ('nonsfi_nacl', 'nonsfi'),
3159 for variant_bit, variant_suffix in target_variant_map:
3160 if nacl_env.Bit(variant_bit):
3161 nacl_env['TARGET_VARIANT'] += '-' + variant_suffix
3163 if nacl_env.Bit('bitcode'):
3164 nacl_env['TARGET_VARIANT'] += '-clang'
3166 nacl_env.Replace(TESTRUNNER_LIBS=['testrunner'])
3167 # TODO(mseaborn): Drop this once chrome side has inlined this.
3168 nacl_env.Replace(PPAPI_LIBS=['ppapi'])
3170 # TODO(mseaborn): Make nacl-glibc-based static linking work with just
3171 # "-static", without specifying a linker script.
3172 # See http://code.google.com/p/nativeclient/issues/detail?id=1298
3173 def GetLinkerScriptBaseName(env):
3174 if env.Bit('build_x86_64'):
3175 return 'elf_x86_64_nacl'
3177 return 'elf_i386_nacl'
3179 if (nacl_env.Bit('nacl_glibc') and
3180 nacl_env.Bit('nacl_static_link')):
3181 nacl_env.Append(LINKFLAGS=['-static'])
3182 if nacl_env.Bit('target_x86'):
3183 # The "-lc" is necessary because libgcc_eh depends on libc but for
3184 # some reason nacl-gcc is not linking with "--start-group/--end-group".
3185 nacl_env.Append(LINKFLAGS=[
3186 '-T', 'ldscripts/%s.x.static' % GetLinkerScriptBaseName(nacl_env),
3189 if nacl_env.Bit('running_on_valgrind'):
3190 nacl_env.Append(CCFLAGS = ['-g', '-Wno-overlength-strings',
3191 '-fno-optimize-sibling-calls'],
3192 CPPDEFINES = [['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3193 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ]])
3194 # With GLibC, libvalgrind.so is preloaded at runtime.
3195 # With Newlib, it has to be linked in.
3196 if not nacl_env.Bit('nacl_glibc'):
3197 nacl_env.Append(LINKFLAGS = ['-Wl,-u,have_nacl_valgrind_interceptors'],
3198 LIBS = ['valgrind'])
3200 environment_list.append(nacl_env)
3202 if not nacl_env.Bit('nacl_glibc'):
3203 # These are all specific to nacl-newlib so we do not include them
3204 # when building against nacl-glibc. The functionality of
3205 # pthread/startup/stubs/nosys is provided by glibc. The valgrind
3206 # code currently assumes nc_threads.
3208 BUILD_SCONSCRIPTS = [
3209 #### ALPHABETICALLY SORTED ####
3210 'src/untrusted/pthread/nacl.scons',
3211 'src/untrusted/stubs/nacl.scons',
3212 'src/untrusted/nosys/nacl.scons',
3213 #### ALPHABETICALLY SORTED ####
3216 BUILD_SCONSCRIPTS = [
3217 #### ALPHABETICALLY SORTED ####
3218 'src/nonsfi/irt/build.scons',
3219 'src/nonsfi/linux/nacl.scons',
3220 'src/nonsfi/loader/build.scons',
3221 'src/shared/gio/nacl.scons',
3222 'src/shared/imc/nacl.scons',
3223 'src/shared/ldr/nacl.scons',
3224 'src/shared/platform/nacl.scons',
3225 'src/shared/srpc/nacl.scons',
3226 'src/trusted/service_runtime/nacl.scons',
3227 'src/trusted/validator/nacl.scons',
3228 'src/trusted/weak_ref/nacl.scons',
3229 'src/untrusted/crash_dump/nacl.scons',
3230 'src/untrusted/irt/nacl_headers.scons',
3231 'src/untrusted/minidump_generator/nacl.scons',
3232 'src/untrusted/nacl/nacl.scons',
3233 'src/untrusted/valgrind/nacl.scons',
3234 #### ALPHABETICALLY SORTED ####
3236 nacl_env.AddChromeFilesFromGroup('untrusted_scons_files')
3238 # These are tests that are worthwhile to run in IRT variant only.
3240 #### ALPHABETICALLY SORTED ####
3241 'tests/irt/nacl.scons',
3242 'tests/irt_compatibility/nacl.scons',
3243 'tests/sbrk/nacl.scons',
3244 'tests/translator_size_limits/nacl.scons',
3247 # These are tests that are worthwhile to run in both IRT and non-IRT variants.
3248 # The nacl_irt_test mode runs them in the IRT variants.
3249 irt_variant_tests = [
3250 #### ALPHABETICALLY SORTED ####
3251 'tests/app_lib/nacl.scons',
3252 'tests/bigalloc/nacl.scons',
3253 'tests/callingconv/nacl.scons',
3254 'tests/callingconv_ppapi/nacl.scons',
3255 'tests/callingconv_case_by_case/nacl.scons',
3256 'tests/clock/nacl.scons',
3257 'tests/common/nacl.scons',
3258 'tests/compiler_thread_suspension/nacl.scons',
3259 'tests/computed_gotos/nacl.scons',
3260 'tests/data_below_data_start/nacl.scons',
3261 'tests/data_not_executable/nacl.scons',
3262 'tests/debug_stub/nacl.scons',
3263 'tests/dup/nacl.scons',
3264 'tests/dynamic_code_loading/nacl.scons',
3265 'tests/dynamic_linking/nacl.scons',
3266 'tests/egyptian_cotton/nacl.scons',
3267 'tests/environment_variables/nacl.scons',
3268 'tests/exception_test/nacl.scons',
3269 'tests/fdopen_test/nacl.scons',
3270 'tests/fib/nacl.scons',
3271 'tests/file/nacl.scons',
3272 'tests/fixedfeaturecpu/nacl.scons',
3273 'tests/futexes/nacl.scons',
3274 'tests/gc_instrumentation/nacl.scons',
3275 'tests/gdb/nacl.scons',
3276 'tests/glibc_file64_test/nacl.scons',
3277 'tests/glibc_static_test/nacl.scons',
3278 'tests/glibc_syscall_wrappers/nacl.scons',
3279 'tests/glibc_socket_wrappers/nacl.scons',
3280 'tests/hello_world/nacl.scons',
3281 'tests/imc_shm_mmap/nacl.scons',
3282 'tests/includability/nacl.scons',
3283 'tests/infoleak/nacl.scons',
3284 'tests/libc/nacl.scons',
3285 'tests/libc_free_hello_world/nacl.scons',
3286 'tests/list_mappings/nacl.scons',
3287 'tests/longjmp/nacl.scons',
3288 'tests/loop/nacl.scons',
3289 'tests/mandel/nacl.scons',
3290 'tests/math/nacl.scons',
3291 'tests/memcheck_test/nacl.scons',
3292 'tests/mmap/nacl.scons',
3293 'tests/mmap_main_nexe/nacl.scons',
3294 'tests/mmap_prot_exec/nacl.scons',
3295 'tests/mmap_race_protect/nacl.scons',
3296 'tests/nacl_log/nacl.scons',
3297 'tests/nameservice/nacl.scons',
3298 'tests/nanosleep/nacl.scons',
3299 'tests/nonsfi/nacl.scons',
3300 'tests/noop/nacl.scons',
3301 'tests/nrd_xfer/nacl.scons',
3302 'tests/nthread_nice/nacl.scons',
3303 'tests/null/nacl.scons',
3304 'tests/nullptr/nacl.scons',
3305 'tests/pagesize/nacl.scons',
3306 'tests/performance/nacl.scons',
3307 'tests/pnacl_abi/nacl.scons',
3308 'tests/pnacl_dynamic_loading/nacl.scons',
3309 'tests/pnacl_native_objects/nacl.scons',
3310 'tests/process_create/nacl.scons',
3311 'tests/random/nacl.scons',
3312 'tests/redir/nacl.scons',
3313 'tests/rodata_not_writable/nacl.scons',
3314 'tests/run_py/nacl.scons',
3315 'tests/sel_ldr/nacl.scons',
3316 'tests/sel_ldr_seccomp/nacl.scons',
3317 'tests/sel_main_chrome/nacl.scons',
3318 'tests/signal_handler/nacl.scons',
3319 'tests/simd/nacl.scons',
3320 'tests/sleep/nacl.scons',
3321 'tests/srpc/nacl.scons',
3322 'tests/srpc_hw/nacl.scons',
3323 'tests/srpc_message/nacl.scons',
3324 'tests/stack_alignment/nacl.scons',
3325 'tests/stubout_mode/nacl.scons',
3326 'tests/subprocess/nacl.scons',
3327 'tests/sysbasic/nacl.scons',
3328 'tests/syscall_return_regs/nacl.scons',
3329 'tests/syscall_return_sandboxing/nacl.scons',
3330 'tests/syscalls/nacl.scons',
3331 'tests/thread_capture/nacl.scons',
3332 'tests/threads/nacl.scons',
3333 'tests/time/nacl.scons',
3334 'tests/tls/nacl.scons',
3335 'tests/tls_perf/nacl.scons',
3336 'tests/tls_segment_x86_32/nacl.scons',
3337 'tests/toolchain/nacl.scons',
3338 'tests/toolchain/arm/nacl.scons',
3339 'tests/toolchain/mips/nacl.scons',
3340 'tests/unittests/shared/platform/nacl.scons',
3341 'tests/untrusted_check/nacl.scons',
3342 'tests/unwind_restores_regs/nacl.scons',
3343 #### ALPHABETICALLY SORTED ####
3344 # NOTE: The following tests are really IRT-only tests, but they
3345 # are in this category so that they can generate libraries (which
3346 # works in nacl_env but not in nacl_irt_test_env) while also
3347 # adding tests to nacl_irt_test_env.
3348 'tests/inbrowser_test_runner/nacl.scons',
3349 'tests/untrusted_crash_dump/nacl.scons',
3350 'tests/untrusted_minidump/nacl.scons',
3353 # These are tests that are NOT worthwhile to run in an IRT variant.
3354 # In some cases, that's because they are browser tests which always
3355 # use the IRT. In others, it's because they are special-case tests
3356 # that are incompatible with having an IRT loaded.
3357 nonvariant_tests = [
3358 #### ALPHABETICALLY SORTED ####
3359 'tests/barebones/nacl.scons',
3360 'tests/chrome_extension/nacl.scons',
3361 'tests/custom_desc/nacl.scons',
3362 'tests/faulted_thread_queue/nacl.scons',
3363 'tests/gold_plugin/nacl.scons',
3364 'tests/imc_sockets/nacl.scons',
3365 'tests/minnacl/nacl.scons',
3366 'tests/multiple_sandboxes/nacl.scons',
3367 # Potential issue with running them:
3368 # http://code.google.com/p/nativeclient/issues/detail?id=2092
3369 # See also the comment in "buildbot/buildbot_standard.py"
3370 'tests/pnacl_shared_lib_test/nacl.scons',
3371 'tests/pwrite/nacl.scons',
3372 'tests/signal_handler_single_step/nacl.scons',
3373 'tests/thread_suspension/nacl.scons',
3374 'tests/trusted_crash/crash_in_syscall/nacl.scons',
3375 'tests/trusted_crash/osx_crash_filter/nacl.scons',
3376 'tests/trusted_crash/osx_crash_forwarding/nacl.scons',
3377 'tests/unittests/shared/imc/nacl.scons',
3378 'tests/unittests/shared/srpc/nacl.scons',
3379 #### ALPHABETICALLY SORTED ####
3382 nacl_env.Append(BUILD_SCONSCRIPTS=nonvariant_tests)
3383 nacl_env.AddChromeFilesFromGroup('nonvariant_test_scons_files')
3384 nacl_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3385 nacl_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3387 # Defines TESTS_TO_RUN_INBROWSER.
3388 SConscript('tests/inbrowser_test_runner/selection.scons',
3389 exports=['nacl_env'])
3391 # Possibly install a toolchain by downloading it
3392 # TODO: explore using a less heavy weight mechanism
3393 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3396 SCons.Script.AddOption('--download',
3400 action='store_true',
3401 help='deprecated - allow tools to download')
3403 if nacl_env.GetOption('download'):
3404 print '@@@@ --download is deprecated, use gclient runhooks --force'
3405 nacl_sync_env = nacl_env.Clone()
3406 nacl_sync_env['ENV'] = os.environ
3407 nacl_sync_env.Execute('gclient runhooks --force')
3410 def NaClSharedLibrary(env, lib_name, *args, **kwargs):
3411 env_shared = env.Clone(COMPONENT_STATIC=False)
3412 soname = SCons.Util.adjustixes(lib_name, 'lib', '.so')
3413 env_shared.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s' % (soname)])
3414 return env_shared.ComponentLibrary(lib_name, *args, **kwargs)
3416 nacl_env.AddMethod(NaClSharedLibrary)
3418 def NaClSdkLibrary(env, lib_name, *args, **kwargs):
3419 n = [env.ComponentLibrary(lib_name, *args, **kwargs)]
3420 if not env.Bit('nacl_disable_shared'):
3421 n.append(env.NaClSharedLibrary(lib_name, *args, **kwargs))
3424 nacl_env.AddMethod(NaClSdkLibrary)
3427 # Special environment for untrusted test binaries that use raw syscalls
3428 def RawSyscallObjects(env, sources):
3429 raw_syscall_env = env.Clone()
3430 raw_syscall_env.Append(
3432 ['USE_RAW_SYSCALLS', '1'],
3433 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
3434 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
3435 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
3436 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
3440 for source_file in sources:
3441 target_name = 'raw_' + os.path.basename(source_file).rstrip('.c')
3442 object = raw_syscall_env.ComponentObject(target_name,
3444 objects.append(object)
3447 nacl_env.AddMethod(RawSyscallObjects)
3450 # The IRT-building environment was cloned from nacl_env, but it should
3451 # ignore the --nacl_glibc, nacl_pic=1 and bitcode=1 switches.
3452 # We have to reinstantiate the naclsdk.py magic after clearing those flags,
3453 # so it regenerates the tool paths right.
3454 # TODO(mcgrathr,bradnelson): could get cleaner if naclsdk.py got folded back in.
3455 nacl_irt_env.ClearBits('nacl_glibc')
3456 nacl_irt_env.ClearBits('nacl_pic')
3457 # We build the IRT using the nnacl TC even when the pnacl TC is used otherwise.
3458 if nacl_irt_env.Bit('target_mips32') or nacl_irt_env.Bit('target_x86_64'):
3459 nacl_irt_env.SetBits('bitcode')
3461 nacl_irt_env.ClearBits('bitcode')
3462 nacl_irt_env.ClearBits('pnacl_generate_pexe')
3463 nacl_irt_env.ClearBits('use_sandboxed_translator')
3464 nacl_irt_env.Tool('naclsdk')
3465 # These are unfortunately clobbered by running Tool, which
3466 # we needed to do to get the destination directory reset.
3467 # We want all the same values from nacl_env.
3468 nacl_irt_env.Replace(EXTRA_CFLAGS=nacl_env['EXTRA_CFLAGS'],
3469 EXTRA_CXXFLAGS=nacl_env['EXTRA_CXXFLAGS'],
3470 CCFLAGS=nacl_env['CCFLAGS'],
3471 CFLAGS=nacl_env['CFLAGS'],
3472 CXXFLAGS=nacl_env['CXXFLAGS'])
3473 FixWindowsAssembler(nacl_irt_env)
3474 # Make it find the libraries it builds, rather than the SDK ones.
3475 nacl_irt_env.Replace(LIBPATH='${LIB_DIR}')
3477 if nacl_irt_env.Bit('bitcode'):
3478 if nacl_irt_env.Bit('target_x86_64'):
3479 nacl_irt_env.Append(CCFLAGS=['--target=x86_64-unknown-nacl'])
3480 nacl_irt_env.Append(LINKFLAGS=['--target=x86_64-unknown-nacl',
3481 '--pnacl-allow-translate',
3483 elif nacl_irt_env.Bit('target_mips32'):
3484 # Disable the PNaCl IRT verifier since it will complain about
3485 # __executable_start symbol not being a valid external symbol.
3486 nacl_irt_env.Append(LINKFLAGS=['--pnacl-disable-abi-check'])
3488 # The IRT is C only, don't link with the C++ linker so that it doesn't
3489 # start depending on the C++ standard library and (in the case of
3491 nacl_irt_env.Replace(LINK=(nacl_irt_env['LINK'].
3492 replace('pnacl-clang++', 'pnacl-clang')))
3494 if nacl_irt_env.Bit('bitcode'):
3495 nacl_irt_env.Append(LINKFLAGS=['--pnacl-allow-native'])
3497 # All IRT code must avoid direct use of the TLS ABI register, which
3498 # is reserved for user TLS. Instead, ensure all TLS accesses use a
3499 # call to __nacl_read_tp, which the IRT code overrides to segregate
3500 # IRT-private TLS from user TLS. This only applies to mips now, on
3501 # other platforms we modify the TLS register through tls_edit as a
3503 if nacl_irt_env.Bit('target_mips32'):
3504 nacl_irt_env.Append(LINKFLAGS=['-Wt,-mtls-use-call'])
3506 # TODO(mcgrathr): Clean up uses of these methods.
3507 def AddLibraryDummy(env, nodes):
3509 nacl_irt_env.AddMethod(AddLibraryDummy, 'AddLibraryToSdk')
3511 def AddObjectInternal(env, nodes):
3512 return env.Replicate('${LIB_DIR}', nodes)
3513 nacl_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3514 nacl_irt_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3516 def IrtNaClSdkLibrary(env, lib_name, *args, **kwargs):
3517 env.ComponentLibrary(lib_name, *args, **kwargs)
3518 nacl_irt_env.AddMethod(IrtNaClSdkLibrary, 'NaClSdkLibrary')
3520 nacl_irt_env.AddMethod(SDKInstallBin)
3522 # Populate the internal include directory when AddHeaderToSdk
3523 # is used inside nacl_env.
3524 def AddHeaderInternal(env, nodes, subdir='nacl'):
3525 dir = '${INCLUDE_DIR}'
3526 if subdir is not None:
3528 n = env.Replicate(dir, nodes)
3531 nacl_irt_env.AddMethod(AddHeaderInternal, 'AddHeaderToSdk')
3533 def PublishHeader(env, nodes, subdir):
3534 if ('install' in COMMAND_LINE_TARGETS or
3535 'install_headers' in COMMAND_LINE_TARGETS):
3536 dir = env.GetAbsDirArg('includedir', 'install_headers')
3537 if subdir is not None:
3539 n = env.Install(dir, nodes)
3540 env.Alias('install', env.Alias('install_headers', n))
3543 def PublishLibrary(env, nodes):
3544 env.Alias('build_lib', nodes)
3546 if ('install' in COMMAND_LINE_TARGETS or
3547 'install_lib' in COMMAND_LINE_TARGETS):
3548 dir = env.GetAbsDirArg('libdir', 'install_lib')
3549 n = env.Install(dir, nodes)
3550 env.Alias('install', env.Alias('install_lib', n))
3553 def NaClAddHeader(env, nodes, subdir='nacl'):
3554 n = AddHeaderInternal(env, nodes, subdir)
3555 PublishHeader(env, n, subdir)
3557 nacl_env.AddMethod(NaClAddHeader, 'AddHeaderToSdk')
3559 def NaClAddLibrary(env, nodes):
3560 nodes = env.Replicate('${LIB_DIR}', nodes)
3561 PublishLibrary(env, nodes)
3563 nacl_env.AddMethod(NaClAddLibrary, 'AddLibraryToSdk')
3565 def NaClAddObject(env, nodes):
3566 lib_nodes = env.Replicate('${LIB_DIR}', nodes)
3567 PublishLibrary(env, lib_nodes)
3569 nacl_env.AddMethod(NaClAddObject, 'AddObjectToSdk')
3571 # We want to do this for nacl_env when not under --nacl_glibc,
3572 # but for nacl_irt_env whether or not under --nacl_glibc, so
3573 # we do it separately for each after making nacl_irt_env and
3574 # clearing its Bit('nacl_glibc').
3575 def AddImplicitLibs(env):
3578 # Require the pnacl_irt_shim for pnacl x86-64 and arm.
3579 # Use -B to have the compiler look for the fresh libpnacl_irt_shim.a.
3580 if ( env.Bit('bitcode') and
3581 (env.Bit('target_x86_64') or env.Bit('target_arm'))
3582 and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT'):
3583 # Note: without this hack ibpnacl_irt_shim.a will be deleted
3584 # when "built_elsewhere=1"
3585 # Since we force the build in a previous step the dependency
3586 # is not really needed.
3587 # Note: the "precious" mechanism did not work in this case
3588 if not env.Bit('built_elsewhere'):
3589 if env.Bit('enable_chrome_side'):
3590 implicit_libs += ['libpnacl_irt_shim.a']
3592 if not env.Bit('nacl_glibc'):
3593 # These are automatically linked in by the compiler, either directly
3594 # or via the linker script that is -lc. In the non-glibc build, we
3595 # are the ones providing these files, so we need dependencies.
3596 # The ComponentProgram method (site_scons/site_tools/component_builders.py)
3597 # adds dependencies on env['IMPLICIT_LIBS'] if that's set.
3598 if env.Bit('bitcode'):
3599 implicit_libs += ['libnacl.a']
3601 implicit_libs += ['crt1.o',
3605 # TODO(mcgrathr): multilib nonsense defeats -B! figure out a better way.
3606 if GetTargetPlatform() == 'x86-32':
3607 implicit_libs.append(os.path.join('32', 'crt1.o'))
3609 if implicit_libs != []:
3610 env['IMPLICIT_LIBS'] = [env.File(os.path.join('${LIB_DIR}', file))
3611 for file in implicit_libs]
3612 # The -B<dir>/ flag is necessary to tell gcc to look for crt[1in].o there.
3613 env.Prepend(LINKFLAGS=['-B${LIB_DIR}/'])
3615 AddImplicitLibs(nacl_env)
3616 AddImplicitLibs(nacl_irt_env)
3618 nacl_irt_env.Append(
3619 BUILD_SCONSCRIPTS = [
3620 'src/shared/gio/nacl.scons',
3621 'src/shared/platform/nacl.scons',
3622 'src/shared/srpc/nacl.scons',
3623 'src/tools/tls_edit/build.scons',
3624 'src/untrusted/irt/nacl.scons',
3625 'src/untrusted/nacl/nacl.scons',
3626 'src/untrusted/stubs/nacl.scons',
3627 'tests/irt_private_pthread/nacl.scons',
3629 nacl_irt_env.AddChromeFilesFromGroup('untrusted_irt_scons_files')
3631 environment_list.append(nacl_irt_env)
3633 # Since browser_tests already use the IRT normally, those are fully covered
3634 # in nacl_env. But the non_browser_tests don't use the IRT in nacl_env.
3635 # We want additional variants of those tests with the IRT, so we make
3636 # another environment and repeat them with that adjustment.
3637 nacl_irt_test_env = nacl_env.Clone(
3638 BUILD_TYPE = 'nacl_irt_test',
3639 BUILD_TYPE_DESCRIPTION = 'NaCl tests build with IRT',
3640 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT_TESTS',
3642 INCLUDE_DIR = nacl_env.Dir('${INCLUDE_DIR}'),
3643 LIB_DIR = nacl_env.Dir('${LIB_DIR}'),
3644 BUILD_SCONSCRIPTS = [],
3646 nacl_irt_test_env.SetBits('tests_use_irt')
3647 if nacl_irt_test_env.Bit('enable_chrome_side'):
3648 nacl_irt_test_env.Replace(TESTRUNNER_LIBS=['testrunner_browser'])
3650 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3651 nacl_irt_test_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3652 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_only_tests)
3653 TestsUsePublicLibs(nacl_irt_test_env)
3654 TestsUsePublicListMappingsLib(nacl_irt_test_env)
3656 # We add the following settings after creating nacl_irt_test_env because we
3657 # don't want them to be inherited by nacl_irt_test_env.
3658 if nacl_env.Bit('nonsfi_nacl'):
3659 # Not-IRT-using non-SFI code uses Linux syscalls directly. Since this
3660 # involves using inline assembly, this requires turning off the PNaCl ABI
3662 nacl_env.SetBits('nonstable_bitcode')
3663 nacl_env.Append(LINKFLAGS=['--pnacl-disable-abi-check'])
3664 # Tell the PNaCl translator to link a Linux executable.
3665 nacl_env.Append(TRANSLATEFLAGS=['--noirt'])
3667 # If a tests/.../nacl.scons file builds a library, we will just use
3668 # the one already built in nacl_env instead.
3669 def IrtTestDummyLibrary(*args, **kwargs):
3671 nacl_irt_test_env.AddMethod(IrtTestDummyLibrary, 'ComponentLibrary')
3673 def IrtTestAddNodeToTestSuite(env, node, suite_name, node_name=None,
3674 is_broken=False, is_flaky=False,
3675 disable_irt_suffix=False):
3676 # The disable_irt_suffix argument is there for allowing tests
3677 # defined in nacl_irt_test_env to be part of chrome_browser_tests
3678 # (rather than part of chrome_browser_tests_irt).
3679 # TODO(mseaborn): But really, all of chrome_browser_tests should be
3680 # placed in nacl_irt_test_env rather than in nacl_env.
3681 suite_name = AddImplicitTestSuites(suite_name, node_name)
3682 if not disable_irt_suffix:
3683 if node_name is not None:
3685 suite_name = [name + '_irt' for name in suite_name]
3686 # NOTE: This needs to be called directly to as we're overriding the
3688 return AddNodeToTestSuite(env, node, suite_name, node_name,
3689 is_broken, is_flaky)
3690 nacl_irt_test_env.AddMethod(IrtTestAddNodeToTestSuite, 'AddNodeToTestSuite')
3692 environment_list.append(nacl_irt_test_env)
3695 windows_coverage_env = windows_debug_env.Clone(
3696 tools = ['code_coverage'],
3697 BUILD_TYPE = 'coverage-win',
3698 BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
3699 # TODO(bradnelson): switch nacl to common testing process so this won't be
3701 MANIFEST_FILE = None,
3702 COVERAGE_ANALYZER_DIR=r'..\third_party\coverage_analyzer\bin',
3703 COVERAGE_ANALYZER='$COVERAGE_ANALYZER_DIR\coverage_analyzer.exe',
3705 # TODO(bradnelson): Switch nacl to common testing process so this won't be
3706 # needed. Ignoring instrumentation failure as that's easier
3707 # than trying to gate out the ones with asm we can't handle.
3708 windows_coverage_env['LINKCOM'] = windows_coverage_env.Action([
3709 windows_coverage_env.get('LINKCOM', []),
3710 '-$COVERAGE_VSINSTR /COVERAGE ${TARGET}'])
3711 windows_coverage_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
3712 AddDualLibrary(windows_coverage_env)
3713 environment_list.append(windows_coverage_env)
3715 mac_coverage_env = mac_debug_env.Clone(
3716 tools = ['code_coverage'],
3717 BUILD_TYPE = 'coverage-mac',
3718 BUILD_TYPE_DESCRIPTION = 'MacOS code coverage build',
3719 # Strict doesnt't currently work for coverage because the path to gcov is
3720 # magically baked into the compiler.
3721 LIBS_STRICT = False,
3723 AddDualLibrary(mac_coverage_env)
3724 environment_list.append(mac_coverage_env)
3726 linux_coverage_env = linux_debug_env.Clone(
3727 tools = ['code_coverage'],
3728 BUILD_TYPE = 'coverage-linux',
3729 BUILD_TYPE_DESCRIPTION = 'Linux code coverage build',
3730 # Strict doesnt't currently work for coverage because the path to gcov is
3731 # magically baked into the compiler.
3732 LIBS_STRICT = False,
3735 linux_coverage_env.FilterOut(CCFLAGS=['-fPIE'])
3736 linux_coverage_env.Append(CCFLAGS=['-fPIC'])
3738 linux_coverage_env['OPTIONAL_COVERAGE_LIBS'] = '$COVERAGE_LIBS'
3739 AddDualLibrary(linux_coverage_env)
3740 environment_list.append(linux_coverage_env)
3743 # Environment Massaging
3744 RELEVANT_CONFIG = ['NACL_BUILD_FAMILY',
3748 'BUILD_TYPE_DESCRIPTION',
3751 MAYBE_RELEVANT_CONFIG = ['BUILD_OS',
3752 'BUILD_ARCHITECTURE',
3755 'TARGET_ARCHITECTURE',
3759 def DumpCompilerVersion(cc, env):
3761 env.Execute(env.Action('set'))
3762 env.Execute(env.Action('${CC} -v -c'))
3763 env.Execute(env.Action('${CC} -print-search-dirs'))
3764 env.Execute(env.Action('${CC} -print-libgcc-file-name'))
3765 elif cc.startswith('cl'):
3768 p = subprocess.Popen(env.subst('${CC} /V'),
3770 stdout=subprocess.PIPE,
3771 stderr=subprocess.PIPE)
3772 stdout, stderr = p.communicate()
3773 print stderr[0:stderr.find("\r")]
3774 except WindowsError:
3775 # If vcvars was not run before running SCons, we won't be able to find
3776 # the compiler at this point. SCons has built in functions for finding
3777 # the compiler, but they haven't run yet.
3778 print 'Can not find the compiler, assuming SCons will find it later.'
3780 print "UNKNOWN COMPILER"
3783 def SanityCheckEnvironments(all_envs):
3784 # simple completeness check
3785 for env in all_envs:
3786 for tag in RELEVANT_CONFIG:
3787 assert tag in env, repr(tag)
3788 assert env[tag], repr(env[tag])
3791 def LinkTrustedEnv(selected_envs):
3792 # Collect build families and ensure that we have only one env per family.
3794 for env in selected_envs:
3795 family = env['NACL_BUILD_FAMILY']
3796 if family not in family_map:
3797 family_map[family] = env
3799 msg = 'You are using incompatible environments simultaneously\n'
3800 msg += '%s vs %s\n' % (env['BUILD_TYPE'],
3801 family_map[family]['BUILD_TYPE'])
3802 msg += ('Please specfy the exact environments you require, e.g. '
3803 'MODE=dbg-host,nacl')
3804 raise Exception(msg)
3806 # Set TRUSTED_ENV so that tests of untrusted code can locate sel_ldr
3807 # etc. We set this on trusted envs too because some tests on
3808 # trusted envs run sel_ldr (e.g. using checked-in binaries).
3809 if 'TRUSTED' in family_map:
3810 for env in selected_envs:
3811 env['TRUSTED_ENV'] = family_map['TRUSTED']
3812 # Propagate some environment variables from the trusted environment,
3813 # in case some (e.g. Mac's DYLD_LIBRARY_PATH) are necessary for
3814 # running sel_ldr et al in untrusted environments' tests.
3815 for var in env['TRUSTED_ENV'].get('PROPAGATE_ENV', []):
3816 env['ENV'][var] = env['TRUSTED_ENV']['ENV'][var]
3817 if 'TRUSTED' not in family_map or 'UNTRUSTED' not in family_map:
3818 Banner('Warning: "--mode" did not specify both trusted and untrusted '
3819 'build environments. As a result, many tests will not be run.')
3822 build_platform = GetBuildPlatform()
3824 # Build Platform Base Function
3825 platform_func_map = {
3826 'win32' : MakeWindowsEnv,
3827 'cygwin': MakeWindowsEnv,
3828 'linux' : MakeGenericLinuxEnv,
3829 'linux2': MakeGenericLinuxEnv,
3830 'darwin': MakeMacEnv,
3832 if sys.platform not in platform_func_map:
3833 raise UserError('Unrecognized host platform: %s', sys.platform)
3834 make_env_func = platform_func_map[sys.platform]
3836 build_env = make_env_func(build_platform)
3837 build_env['IS_BUILD_ENV'] = True
3839 # Building tls_edit depends on gio, platform, and validator_ragel.
3840 build_env['BUILD_SCONSCRIPTS'] = [
3841 # KEEP THIS SORTED PLEASE
3842 'src/shared/gio/build.scons',
3843 'src/shared/platform/build.scons',
3844 'src/trusted/validator_ragel/build.scons',
3847 # The build environment is only used for intermediate steps and should
3848 # not be creating any targets. Aliases are used as means to add targets
3849 # to builds (IE, all_programs, all_libraries...etc.). Since we want to
3850 # share all of our build scripts but not define any aliases, we should
3851 # override the alias function and essentially stub it out.
3852 build_env.Alias = lambda env, target, source=[], actions=None, **kw : []
3856 def LinkBuildEnv(selected_envs):
3858 'opt': opt_build_env,
3859 'dbg': dbg_build_env,
3862 # We need to find the optimization level in order to know which
3863 # build environment we want to use
3865 for env in selected_envs:
3866 if env.get('OPTIMIZATION_LEVEL', None):
3867 opt_level = env['OPTIMIZATION_LEVEL']
3870 build_env = build_env_map.get(opt_level, opt_build_env)
3871 for env in selected_envs:
3872 env['BUILD_ENV'] = build_env
3874 # If the build environment is different from all the selected environments,
3875 # we will need to also append it to the selected environments so the targets
3877 build_env_root = build_env.subst('${TARGET_ROOT}')
3878 for env in selected_envs:
3879 if build_env_root == env.subst('${TARGET_ROOT}'):
3882 # Did not find a matching environment, append the build environment now.
3883 selected_envs.append(build_env)
3885 def DumpEnvironmentInfo(selected_envs):
3886 if VerboseConfigInfo(pre_base_env):
3887 Banner("The following environments have been configured")
3888 for env in selected_envs:
3889 for tag in RELEVANT_CONFIG:
3890 assert tag in env, repr(tag)
3891 print "%s: %s" % (tag, env.subst(env.get(tag)))
3892 for tag in MAYBE_RELEVANT_CONFIG:
3893 print "%s: %s" % (tag, env.subst(env.get(tag)))
3894 cc = env.subst('${CC}')
3896 asppcom = env.subst('${ASPPCOM}')
3897 print 'ASPPCOM:', asppcom
3898 DumpCompilerVersion(cc, env)
3900 rev_file = 'toolchain/linux_x86_pnacl/pnacl_newlib/REV'
3901 if os.path.exists(rev_file):
3902 for line in open(rev_file).read().split('\n'):
3903 if "Revision:" in line:
3904 print "PNACL : %s" % line
3906 def PnaclSetEmulatorForSandboxedTranslator(selected_envs):
3907 # Slip in emulator flags if necessary, for the sandboxed pnacl translator
3908 # on ARM, once emulator is actually known (vs in naclsdk.py, where it
3909 # is not yet known).
3910 for env in selected_envs:
3911 if (env.Bit('bitcode')
3912 and env.Bit('use_sandboxed_translator')
3913 and env.UsingEmulator()):
3914 # This must modify the LINK command itself, since LINKFLAGS may
3915 # be filtered (e.g., in barebones tests).
3916 env.Append(LINK=' --pnacl-use-emulator')
3917 env.Append(TRANSLATE=' --pnacl-use-emulator')
3920 # Blank out defaults.
3923 # Apply optional supplement if present in the directory tree.
3924 if os.path.exists(pre_base_env.subst('$MAIN_DIR/supplement/supplement.scons')):
3925 SConscript('supplement/supplement.scons', exports=['environment_list'])
3927 # print sytem info (optionally)
3928 if VerboseConfigInfo(pre_base_env):
3929 Banner('SCONS ARGS:' + str(sys.argv))
3930 os.system(pre_base_env.subst('${PYTHON} tools/sysinfo.py'))
3934 SanityCheckEnvironments(environment_list)
3935 selected_envs = FilterEnvironments(environment_list)
3937 # If we are building NaCl, build nacl_irt too. This works around it being
3938 # a separate mode due to the vagaries of scons when we'd really rather it
3939 # not be, while not requiring that every bot command line using --mode be
3940 # changed to list '...,nacl,nacl_irt' explicitly.
3941 if nacl_env in selected_envs:
3942 selected_envs.append(nacl_irt_env)
3944 # The nacl_irt_test_env requires nacl_env to build things correctly.
3945 if nacl_irt_test_env in selected_envs and nacl_env not in selected_envs:
3946 selected_envs.append(nacl_env)
3948 DumpEnvironmentInfo(selected_envs)
3949 LinkTrustedEnv(selected_envs)
3951 # When building NaCl, any intermediate build tool that is used during the
3952 # build process must be built using the current build environment, not the
3953 # target. Create a build environment for this purpose and link it into
3954 # the selected environments
3955 dbg_build_env, opt_build_env = GenerateOptimizationLevels(MakeBuildEnv())
3956 LinkBuildEnv(selected_envs)
3958 # This must happen after LinkTrustedEnv, since that is where TRUSTED_ENV
3959 # is finally set, and env.UsingEmulator() checks TRUSTED_ENV for the emulator.
3960 # This must also happen before BuildEnvironments.
3961 PnaclSetEmulatorForSandboxedTranslator(selected_envs)
3963 BuildEnvironments(selected_envs)
3965 # Change default to build everything, but not run tests.
3966 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
3969 # Sanity check whether we are ready to build nacl modules
3970 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3971 if nacl_env.Bit('naclsdk_validate') and (nacl_env in selected_envs or
3972 nacl_irt_env in selected_envs):
3973 nacl_env.ValidateSdk()
3975 if BROKEN_TEST_COUNT > 0:
3976 msg = "There are %d broken tests." % BROKEN_TEST_COUNT
3977 if GetOption('brief_comstr'):
3978 msg += " Add --verbose to the command line for more information."
3981 # separate warnings from actual build output
3982 Banner('B U I L D - O U T P U T:')