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 # NOTE: Underlay for src/third_party_mod/gtest
32 # TODO: try to eliminate this hack
33 Dir('src/third_party_mod/gtest').addRepository(
34 Dir('#/../testing/gtest'))
36 # turning garbage collection off reduces startup time by 10%
43 def PrintFinalReport():
44 """This function is run just before scons exits and dumps various reports.
46 # Note, these global declarations are not strictly necessary
51 if pre_base_env.Bit('target_stats'):
54 print 'COMMAND EXECUTION REPORT'
56 for k in sorted(CMD_COUNTER.keys()):
57 print "%4d %s" % (CMD_COUNTER[k], k)
61 print 'ENVIRONMENT USAGE REPORT'
63 for k in sorted(ENV_COUNTER.keys()):
64 print "%4d %s" % (ENV_COUNTER[k], k)
67 for failure in GetBuildFailures():
68 for node in Flatten(failure.node):
70 # If this wasn't a test, "GetTestName" will return raw_name.
71 'test_name': GetTestName(node),
72 'raw_name': str(node.path),
73 'errstr': failure.errstr
76 json_path = ARGUMENTS.get('json_build_results_output_file')
78 with open(json_path, 'w') as f:
79 json.dump(failures, f, sort_keys=True, indent=2)
86 print 'ERROR REPORT: %d failures' % len(failures)
89 for failure in failures:
90 test_name = failure['test_name']
91 if test_name != failure['raw_name']:
92 test_name = '%s (%s)' % (test_name, failure['raw_name'])
93 print "%s failed: %s\n" % (test_name, failure['errstr'])
96 def VerboseConfigInfo(env):
97 "Should we print verbose config information useful for bug reports"
98 if '--help' in sys.argv: return False
99 if env.Bit('prebuilt') or env.Bit('built_elsewhere'): return False
100 return env.Bit('sysinfo')
105 # NOTE BitFromArgument(...) implicitly defines additional ACCEPTABLE_ARGUMENTS.
106 ACCEPTABLE_ARGUMENTS = set([
107 # TODO: add comments what these mean
108 # TODO: check which ones are obsolete
109 #### ASCII SORTED ####
110 # Use a destination directory other than the default "scons-out".
114 # Limit bandwidth of browser tester
116 # Location to download Chromium binaries to and/or read them from.
117 'chrome_binaries_dir',
118 # used for chrome_browser_tests: path to the browser
119 'chrome_browser_path',
120 # A comma-separated list of test names to disable by excluding the
121 # tests from a test suite. For example, 'small_tests
122 # disable_tests=run_hello_world_test' will run small_tests without
123 # including hello_world_test. Note that if a test listed here
124 # does not exist you will not get an error or a warning.
126 # used for chrome_browser_tests: path to a pre-built browser plugin.
127 'force_ppapi_plugin',
128 # force emulator use by tests
130 # force sel_ldr use by tests
132 # force irt image used by tests
134 # Path to a JSON file for machine-readable output.
135 'json_build_results_output_file',
136 # Replacement memcheck command for overriding the DEPS-in memcheck
137 # script. May have commas to separate separate shell args. There
138 # is no quoting, so this implies that this mechanism will fail if
139 # the args actually need to have commas. See
140 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
141 # the discussion of why this argument is needed.
143 # If the replacement memcheck command only works for trusted code,
144 # set memcheck_trusted_only to non-zero.
145 'memcheck_trusted_only',
146 # colon-separated list of linker flags, e.g. "-lfoo:-Wl,-u,bar".
148 # colon-separated list of pnacl bcld flags, e.g. "-lfoo:-Wl,-u,bar".
149 # Not using nacl_linkflags since that gets clobbered in some tests.
154 # Run tests under this tool (e.g. valgrind, tsan, strace, etc).
155 # If the tool has options, pass them after comma: 'tool,--opt1,--opt2'.
156 # NB: no way to use tools the names or the args of
157 # which contains a comma.
159 # More args for the tool.
160 'run_under_extra_args',
161 # Multiply timeout values by this number.
163 # test_wrapper specifies a wrapper program such as
164 # tools/run_test_via_ssh.py, which runs tests on a remote host
165 # using rsync and SSH. Example usage:
166 # ./scons run_hello_world_test platform=arm force_emulator= \
167 # test_wrapper="./tools/run_test_via_ssh.py --host=armbox --subdir=tmp"
169 # Replacement tsan command for overriding the DEPS-in tsan
170 # script. May have commas to separate separate shell args. There
171 # is no quoting, so this implies that this mechanism will fail if
172 # the args actually need to have commas. See
173 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
174 # the discussion of why this argument is needed.
176 # Run browser tests under this tool. See
177 # tools/browser_tester/browsertester/browserlauncher.py for tool names.
179 # activates buildbot-specific presets
181 # Where to install header files for public consumption.
183 # Where to install libraries for public consumption.
185 # Where to install trusted-code binaries for public (SDK) consumption.
187 # Where a Breakpad build output directory is for optional Breakpad testing.
188 'breakpad_tools_dir',
189 # Allows overriding the version number in the toolchain's
190 # FEATURE_VERSION file. This is used for PNaCl ABI compatibility
192 'toolchain_feature_version',
196 # Overly general to provide compatibility with existing build bots, etc.
197 # In the future it might be worth restricting the values that are accepted.
198 _TRUE_STRINGS = set(['1', 'true', 'yes'])
199 _FALSE_STRINGS = set(['0', 'false', 'no'])
202 # Converts a string representing a Boolean value, of some sort, into an actual
203 # Boolean value. Python's built in type coercion does not work because
204 # bool('False') == True
205 def StringValueToBoolean(value):
206 # ExpandArguments may stick non-string values in ARGUMENTS. Be accommodating.
207 if isinstance(value, bool):
210 if not isinstance(value, basestring):
211 raise Exception("Expecting a string but got a %s" % repr(type(value)))
213 if value.lower() in _TRUE_STRINGS:
215 elif value.lower() in _FALSE_STRINGS:
218 raise Exception("Cannot convert '%s' to a Boolean value" % value)
221 def GetBinaryArgumentValue(arg_name, default):
222 if not isinstance(default, bool):
223 raise Exception("Default value for '%s' must be a Boolean" % arg_name)
224 if arg_name not in ARGUMENTS:
226 return StringValueToBoolean(ARGUMENTS[arg_name])
229 # name is the name of the bit
230 # arg_name is the name of the command-line argument, if it differs from the bit
231 def BitFromArgument(env, name, default, desc, arg_name=None):
232 # In most cases the bit name matches the argument name
236 DeclareBit(name, desc)
237 assert arg_name not in ACCEPTABLE_ARGUMENTS, repr(arg_name)
238 ACCEPTABLE_ARGUMENTS.add(arg_name)
240 if GetBinaryArgumentValue(arg_name, default):
246 # SetUpArgumentBits declares binary command-line arguments and converts them to
247 # bits. For example, one of the existing declarations would result in the
248 # argument "bitcode=1" causing env.Bit('bitcode') to evaluate to true.
249 # NOTE Command-line arguments are a SCons-ism that is separate from
250 # command-line options. Options are prefixed by "-" or "--" whereas arguments
251 # are not. The function SetBitFromOption can be used for options.
252 # NOTE This function must be called before the bits are used
253 # NOTE This function must be called after all modifications of ARGUMENTS have
254 # been performed. See: ExpandArguments
255 def SetUpArgumentBits(env):
256 BitFromArgument(env, 'bitcode', default=False,
257 desc='We are building bitcode')
259 BitFromArgument(env, 'translate_fast', default=False,
260 desc='When using pnacl TC (bitcode=1) use accelerated translation step')
262 BitFromArgument(env, 'built_elsewhere', default=False,
263 desc='The programs have already been built by another system')
265 BitFromArgument(env, 'skip_trusted_tests', default=False,
266 desc='Only run untrusted tests - useful for translator testing'
267 ' (also skips tests of the IRT itself')
269 BitFromArgument(env, 'nacl_pic', default=False,
270 desc='generate position indepent code for (P)NaCl modules')
272 BitFromArgument(env, 'nacl_static_link', default=not env.Bit('nacl_glibc'),
273 desc='Whether to use static linking instead of dynamic linking '
274 'for building NaCl executables during tests. '
275 'For nacl-newlib, the default is 1 (static linking). '
276 'For nacl-glibc, the default is 0 (dynamic linking).')
278 BitFromArgument(env, 'nacl_disable_shared', default=not env.Bit('nacl_glibc'),
279 desc='Do not build shared versions of libraries. '
280 'For nacl-newlib, the default is 1 (static libraries only). '
281 'For nacl-glibc, the default is 0 (both static and shared libraries).')
283 # Defaults on when --verbose is specified.
284 # --verbose sets 'brief_comstr' to False, so this looks a little strange
285 BitFromArgument(env, 'target_stats', default=not GetOption('brief_comstr'),
286 desc='Collect and display information about which commands are executed '
287 'during the build process')
289 BitFromArgument(env, 'werror', default=True,
290 desc='Treat warnings as errors (-Werror)')
292 BitFromArgument(env, 'disable_nosys_linker_warnings', default=False,
293 desc='Disable warning mechanism in src/untrusted/nosys/warning.h')
295 BitFromArgument(env, 'naclsdk_validate', default=True,
296 desc='Verify the presence of the SDK')
298 BitFromArgument(env, 'running_on_valgrind', default=False,
299 desc='Compile and test using valgrind')
301 BitFromArgument(env, 'enable_tmpfs_redirect_var', default=False,
302 desc='Allow redirecting tmpfs location for shared memory '
303 '(by default, /dev/shm is used)')
305 BitFromArgument(env, 'pp', default=False,
306 desc='Enable pretty printing')
308 # Defaults on when --verbose is specified
309 # --verbose sets 'brief_comstr' to False, so this looks a little strange
310 BitFromArgument(env, 'sysinfo', default=not GetOption('brief_comstr'),
311 desc='Print verbose system information')
313 BitFromArgument(env, 'disable_flaky_tests', default=False,
314 desc='Do not run potentially flaky tests - used on Chrome bots')
316 BitFromArgument(env, 'use_sandboxed_translator', default=False,
317 desc='use pnacl sandboxed translator for linking (not available for arm)')
319 BitFromArgument(env, 'pnacl_generate_pexe', default=env.Bit('bitcode'),
320 desc='use pnacl to generate pexes and translate in a separate step')
322 BitFromArgument(env, 'translate_in_build_step', default=True,
323 desc='Run translation during build phase (e.g. if do_not_run_tests=1)')
325 BitFromArgument(env, 'pnacl_unsandboxed', default=False,
326 desc='Translate pexe to an unsandboxed, host executable')
328 BitFromArgument(env, 'browser_headless', default=False,
329 desc='Where possible, set up a dummy display to run the browser on '
330 'when running browser tests. On Linux, this runs the browser through '
331 'xvfb-run. This Scons does not need to be run with an X11 display '
332 'and we do not open a browser window on the user\'s desktop. '
333 'Unfortunately there is no equivalent on Mac OS X.')
335 BitFromArgument(env, 'disable_crash_dialog', default=True,
336 desc='Disable Windows\' crash dialog box, which Windows pops up when a '
337 'process exits with an unhandled fault. Windows enables this by '
338 'default for processes launched from the command line or from the '
339 'GUI. Our default is to disable it, because the dialog turns crashes '
340 'into hangs on Buildbot, and our test suite includes various crash '
343 BitFromArgument(env, 'do_not_run_tests', default=False,
344 desc='Prevents tests from running. This lets SCons build the files needed '
345 'to run the specified test(s) without actually running them. This '
346 'argument is a counterpart to built_elsewhere.')
348 BitFromArgument(env, 'validator_ragel', default=True,
349 desc='Use the R-DFA validator instead of the original validators.')
351 # TODO(shcherbina): add support for other golden-based tests, not only
352 # run_x86_*_validator_testdata_tests.
353 BitFromArgument(env, 'regenerate_golden', default=False,
354 desc='When running golden-based tests, instead of comparing results '
355 'save actual output as golden data.')
357 BitFromArgument(env, 'x86_64_zero_based_sandbox', default=False,
358 desc='Use the zero-address-based x86-64 sandbox model instead of '
359 'the r15-based model.')
361 BitFromArgument(env, 'android', default=False,
362 desc='Build for Android target')
364 BitFromArgument(env, 'arm_hard_float', default=True,
365 desc='Build for hard float ARM ABI')
367 BitFromArgument(env, 'skip_nonstable_bitcode', default=False,
368 desc='Skip tests involving non-stable bitcode')
370 #########################################################################
372 # This is for generating a testing library for use within private test
373 # enuminsts, where we want to compare and test different validators.
375 BitFromArgument(env, 'ncval_testing', default=False,
376 desc='EXPERIMENTAL: Compile validator code for testing within enuminsts')
378 # PNaCl sanity checks
379 if ((env.Bit('pnacl_generate_pexe') or env.Bit('use_sandboxed_translator'))
380 and not env.Bit('bitcode')):
381 raise UserError("pnacl_generate_pexe and use_sandboxed_translator"
382 " don't make sense without bitcode")
384 # Sandboxed translator only accepts stable bitcode. Hence we must disallow
385 # nonstable bitcodes.
386 if env.Bit('use_sandboxed_translator'):
387 env.SetBits('skip_nonstable_bitcode')
389 def CheckArguments():
390 for key in ARGUMENTS:
391 if key not in ACCEPTABLE_ARGUMENTS:
392 raise UserError('bad argument: %s' % key)
395 # Sets a command line argument. Dies if an argument with this name is already
397 def SetArgument(key, value):
398 print ' %s=%s' % (key, str(value))
400 raise UserError('ERROR: %s redefined' % (key, ))
401 ARGUMENTS[key] = value
403 # Expands "macro" command line arguments.
404 def ExpandArguments():
405 if ARGUMENTS.get('buildbot') == 'memcheck':
406 print 'buildbot=memcheck expands to the following arguments:'
407 SetArgument('run_under',
408 ARGUMENTS.get('memcheck_command',
409 'src/third_party/valgrind/memcheck.sh') +
410 ',--error-exitcode=1')
411 SetArgument('scale_timeout', 20)
412 SetArgument('running_on_valgrind', True)
413 elif ARGUMENTS.get('buildbot') == 'tsan':
414 print 'buildbot=tsan expands to the following arguments:'
415 SetArgument('run_under',
416 ARGUMENTS.get('tsan_command',
417 'src/third_party/valgrind/tsan.sh') +
418 ',--nacl-untrusted,--error-exitcode=1,' +
419 '--suppressions=src/third_party/valgrind/tests.supp')
420 SetArgument('scale_timeout', 20)
421 SetArgument('running_on_valgrind', True)
422 elif ARGUMENTS.get('buildbot') == 'tsan-trusted':
423 print 'buildbot=tsan-trusted expands to the following arguments:'
424 SetArgument('run_under',
425 ARGUMENTS.get('tsan_command',
426 'src/third_party/valgrind/tsan.sh') +
427 ',--error-exitcode=1,' +
428 '--suppressions=src/third_party/valgrind/tests.supp')
429 SetArgument('scale_timeout', 20)
430 SetArgument('running_on_valgrind', True)
431 elif ARGUMENTS.get('buildbot') == 'memcheck-browser-tests':
432 print 'buildbot=memcheck-browser-tests expands to the following arguments:'
433 SetArgument('browser_test_tool', 'memcheck')
434 SetArgument('scale_timeout', 20)
435 SetArgument('running_on_valgrind', True)
436 elif ARGUMENTS.get('buildbot') == 'tsan-browser-tests':
437 print 'buildbot=tsan-browser-tests expands to the following arguments:'
438 SetArgument('browser_test_tool', 'tsan')
439 SetArgument('scale_timeout', 20)
440 SetArgument('running_on_valgrind', True)
441 elif ARGUMENTS.get('buildbot'):
442 raise UserError('ERROR: unexpected argument buildbot="%s"' % (
443 ARGUMENTS.get('buildbot'), ))
447 def GetTargetPlatform():
448 return ARGUMENTS.get('platform', 'x86-32')
450 def GetBuildPlatform():
451 arch_dict = pynacl.platform.ArchDict()
452 machine = platform.machine().lower()
453 if machine not in arch_dict:
454 raise UserError('Unrecognized host architecture: %s', platform.machine())
455 return arch_dict[machine]
457 environment_list = []
459 # Base environment for both nacl and non-nacl variants.
461 if ARGUMENTS.get('DESTINATION_ROOT') is not None:
462 kwargs['DESTINATION_ROOT'] = ARGUMENTS.get('DESTINATION_ROOT')
463 pre_base_env = Environment(
464 # Use the environment that scons was run in to run scons invoked commands.
465 # This allows in things like externally provided PATH, PYTHONPATH.
466 ENV = os.environ.copy(),
467 tools = ['component_setup'],
468 # SOURCE_ROOT is one leave above the native_client directory.
469 SOURCE_ROOT = Dir('#/..').abspath,
470 # Publish dlls as final products (to staging).
471 COMPONENT_LIBRARY_PUBLISH = True,
473 # Use workaround in special scons version.
475 LIBS_DO_SUBST = True,
477 # Select where to find coverage tools.
478 COVERAGE_MCOV = '../third_party/lcov/bin/mcov',
479 COVERAGE_GENHTML = '../third_party/lcov/bin/genhtml',
484 breakpad_tools_dir = ARGUMENTS.get('breakpad_tools_dir')
485 if breakpad_tools_dir is not None:
486 pre_base_env['BREAKPAD_TOOLS_DIR'] = pre_base_env.Dir(
487 os.path.abspath(breakpad_tools_dir))
491 DeclareBit('clang', 'Use clang to build trusted code')
492 pre_base_env.SetBitFromOption('clang', False)
495 'Use AddressSanitizer to build trusted code (implies --clang)')
496 pre_base_env.SetBitFromOption('asan', False)
497 if pre_base_env.Bit('asan'):
498 pre_base_env.SetBits('clang')
502 DeclareBit('coverage_enabled', 'The build should be instrumented to generate'
503 'coverage information')
505 # If the environment variable BUILDBOT_BUILDERNAME is set, we can determine
506 # if we are running in a VM by the lack of a '-bare-' (aka bare metal) in the
507 # bot name. Otherwise if the builder name is not set, then assume real HW.
508 DeclareBit('running_on_vm', 'Returns true when environment is running in a VM')
509 builder = os.environ.get('BUILDBOT_BUILDERNAME')
510 if builder and builder.find('-bare-') == -1:
511 pre_base_env.SetBits('running_on_vm')
513 pre_base_env.ClearBits('running_on_vm')
515 DeclareBit('nacl_glibc', 'Use nacl-glibc for building untrusted code')
516 pre_base_env.SetBitFromOption('nacl_glibc', False)
518 # This function should be called ASAP after the environment is created, but
519 # after ExpandArguments.
520 SetUpArgumentBits(pre_base_env)
522 # Register PrintFinalReport only after SetUpArgumentBits since it references
523 # bits that get declared in SetUpArgumentBits
524 atexit.register(PrintFinalReport)
526 def DisableCrashDialog():
527 if sys.platform == 'win32':
530 # The double call is to preserve existing flags, as discussed at
531 # http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
532 new_flags = win32con.SEM_NOGPFAULTERRORBOX
533 existing_flags = win32api.SetErrorMode(new_flags)
534 win32api.SetErrorMode(existing_flags | new_flags)
536 if pre_base_env.Bit('disable_crash_dialog'):
539 # We want to pull CYGWIN setup in our environment or at least set flag
540 # nodosfilewarning. It does not do anything when CYGWIN is not involved
541 # so let's do it in all cases.
542 pre_base_env['ENV']['CYGWIN'] = os.environ.get('CYGWIN', 'nodosfilewarning')
544 # Note: QEMU_PREFIX_HOOK may influence test runs and sb translator invocations
545 pre_base_env['ENV']['QEMU_PREFIX_HOOK'] = os.environ.get('QEMU_PREFIX_HOOK', '')
547 # Allow the zero-based sandbox model to run insecurely.
548 # TODO(arbenson): remove this once binutils bug is fixed (see
549 # src/trusted/service_runtime/arch/x86_64/sel_addrspace_posix_x86_64.c)
550 if pre_base_env.Bit('x86_64_zero_based_sandbox'):
551 pre_base_env['ENV']['NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX'] = 1
553 if pre_base_env.Bit('werror'):
554 werror_flags = ['-Werror']
558 # Allow variadic macros
559 werror_flags = werror_flags + ['-Wno-variadic-macros']
561 if pre_base_env.Bit('clang'):
562 # Allow 'default' label in switch even when all enumeration cases
564 werror_flags += ['-Wno-covered-switch-default']
565 # Allow C++11 extensions (for "override")
566 werror_flags += ['-Wno-c++11-extensions']
569 # Method to make sure -pedantic, etc, are not stripped from the
570 # default env, since occasionally an engineer will be tempted down the
571 # dark -- but wide and well-trodden -- path of expediency and stray
572 # from the path of correctness.
574 def EnsureRequiredBuildWarnings(env):
575 if env.Bit('linux') or env.Bit('mac'):
576 required_env_flags = set(['-pedantic', '-Wall'] + werror_flags)
577 ccflags = set(env.get('CCFLAGS'))
579 if not required_env_flags.issubset(ccflags):
580 raise UserError('required build flags missing: '
581 + ' '.join(required_env_flags.difference(ccflags)))
583 # windows get a pass for now
586 pre_base_env.AddMethod(EnsureRequiredBuildWarnings)
588 # Expose MakeTempDir and MakeTempFile to scons scripts
589 pre_base_env.AddMethod(test_lib.MakeTempDir)
590 pre_base_env.AddMethod(test_lib.MakeTempFile)
592 # Method to add target suffix to name.
593 def NaClTargetArchSuffix(env, name):
594 return name + '_' + env['TARGET_FULLARCH'].replace('-', '_')
596 pre_base_env.AddMethod(NaClTargetArchSuffix)
599 # Generic Test Wrapper
601 # Add list of Flaky or Bad tests to skip per platform. A
602 # platform is defined as build type
603 # <BUILD_TYPE>-<SUBARCH>
608 # This is a list of tests that do not yet pass when using nacl-glibc.
609 # TODO(mseaborn): Enable more of these tests!
610 nacl_glibc_skiplist = set([
611 # Struct layouts differ.
613 # Syscall wrappers not implemented yet.
616 # Fails because clock() is not hooked up.
617 'run_timefuncs_test',
618 # Needs further investigation.
620 # run_srpc_sysv_shm_test fails because:
621 # 1) it uses fstat(), while we only have an fstat64() wrapper;
622 # 2) the test needs an explicit fflush(stdout) call because the
623 # process is killed without exit() being called.
624 'run_srpc_sysv_shm_test',
625 # This test fails with nacl-glibc: glibc reports an internal
626 # sanity check failure in free().
627 # TODO(robertm): This needs further investigation.
628 'run_ppapi_event_test',
629 'run_srpc_ro_file_test',
630 'run_ppapi_geturl_valid_test',
631 'run_ppapi_geturl_invalid_test',
632 # http://code.google.com/p/chromium/issues/detail?id=108131
633 # we would need to list all of the glibc components as
634 # web accessible resources in the extensions's manifest.json,
635 # not just the nexe and nmf file.
636 'run_ppapi_extension_mime_handler_browser_test',
638 nacl_glibc_skiplist.update(['%s_irt' % test for test in nacl_glibc_skiplist])
641 # If a test is not in one of these suites, it will probally not be run on a
642 # regular basis. These are the suites that will be run by the try bot or that
643 # a large number of users may run by hand.
644 MAJOR_TEST_SUITES = set([
648 # Tests using the pepper plugin, only run with chrome
649 # TODO(ncbray): migrate pepper_browser_tests to chrome_browser_tests
650 'pepper_browser_tests',
651 # Lightweight browser tests
652 'chrome_browser_tests',
654 'memcheck_bot_tests',
656 # Special testing environment for testing comparing x86 validators.
658 # Environment for validator difference testing
659 'validator_diff_tests',
662 # These are the test suites we know exist, but aren't run on a regular basis.
663 # These test suites are essentially shortcuts that run a specific subset of the
665 ACCEPTABLE_TEST_SUITES = set([
667 'dynamic_load_tests',
668 'eh_tests', # Tests for C++ exception handling
669 'exception_tests', # Tests for hardware exception handling
676 'sel_ldr_sled_tests',
679 'validator_modeling',
681 # Special testing of the decoder for the ARM validator.
685 # Under --mode=nacl_irt_test we build variants of numerous tests normally
686 # built under --mode=nacl. The test names and suite names for these
687 # variants are set (in IrtTestAddNodeToTestSuite, below) by appending _irt
688 # to the names used for the --mode=nacl version of the same tests.
689 MAJOR_TEST_SUITES |= set([name + '_irt'
690 for name in MAJOR_TEST_SUITES])
691 ACCEPTABLE_TEST_SUITES |= set([name + '_irt'
692 for name in ACCEPTABLE_TEST_SUITES])
694 # The major test suites are also acceptable names. Suite names are checked
695 # against this set in order to catch typos.
696 ACCEPTABLE_TEST_SUITES.update(MAJOR_TEST_SUITES)
699 def ValidateTestSuiteNames(suite_name, node_name):
700 if node_name is None:
701 node_name = '<unknown>'
703 # Prevent a silent failiure - strings are iterable!
704 if not isinstance(suite_name, (list, tuple)):
705 raise Exception("Test suites for %s should be specified as a list, "
706 "not as a %s: %s" % (node_name, type(suite_name).__name__,
710 raise Exception("No test suites are specified for %s. Set the 'broken' "
711 "parameter on AddNodeToTestSuite in the cases where there's a known "
712 "issue and you don't want the test to run" % (node_name,))
714 # Make sure each test is in at least one test suite we know will run
715 major_suites = set(suite_name).intersection(MAJOR_TEST_SUITES)
717 raise Exception("None of the test suites %s for %s are run on a "
718 "regular basis" % (repr(suite_name), node_name))
720 # Make sure a wierd test suite hasn't been inadvertantly specified
722 if s not in ACCEPTABLE_TEST_SUITES:
723 raise Exception("\"%s\" is not a known test suite. Either this is "
724 "a typo for %s, or it should be added to ACCEPTABLE_TEST_SUITES in "
725 "SConstruct" % (s, node_name))
727 BROKEN_TEST_COUNT = 0
730 def GetPlatformString(env):
731 build = env['BUILD_TYPE']
733 # If we are testing 'NACL' we really need the trusted info
734 if build=='nacl' and 'TRUSTED_ENV' in env:
735 trusted_env = env['TRUSTED_ENV']
736 build = trusted_env['BUILD_TYPE']
737 subarch = trusted_env['BUILD_SUBARCH']
739 subarch = env['BUILD_SUBARCH']
741 # Build the test platform string
742 return build + '-' + subarch
744 pre_base_env.AddMethod(GetPlatformString)
747 tests_to_disable_qemu = set([
748 # These tests do not work under QEMU but do work on ARM hardware.
750 # You should use the is_broken argument in preference to adding
751 # tests to this list.
753 # TODO(dschuff) some of these tests appear to work with the new QEMU.
755 # http://code.google.com/p/nativeclient/issues/detail?id=2437
756 # Note, for now these tests disable both the irt and non-irt variants
757 'run_atomic_ops_test', # still broken with qemu 2012/06/12
758 'run_atomic_ops_nexe_test',
759 'run_egyptian_cotton_test', # still broken with qemu 2012/06/12
760 'run_many_threads_sequential_test',
761 'run_mmap_atomicity_test', # still broken with qemu 2012/06/12
762 # http://code.google.com/p/nativeclient/issues/detail?id=2142
763 'run_nacl_semaphore_test',
764 'run_nacl_tls_unittest',
765 # subprocess needs to also have qemu prefix, which isn't supported
766 'run_subprocess_test',
767 # The next 2 tests seem flaky on QEMU
768 'run_srpc_manifest_file_test',
769 'run_srpc_message_untrusted_test',
770 'run_thread_stack_alloc_test',
771 'run_thread_suspension_test',
773 'run_dynamic_modify_test',
774 # qemu has bugs that make TestCatchingFault flaky (see
775 # http://code.google.com/p/nativeclient/issues/detail?id=3239), and
776 # we don't particularly need to measure performance under qemu.
777 'run_performance_test',
780 tests_to_disable = set()
781 if ARGUMENTS.get('disable_tests', '') != '':
782 tests_to_disable.update(ARGUMENTS['disable_tests'].split(','))
785 def ShouldSkipTest(env, node_name):
786 if (env.Bit('skip_trusted_tests')
787 and (env['NACL_BUILD_FAMILY'] == 'TRUSTED'
788 or env['NACL_BUILD_FAMILY'] == 'UNTRUSTED_IRT')):
791 if env.Bit('do_not_run_tests'):
792 # This hack is used for pnacl testing where we might build tests
793 # without running them on one bot and then transfer and run them on another.
794 # The skip logic only takes the first bot into account e.g. qemu
795 # restrictions, while it really should be skipping based on the second
796 # bot. By simply disabling the skipping completely we work around this.
799 # There are no known-to-fail tests any more, but this code is left
800 # in so that if/when we port to a new architecture or add a test
801 # that is known to fail on some platform(s), we can continue to have
802 # a central location to disable tests from running. NB: tests that
803 # don't *build* on some platforms need to be omitted in another way.
805 if node_name in tests_to_disable:
808 if env.UsingEmulator():
809 if node_name in tests_to_disable_qemu:
811 # For now also disable the irt variant
812 if node_name.endswith('_irt') and node_name[:-4] in tests_to_disable_qemu:
815 # Retrieve list of tests to skip on this platform
816 skiplist = bad_build_lists.get(env.GetPlatformString(), [])
817 if node_name in skiplist:
820 if env.Bit('nacl_glibc') and node_name in nacl_glibc_skiplist:
825 pre_base_env.AddMethod(ShouldSkipTest)
828 def AddNodeToTestSuite(env, node, suite_name, node_name, is_broken=False,
830 global BROKEN_TEST_COUNT
832 # CommandTest can return an empty list when it silently discards a test
836 assert node_name is not None
837 test_name_regex = r'run_.*_(unit)?test.*$'
838 assert re.match(test_name_regex, node_name), (
839 'test %r does not match "run_..._test" naming convention '
840 '(precise regex is %s)' % (node_name, test_name_regex))
842 ValidateTestSuiteNames(suite_name, node_name)
846 if is_broken or is_flaky and env.Bit('disable_flaky_tests'):
847 # Only print if --verbose is specified
848 if not GetOption('brief_comstr'):
849 print '*** BROKEN ', node_name
850 BROKEN_TEST_COUNT += 1
851 env.Alias('broken_tests', node)
852 elif env.ShouldSkipTest(node_name):
853 print '*** SKIPPING ', env.GetPlatformString(), ':', node_name
854 env.Alias('broken_tests', node)
856 env.Alias('all_tests', node)
862 env.ComponentTestOutput(node_name, node)
863 test_name = node_name
865 # This is rather shady, but the tests need a name without dots so they match
867 # TODO(ncbray) node_name should not be optional.
868 test_name = os.path.basename(str(node[0].path))
869 if test_name.endswith('.out'):
870 test_name = test_name[:-4]
871 test_name = test_name.replace('.', '_')
872 SetTestName(node, test_name)
874 pre_base_env.AddMethod(AddNodeToTestSuite)
877 def TestBindsFixedTcpPort(env, node):
878 # This tells Scons that tests that bind a fixed TCP port should not
879 # run concurrently, because they would interfere with each other.
880 # These tests are typically tests for NaCl's GDB debug stub. The
881 # dummy filename used below is an arbitrary token that just has to
882 # match across the tests.
883 SideEffect(env.File('${SCONSTRUCT_DIR}/test_binds_fixed_tcp_port'), node)
885 pre_base_env.AddMethod(TestBindsFixedTcpPort)
888 # Convenient testing aliases
889 # NOTE: work around for scons non-determinism in the following two lines
890 Alias('sel_ldr_sled_tests', [])
892 Alias('small_tests', [])
893 Alias('medium_tests', [])
894 Alias('large_tests', [])
896 Alias('small_tests_irt', [])
897 Alias('medium_tests_irt', [])
898 Alias('large_tests_irt', [])
900 Alias('pepper_browser_tests', [])
901 Alias('chrome_browser_tests', [])
903 Alias('unit_tests', 'small_tests')
904 Alias('smoke_tests', ['small_tests', 'medium_tests'])
906 if pre_base_env.Bit('nacl_glibc'):
907 Alias('memcheck_bot_tests', ['small_tests'])
908 Alias('tsan_bot_tests', ['small_tests'])
910 Alias('memcheck_bot_tests', ['small_tests', 'medium_tests', 'large_tests'])
911 Alias('tsan_bot_tests', [])
919 pre_base_env.AddMethod(Banner)
923 # Define the platforms, and use them to define the path for the
924 # scons-out directory (aka TARGET_ROOT)
926 # Various variables in the scons environment are related to this, e.g.
928 # BUILD_ARCH: (arm, mips, x86)
929 # BUILD_SUBARCH: (32, 64)
931 # This dictionary is used to translate from a platform name to a
932 # (arch, subarch) pair
933 AVAILABLE_PLATFORMS = {
934 'x86-32' : { 'arch' : 'x86' , 'subarch' : '32' },
935 'x86-64' : { 'arch' : 'x86' , 'subarch' : '64' },
936 'mips32' : { 'arch' : 'mips', 'subarch' : '32' },
937 'arm' : { 'arch' : 'arm' , 'subarch' : '32' },
940 # Decode platform into list [ ARCHITECTURE , EXEC_MODE ].
941 def DecodePlatform(platform):
942 if platform in AVAILABLE_PLATFORMS:
943 return AVAILABLE_PLATFORMS[platform]
944 raise UserError('Unrecognized platform: %s' % platform)
947 DeclareBit('build_x86_32', 'Building binaries for the x86-32 architecture',
948 exclusive_groups='build_arch')
949 DeclareBit('build_x86_64', 'Building binaries for the x86-64 architecture',
950 exclusive_groups='build_arch')
951 DeclareBit('build_mips32', 'Building binaries for the MIPS architecture',
952 exclusive_groups='build_arch')
953 DeclareBit('build_arm_arm', 'Building binaries for the ARM architecture',
954 exclusive_groups='build_arch')
955 DeclareBit('target_x86_32', 'Tools being built will process x86-32 binaries',
956 exclusive_groups='target_arch')
957 DeclareBit('target_x86_64', 'Tools being built will process x86-36 binaries',
958 exclusive_groups='target_arch')
959 DeclareBit('target_mips32', 'Tools being built will process MIPS binaries',
960 exclusive_groups='target_arch')
961 DeclareBit('target_arm_arm', 'Tools being built will process ARM binaries',
962 exclusive_groups='target_arch')
964 # Shorthand for either the 32 or 64 bit version of x86.
965 DeclareBit('build_x86', 'Building binaries for the x86 architecture')
966 DeclareBit('target_x86', 'Tools being built will process x86 binaries')
968 DeclareBit('build_arm', 'Building binaries for the arm architecture')
969 DeclareBit('target_arm', 'Tools being built will process arm binaries')
972 def MakeArchSpecificEnv(platform=None):
973 env = pre_base_env.Clone()
975 platform = GetTargetPlatform()
976 info = DecodePlatform(platform)
978 env.Replace(BUILD_FULLARCH=platform)
979 env.Replace(BUILD_ARCHITECTURE=info['arch'])
980 env.Replace(BUILD_SUBARCH=info['subarch'])
981 env.Replace(TARGET_FULLARCH=platform)
982 env.Replace(TARGET_ARCHITECTURE=info['arch'])
983 env.Replace(TARGET_SUBARCH=info['subarch'])
985 # Example: PlatformBit('build', 'x86-32') -> build_x86_32
986 def PlatformBit(prefix, platform):
987 return "%s_%s" % (prefix, platform.replace('-', '_'))
989 env.SetBits(PlatformBit('build', platform))
990 env.SetBits(PlatformBit('target', platform))
992 if env.Bit('build_x86_32') or env.Bit('build_x86_64'):
993 env.SetBits('build_x86')
994 if env.Bit('build_arm_arm'):
995 env.SetBits('build_arm')
997 if env.Bit('target_x86_32') or env.Bit('target_x86_64'):
998 env.SetBits('target_x86')
999 if env.Bit('target_arm_arm'):
1000 env.SetBits('target_arm')
1002 env.Replace(BUILD_ISA_NAME=platform)
1004 if env.Bit('target_mips32'):
1005 # This is a silent default on MIPS.
1006 env.SetBits('bitcode')
1008 # Determine where the object files go
1009 env.Replace(BUILD_TARGET_NAME=platform)
1010 # This may be changed later; see target_variant_map, below.
1011 env.Replace(TARGET_VARIANT='')
1012 env.Replace(TARGET_ROOT=
1013 '${DESTINATION_ROOT}/${BUILD_TYPE}-${BUILD_TARGET_NAME}${TARGET_VARIANT}')
1018 pre_base_env.AddMethod(lambda self: ARGUMENTS.get('running_on_valgrind'),
1019 'IsRunningUnderValgrind')
1021 DeclareBit('with_leakcheck', 'Running under Valgrind leak checker')
1023 def RunningUnderLeakCheck():
1024 run_under = ARGUMENTS.get('run_under')
1026 extra_args = ARGUMENTS.get('run_under_extra_args')
1028 run_under += extra_args
1029 if run_under.find('leak-check=full') > 0:
1033 if RunningUnderLeakCheck():
1034 pre_base_env.SetBits('with_leakcheck')
1037 def HasSuffix(item, suffix):
1038 if isinstance(item, str):
1039 return item.endswith(suffix)
1040 elif hasattr(item, '__getitem__'):
1041 return HasSuffix(item[0], suffix)
1043 return item.path.endswith(suffix)
1046 def StripSuffix(string, suffix):
1047 assert string.endswith(suffix)
1048 return string[:-len(suffix)]
1051 def DualLibrary(env, lib_name, *args, **kwargs):
1052 """Builder to build both .a and _shared.a library in one step.
1055 env: Environment in which we were called.
1056 lib_name: Library name.
1057 args: Positional arguments.
1058 kwargs: Keyword arguments.
1060 static_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.os')]
1061 shared_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.o')]
1062 # Built static library as ususal.
1063 env.ComponentLibrary(lib_name, static_objs, **kwargs)
1064 # For coverage bots, we only want one object file since two versions would
1065 # write conflicting information to the same .gdca/.gdna files.
1066 if env.Bit('coverage_enabled'): return
1067 # Build a static library using -fPIC for the .o's.
1068 if env.Bit('linux'):
1069 env_shared = env.Clone(OBJSUFFIX='.os')
1070 env_shared.Append(CCFLAGS=['-fPIC'])
1071 # -fPIE overrides -fPIC, and shared libraries should not be linked
1073 env_shared.FilterOut(CCFLAGS=['-fPIE'])
1074 env_shared.ComponentLibrary(lib_name + '_shared', shared_objs, **kwargs)
1075 # for arm trusted we usually build -static
1076 env_shared.FilterOut(LINKFLAGS=['-static'])
1078 def DualObject(env, *args, **kwargs):
1079 """Builder to build both .o and .os in one step.
1082 env: Environment in which we were called.
1083 args: Positional arguments.
1084 kwargs: Keyword arguments.
1086 # Built static library as ususal.
1087 ret = env.ComponentObject(*args, **kwargs)
1088 # For coverage bots, we only want one object file since two versions would
1089 # write conflicting information to the same .gdca/.gdna files.
1090 if env.Bit('coverage_enabled'): return ret
1091 # Build a static library using -fPIC for the .o's.
1092 if env.Bit('linux'):
1093 env_shared = env.Clone(OBJSUFFIX='.os')
1094 env_shared.Append(CCFLAGS=['-fPIC'])
1095 ret += env_shared.ComponentObject(*args, **kwargs)
1099 def AddDualLibrary(env):
1100 env.AddMethod(DualLibrary)
1101 env.AddMethod(DualObject)
1102 # For coverage bots we only build one set of objects and we always set
1103 # '-fPIC' so we do not need a "special" library.
1104 if env.Bit('coverage_enabled'):
1105 env['SHARED_LIBS_SPECIAL'] = False
1107 env['SHARED_LIBS_SPECIAL'] = env.Bit('linux')
1110 # In prebuild mode we ignore the dependencies so that stuff does
1111 # NOT get build again
1112 # Optionally ignore the build process.
1113 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
1114 pre_base_env.SetBitFromOption('prebuilt', False)
1117 # HELPERS FOR TEST INVOLVING TRUSTED AND UNTRUSTED ENV
1118 def GetEmulator(env):
1119 emulator = ARGUMENTS.get('force_emulator')
1120 if emulator is None and 'TRUSTED_ENV' in env:
1121 emulator = env['TRUSTED_ENV'].get('EMULATOR')
1124 pre_base_env.AddMethod(GetEmulator)
1126 def UsingEmulator(env):
1127 return bool(env.GetEmulator())
1129 pre_base_env.AddMethod(UsingEmulator)
1132 def GetValidator(env, validator):
1133 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1134 if 'TRUSTED_ENV' not in env:
1137 if validator is None:
1138 if env.Bit('build_arm'):
1139 validator = 'arm-ncval-core'
1140 elif env.Bit('build_mips32'):
1141 validator = 'mips-ncval-core'
1143 if env.Bit('validator_ragel'):
1144 validator = 'ncval_new'
1148 trusted_env = env['TRUSTED_ENV']
1149 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}%s${PROGSUFFIX}' %
1152 pre_base_env.AddMethod(GetValidator)
1155 # Perform os.path.abspath rooted at the directory SConstruct resides in.
1156 def SConstructAbsPath(env, path):
1157 return os.path.normpath(os.path.join(env['MAIN_DIR'], path))
1159 pre_base_env.AddMethod(SConstructAbsPath)
1163 sel_ldr = ARGUMENTS.get('force_sel_ldr')
1165 return env.File(env.SConstructAbsPath(sel_ldr))
1167 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1168 if 'TRUSTED_ENV' not in env:
1171 trusted_env = env['TRUSTED_ENV']
1172 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}sel_ldr${PROGSUFFIX}')
1174 pre_base_env.AddMethod(GetSelLdr)
1177 def GetSelLdrSeccomp(env):
1178 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1179 if 'TRUSTED_ENV' not in env:
1182 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1185 trusted_env = env['TRUSTED_ENV']
1186 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}'
1187 'sel_ldr_seccomp${PROGSUFFIX}')
1189 pre_base_env.AddMethod(GetSelLdrSeccomp)
1192 def SupportsSeccompBpfSandbox(env):
1193 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1196 # The gcov runtime does some extra calls (such as 'access') that
1197 # are not permitted by the policy.
1198 if env.Bit('coverage_enabled'):
1201 # This is a lame detection if seccomp bpf filters are supported by the kernel.
1202 # We suppose that any Linux kernel v3.2+ supports it, but it is only true
1203 # for Ubuntu kernels. Seccomp BPF filters reached the mainline at 3.5,
1204 # so this check will be wrong on some relatively old non-Ubuntu Linux distros.
1205 kernel_version = map(int, platform.release().split('.', 2)[:2])
1206 return kernel_version >= [3, 2]
1208 pre_base_env.AddMethod(SupportsSeccompBpfSandbox)
1211 def GetBootstrap(env):
1212 if 'TRUSTED_ENV' in env:
1213 trusted_env = env['TRUSTED_ENV']
1214 if trusted_env.Bit('linux'):
1215 template_digits = 'X' * 16
1216 return (trusted_env.File('${STAGING_DIR}/nacl_helper_bootstrap'),
1217 ['--r_debug=0x' + template_digits,
1218 '--reserved_at_zero=0x' + template_digits])
1221 pre_base_env.AddMethod(GetBootstrap)
1223 def AddBootstrap(env, executable, args):
1224 bootstrap, bootstrap_args = env.GetBootstrap()
1225 if bootstrap is None:
1226 return [executable] + args
1228 return [bootstrap, executable] + bootstrap_args + args
1230 pre_base_env.AddMethod(AddBootstrap)
1233 def GetIrtNexe(env, chrome_irt=False):
1234 image = ARGUMENTS.get('force_irt')
1236 return env.SConstructAbsPath(image)
1239 return nacl_irt_env.File('${STAGING_DIR}/irt.nexe')
1241 return nacl_irt_env.File('${STAGING_DIR}/irt_core.nexe')
1243 pre_base_env.AddMethod(GetIrtNexe)
1245 def ApplyTLSEdit(env, nexe_name, raw_nexe):
1246 # If the environment was built elsewhere, we do not need to apply tls_edit
1247 # since it only needs to be done during building.
1248 if env.Bit('built_elsewhere'):
1249 return env.File(nexe_name)
1251 tls_edit_exe = env['BUILD_ENV'].File('${STAGING_DIR}/tls_edit${PROGSUFFIX}')
1254 [tls_edit_exe, raw_nexe],
1255 '${SOURCES[0]} --verbose ${SOURCES[1:]} ${TARGET}')
1257 pre_base_env.AddMethod(ApplyTLSEdit)
1259 def CommandValidatorTestNacl(env, name, image,
1260 validator_flags=None,
1264 validator = env.GetValidator(validator)
1265 if validator is None:
1266 print 'WARNING: no validator found. Skipping test %s' % name
1269 if validator_flags is None:
1270 validator_flags = []
1272 if env.Bit('pnacl_generate_pexe'):
1275 command = [validator] + validator_flags + [image]
1276 return env.CommandTest(name, command, size, **extra)
1278 pre_base_env.AddMethod(CommandValidatorTestNacl)
1281 def ExtractPublishedFiles(env, target_name):
1282 run_files = ['$STAGING_DIR/' + os.path.basename(published_file.path)
1283 for published_file in env.GetPublished(target_name, 'run')]
1284 nexe = '$STAGING_DIR/%s${PROGSUFFIX}' % target_name
1285 return [env.File(file) for file in run_files + [nexe]]
1287 pre_base_env.AddMethod(ExtractPublishedFiles)
1290 # Only include the chrome side of the build if present.
1291 if os.path.exists(pre_base_env.File(
1292 '#/../ppapi/native_client/chrome_main.scons').abspath):
1293 SConscript('#/../ppapi/native_client/chrome_main.scons',
1294 exports=['pre_base_env'])
1295 enable_chrome = True
1297 def AddChromeFilesFromGroup(env, file_group):
1299 pre_base_env.AddMethod(AddChromeFilesFromGroup)
1300 enable_chrome = False
1301 DeclareBit('enable_chrome_side',
1302 'Is the chrome side present.')
1303 pre_base_env.SetBitFromOption('enable_chrome_side', enable_chrome)
1305 def ProgramNameForNmf(env, basename):
1306 """ Create an architecture-specific filename that can be used in an NMF URL.
1308 if env.Bit('pnacl_generate_pexe'):
1311 return '%s_%s' % (basename, env.get('TARGET_FULLARCH'))
1313 pre_base_env.AddMethod(ProgramNameForNmf)
1316 def SelUniversalTest(env,
1320 sel_universal_flags=None,
1322 # The dynamic linker's ability to receive arguments over IPC at
1323 # startup currently requires it to reject the plugin's first
1324 # connection, but this interferes with the sel_universal-based
1325 # testing because sel_universal does not retry the connection.
1326 # TODO(mseaborn): Fix by retrying the connection or by adding an
1327 # option to ld.so to disable its argv-over-IPC feature.
1328 if env.Bit('nacl_glibc') and not env.Bit('nacl_static_link'):
1331 # TODO(petarj): Sel_universal hangs on qemu-mips. Enable when fixed.
1332 if env.Bit('target_mips32') and env.UsingEmulator():
1335 if sel_universal_flags is None:
1336 sel_universal_flags = []
1338 # When run under qemu, sel_universal must sneak in qemu to the execv
1339 # call that spawns sel_ldr.
1340 if env.UsingEmulator():
1341 sel_universal_flags.append('--command_prefix')
1342 sel_universal_flags.append(env.GetEmulator())
1344 if 'TRUSTED_ENV' not in env:
1346 sel_universal = env['TRUSTED_ENV'].File(
1347 '${STAGING_DIR}/${PROGPREFIX}sel_universal${PROGSUFFIX}')
1349 # Point to sel_ldr using an environment variable.
1350 sel_ldr = env.GetSelLdr()
1352 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1354 kwargs.setdefault('osenv', []).append('NACL_SEL_LDR=' + sel_ldr.abspath)
1355 bootstrap, _ = env.GetBootstrap()
1356 if bootstrap is not None:
1357 kwargs['osenv'].append('NACL_SEL_LDR_BOOTSTRAP=%s' % bootstrap.abspath)
1359 node = CommandSelLdrTestNacl(env,
1363 loader=sel_universal,
1364 sel_ldr_flags=sel_universal_flags,
1365 skip_bootstrap=True,
1367 if not env.Bit('built_elsewhere'):
1368 env.Depends(node, sel_ldr)
1369 if bootstrap is not None:
1370 env.Depends(node, bootstrap)
1373 pre_base_env.AddMethod(SelUniversalTest)
1376 def MakeNaClLogOption(env, target):
1377 """ Make up a filename related to the [target], for use with NACLLOG.
1378 The file should end up in the build directory (scons-out/...).
1380 # NOTE: to log to the source directory use file.srcnode().abspath instead.
1381 # See http://www.scons.org/wiki/File%28%29
1382 return env.File(target + '.nacllog').abspath
1384 pre_base_env.AddMethod(MakeNaClLogOption)
1386 def MakeVerboseExtraOptions(env, target, log_verbosity, extra):
1387 """ Generates **extra options that will give access to service runtime logs,
1388 at a given log_verbosity. Slips the options into the given extra dict. """
1389 log_file = env.MakeNaClLogOption(target)
1390 extra['log_file'] = log_file
1391 extra_env = ['NACLLOG=%s' % log_file,
1392 'NACLVERBOSITY=%d' % log_verbosity]
1393 extra['osenv'] = extra.get('osenv', []) + extra_env
1395 pre_base_env.AddMethod(MakeVerboseExtraOptions)
1397 def ShouldUseVerboseOptions(env, extra):
1398 """ Heuristic for setting up Verbose NACLLOG options. """
1399 return ('process_output_single' in extra or
1400 'log_golden' in extra)
1402 pre_base_env.AddMethod(ShouldUseVerboseOptions)
1405 DeclareBit('tests_use_irt', 'Non-browser tests also load the IRT image', False)
1407 # Bit to be set by individual test/nacl.scons files that need to opt out.
1408 DeclareBit('nonstable_bitcode', 'Tests use non-stable bitcode features', False)
1411 def GetFinalizedPexe(env, pexe):
1412 """ Prep and finalize the ABI for a given pexe if needed.
1414 if not env.Bit('pnacl_generate_pexe') or env.Bit('nonstable_bitcode'):
1417 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1418 # file instead. There are currently some canned nexe tests in build.scons.
1419 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1422 # Otherwise, finalize during the build step, since there is no finalize tool
1423 # that can run on triggered bots such as the ARM HW bots.
1424 pexe_name = pexe.abspath
1425 final_name = StripSuffix(pexe_name, '.nonfinal.pexe') + '.final.pexe'
1426 # Make sure the pexe doesn't get removed by the fake builders when
1429 node = env.Command(target=final_name, source=[pexe_name],
1430 action=[Action('${PNACLFINALIZECOM}',
1431 '${PNACLFINALIZECOMSTR}')])
1432 assert len(node) == 1, node
1436 # Translate the given pexe.
1437 def GetTranslatedNexe(env, pexe):
1438 # First finalize the pexe.
1439 pexe = GetFinalizedPexe(env, pexe)
1441 # Then check if we need to translate.
1442 # Check if we started with a pexe, so there is actually a translation step.
1443 if not env.Bit('pnacl_generate_pexe'):
1446 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1447 # file instead. There are currently some canned nexe tests in build.scons.
1448 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1451 # Often there is a build step (do_not_run_tests=1) and a test step
1452 # (which is run with -j1). Normally we want to translate in the build step
1453 # so we can translate in parallel. However when we do sandboxed translation
1454 # on arm hw, we do the build step on x86 and translation on arm, so we have
1455 # to force the translation to be done in the test step. Hence,
1456 # we check the bit 'translate_in_build_step' / check if we are
1458 if not env.Bit('translate_in_build_step') and env.Bit('do_not_run_tests'):
1461 pexe_name = pexe.abspath
1462 # Tidy up the suffix (remove the .final.pexe or .nonfinal.pexe),
1463 # depending on whether or not the pexe was finalized.
1464 suffix_to_strip = '.final.pexe'
1465 if not pexe_name.endswith(suffix_to_strip):
1466 suffix_to_strip = '.nonfinal.pexe'
1467 nexe_name = StripSuffix(pexe_name, suffix_to_strip) + '.nexe'
1468 # Make sure the pexe doesn't get removed by the fake builders when
1471 if env.Bit('nonstable_bitcode'):
1472 env.Append(TRANSLATEFLAGS=['--allow-llvm-bitcode-input'])
1473 node = env.Command(target=nexe_name, source=[pexe_name],
1474 action=[Action('${TRANSLATECOM}', '${TRANSLATECOMSTR}')])
1475 assert len(node) == 1, node
1478 pre_base_env.AddMethod(GetTranslatedNexe)
1481 def CommandTestFileDumpCheck(env,
1486 """Create a test that disassembles a binary (|target|) and checks for
1487 patterns in the |check_file|. Disassembly is done using |objdump_flags|.
1490 # Do not try to run OBJDUMP if 'built_elsewhere', since that *might* mean
1491 # that a toolchain is not even present. E.g., the arm hw buildbots do
1492 # not have the pnacl toolchain. We should be able to look for the host
1493 # ARM objdump though... a TODO(jvoung) for when there is time.
1494 if env.Bit('built_elsewhere'):
1496 target = env.GetTranslatedNexe(target)
1497 return env.CommandTestFileCheck(name,
1498 ['${OBJDUMP}', objdump_flags, target],
1501 pre_base_env.AddMethod(CommandTestFileDumpCheck)
1504 def CommandTestFileCheck(env, name, cmd, check_file):
1505 """Create a test that runs a |cmd| (array of strings),
1506 which is expected to print to stdout. The results
1507 of stdout will then be piped to the file_check.py tool which
1508 will search for the regexes specified in |check_file|. """
1510 return env.CommandTest(name,
1512 env.File('${SCONSTRUCT_DIR}/tools/file_check.py'),
1514 # don't run ${PYTHON} under the emulator.
1515 direct_emulation=False)
1517 pre_base_env.AddMethod(CommandTestFileCheck)
1519 def CommandSelLdrTestNacl(env, name, nexe,
1525 # True for *.nexe statically linked with glibc
1527 skip_bootstrap=False,
1528 wrapper_program_prefix=None,
1529 # e.g., [ 'python', 'time_check.py', '--' ]
1531 # Disable all sel_ldr tests for windows under coverage.
1532 # Currently several .S files block sel_ldr from being instrumented.
1533 # See http://code.google.com/p/nativeclient/issues/detail?id=831
1534 if ('TRUSTED_ENV' in env and
1535 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1536 env['TRUSTED_ENV'].Bit('windows')):
1539 # The nexe might be a pexe that needs finalization, and translation.
1540 nexe = env.GetTranslatedNexe(nexe)
1543 if args is not None:
1546 if env.Bit('pnacl_unsandboxed'):
1547 # Run unsandboxed executable directly, without sel_ldr.
1548 return env.CommandTest(name, command, size, **extra)
1551 loader = env.GetSelLdr()
1553 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1556 # Avoid problems with [] as default arguments
1557 if sel_ldr_flags is None:
1560 # Avoid modifying original list
1561 sel_ldr_flags = list(sel_ldr_flags)
1563 # Disable the validator if running a GLibC test under Valgrind.
1564 # http://code.google.com/p/nativeclient/issues/detail?id=1799
1565 if env.IsRunningUnderValgrind() and env.Bit('nacl_glibc'):
1566 sel_ldr_flags += ['-cc']
1567 # https://code.google.com/p/nativeclient/issues/detail?id=3158
1568 # We don't currently have valgrind.so for LD_PRELOAD to use. That .so
1569 # is not used for newlib.
1570 # TODO(sehr): add valgrind.so built for NaCl.
1573 # Skip platform qualification checks on configurations with known issues.
1574 if env.GetEmulator() or env.IsRunningUnderValgrind():
1575 sel_ldr_flags += ['-Q']
1577 # Skip validation if we are using the x86-64 zero-based sandbox.
1578 # TODO(arbenson): remove this once the validator supports the x86-64
1579 # zero-based sandbox model.
1580 if env.Bit('x86_64_zero_based_sandbox'):
1581 sel_ldr_flags += ['-c']
1583 # The glibc modifications only make sense for nacl_env tests.
1584 # But this function gets used by some base_env (i.e. src/trusted/...)
1585 # tests too. Don't add the --nacl_glibc changes to the command
1586 # line for those cases.
1587 if env.Bit('nacl_glibc') and env['NACL_BUILD_FAMILY'] != 'TRUSTED':
1588 if not glibc_static and not env.Bit('nacl_static_link'):
1589 command = ['${NACL_SDK_LIB}/runnable-ld.so',
1590 # Locally-built shared libraries come from ${LIB_DIR}
1591 # while toolchain-provided ones come from ${NACL_SDK_LIB}.
1592 '--library-path', '${LIB_DIR}:${NACL_SDK_LIB}'] + command
1593 # Enable file access.
1594 sel_ldr_flags += ['-a']
1596 # Turn off sandbox for mac so coverage files can be written out.
1597 if ('TRUSTED_ENV' in env and
1598 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1599 env.Bit('host_mac') and
1600 '-a' not in sel_ldr_flags):
1601 sel_ldr_flags += ['-a']
1603 if env.Bit('tests_use_irt'):
1604 sel_ldr_flags += ['-B', nacl_env.GetIrtNexe()]
1607 loader_cmd = [loader]
1609 loader_cmd = env.AddBootstrap(loader, [])
1611 command = loader_cmd + sel_ldr_flags + ['--'] + command
1613 if env.Bit('host_linux'):
1614 extra['using_nacl_signal_handler'] = True
1616 if env.ShouldUseVerboseOptions(extra):
1617 env.MakeVerboseExtraOptions(name, log_verbosity, extra)
1619 node = env.CommandTest(name, command, size, posix_path=True,
1620 wrapper_program_prefix=wrapper_program_prefix, **extra)
1621 if env.Bit('tests_use_irt'):
1622 env.Alias('irt_tests', node)
1625 pre_base_env.AddMethod(CommandSelLdrTestNacl)
1628 TEST_EXTRA_ARGS = ['stdin', 'log_file',
1629 'stdout_golden', 'stderr_golden', 'log_golden',
1630 'filter_regex', 'filter_inverse', 'filter_group_only',
1631 'osenv', 'arch', 'subarch', 'exit_status', 'track_cmdtime',
1632 'num_runs', 'process_output_single',
1633 'process_output_combined', 'using_nacl_signal_handler',
1634 'declares_exit_status', 'time_warning', 'time_error']
1636 TEST_TIME_THRESHOLD = {
1643 # Valgrind handles SIGSEGV in a way our testing tools do not expect.
1644 UNSUPPORTED_VALGRIND_EXIT_STATUS = ['trusted_sigabrt',
1645 'untrusted_sigill' ,
1646 'untrusted_segfault',
1647 'untrusted_sigsegv_or_equivalent',
1649 'trusted_sigsegv_or_equivalent']
1652 def GetPerfEnvDescription(env):
1653 """ Return a string describing architecture, library, etc. options that may
1656 NOTE: If any of these labels are changed, be sure to update the graph
1657 labels used in tools/nacl_perf_expectations/nacl_perf_expectations.json,
1658 after a few data-points have been collected. """
1659 description_list = [env['TARGET_FULLARCH']]
1660 # Using a list to keep the order consistent.
1661 bit_to_description = [ ('bitcode', ('pnacl', 'nnacl')),
1662 ('translate_fast', ('fast', '')),
1663 ('nacl_glibc', ('glibc', 'newlib')),
1664 ('nacl_static_link', ('static', 'dynamic')),
1666 for (bit, (descr_yes, descr_no)) in bit_to_description:
1668 additional = descr_yes
1670 additional = descr_no
1672 description_list.append(additional)
1673 return '_'.join(description_list)
1675 pre_base_env.AddMethod(GetPerfEnvDescription)
1680 def GetTestName(target):
1681 key = str(target.path)
1682 return TEST_NAME_MAP.get(key, key)
1684 pre_base_env['GetTestName'] = GetTestName
1687 def SetTestName(node, name):
1688 for target in Flatten(node):
1689 TEST_NAME_MAP[str(target.path)] = name
1692 def ApplyTestWrapperCommand(command_args, extra_deps):
1693 new_args = ARGUMENTS['test_wrapper'].split()
1694 for input_file in extra_deps:
1695 new_args.extend(['-F', input_file])
1696 for arg in command_args:
1697 if isinstance(arg, str):
1698 new_args.extend(['-a', arg])
1700 new_args.extend(['-f', arg])
1704 def CommandTest(env, name, command, size='small', direct_emulation=True,
1705 extra_deps=[], posix_path=False, capture_output=True,
1706 capture_stderr=True, wrapper_program_prefix=None,
1707 scale_timeout=None, **extra):
1708 if not name.endswith('.out') or name.startswith('$'):
1709 raise Exception('ERROR: bad test filename for test output %r' % name)
1711 if env.IsRunningUnderValgrind():
1713 elif env.Bit('asan'):
1714 skip = 'AddressSanitizer'
1717 # Valgrind tends to break crash tests by changing the exit status.
1718 # So far, tests using declares_exit_status are crash tests. If this
1719 # changes, we will have to find a way to make declares_exit_status
1720 # work with Valgrind.
1721 if (skip is not None and
1722 (extra.get('exit_status') in UNSUPPORTED_VALGRIND_EXIT_STATUS or
1723 bool(int(extra.get('declares_exit_status', 0))))):
1724 print 'Skipping death test "%s" under %s' % (name, skip)
1728 extra.setdefault('osenv', [])
1729 # Ensure that 'osenv' is a list.
1730 if isinstance(extra['osenv'], str):
1731 extra['osenv'] = [extra['osenv']]
1732 # ASan normally intercepts SIGSEGV and disables our SIGSEGV signal
1733 # handler, which interferes with various NaCl tests, including the
1734 # platform qualification test built into sel_ldr. We fix this by
1735 # telling ASan not to mess with SIGSEGV.
1736 asan_options = ['handle_segv=0']
1737 if env.Bit('host_mac') and int(platform.mac_ver()[0].split('.')[1]) < 7:
1738 # MacOS 10.6 has a bug in the libsandbox system library where it
1739 # makes a memcmp call that reads off the end of a malloc'd block.
1740 # The bug appears to be harmless, but trips an ASan report. So
1741 # tell ASan to suppress memcmp checks.
1742 asan_options.append('strict_memcmp=0')
1743 # Note that the ASan runtime doesn't use : specifically as a separator.
1744 # It actually just looks for "foo=" anywhere in the string with strstr,
1745 # so any separator will do. The most obvious choices, ' ', ',', and ';'
1746 # all cause command_tester.py to split things up and get confused.
1747 extra['osenv'].append('ASAN_OPTIONS=' + ':'.join(asan_options))
1749 name = '${TARGET_ROOT}/test_results/' + name
1750 # NOTE: using the long version of 'name' helps distinguish opt vs dbg
1751 max_time = TEST_TIME_THRESHOLD[size]
1752 if 'scale_timeout' in ARGUMENTS:
1753 max_time = max_time * int(ARGUMENTS['scale_timeout'])
1755 max_time = max_time * scale_timeout
1757 if env.Bit('nacl_glibc'):
1758 suite = 'nacl_glibc'
1760 suite = 'nacl_newlib'
1761 if env.Bit('bitcode'):
1764 script_flags = ['--name', '%s.${GetTestName(TARGET)}' % suite,
1765 '--time_warning', str(max_time),
1766 '--time_error', str(10 * max_time),
1769 run_under = ARGUMENTS.get('run_under')
1771 run_under_extra_args = ARGUMENTS.get('run_under_extra_args')
1772 if run_under_extra_args:
1773 run_under = run_under + ',' + run_under_extra_args
1774 script_flags.append('--run_under')
1775 script_flags.append(run_under)
1777 emulator = env.GetEmulator()
1778 if emulator and direct_emulation:
1779 command = [emulator] + command
1781 # test wrapper should go outside of emulators like qemu, since the
1782 # test wrapper code is not emulated.
1783 if wrapper_program_prefix is not None:
1784 command = wrapper_program_prefix + command
1786 script_flags.append('--perf_env_description')
1787 script_flags.append(env.GetPerfEnvDescription())
1789 # Add architecture info.
1790 extra['arch'] = env['BUILD_ARCHITECTURE']
1791 extra['subarch'] = env['BUILD_SUBARCH']
1793 for flag_name, flag_value in extra.iteritems():
1794 assert flag_name in TEST_EXTRA_ARGS, repr(flag_name)
1795 if isinstance(flag_value, list):
1796 # Options to command_tester.py which are actually lists must not be
1797 # separated by whitespace. This stringifies the lists with a separator
1798 # char to satisfy command_tester.
1799 flag_value = command_tester.StringifyList(flag_value)
1800 # do not add --flag + |flag_name| |flag_value| if
1801 # |flag_value| is false (empty).
1803 script_flags.append('--' + flag_name)
1804 # Make sure flag values are strings (or SCons objects) when building
1805 # up the command. Right now, this only means convert ints to strings.
1806 if isinstance(flag_value, int):
1807 flag_value = str(flag_value)
1808 script_flags.append(flag_value)
1811 if not capture_output:
1812 script_flags.extend(['--capture_output', '0'])
1813 if not capture_stderr:
1814 script_flags.extend(['--capture_stderr', '0'])
1816 # Set command_tester.py's output filename. We skip this when using
1817 # test_wrapper because the run_test_via_ssh.py wrapper does not have
1818 # the ability to copy result files back from the remote host.
1819 if 'test_wrapper' not in ARGUMENTS:
1820 script_flags.extend(['--report', name])
1822 test_script = env.File('${SCONSTRUCT_DIR}/tools/command_tester.py')
1823 extra_deps = extra_deps + [env.File('${SCONSTRUCT_DIR}/tools/test_lib.py')]
1824 command = ['${PYTHON}', test_script] + script_flags + command
1825 if 'test_wrapper' in ARGUMENTS:
1826 command = ApplyTestWrapperCommand(command, extra_deps)
1827 return env.AutoDepsCommand(name, command,
1828 extra_deps=extra_deps, posix_path=posix_path,
1829 disabled=env.Bit('do_not_run_tests'))
1831 pre_base_env.AddMethod(CommandTest)
1834 def FileSizeTest(env, name, envFile, max_size=None):
1835 """FileSizeTest() returns a scons node like the other XYZTest generators.
1836 It logs the file size of envFile in a perf-buildbot-recognizable format.
1837 Optionally, it can cause a test failure if the file is larger than max_size.
1839 def doSizeCheck(target, source, env):
1840 filepath = source[0].abspath
1841 actual_size = os.stat(filepath).st_size
1842 command_tester.LogPerfResult(name,
1843 env.GetPerfEnvDescription(),
1844 '%.3f' % (actual_size / 1024.0),
1846 # Also get zipped size.
1847 nexe_file = open(filepath, 'rb')
1848 zipped_size = len(zlib.compress(nexe_file.read()))
1850 command_tester.LogPerfResult(name,
1851 'ZIPPED_' + env.GetPerfEnvDescription(),
1852 '%.3f' % (zipped_size / 1024.0),
1854 # Finally, do the size check.
1855 if max_size is not None and actual_size > max_size:
1856 # NOTE: this exception only triggers a failure for this particular test,
1857 # just like any other test failure.
1858 raise Exception("File %s larger than expected: expected up to %i, got %i"
1859 % (filepath, max_size, actual_size))
1860 # If 'built_elsewhere', the file should should have already been built.
1861 # Do not try to built it and/or its pieces.
1862 if env.Bit('built_elsewhere'):
1863 env.Ignore(name, envFile)
1864 return env.Command(name, envFile, doSizeCheck)
1866 pre_base_env.AddMethod(FileSizeTest)
1868 def StripExecutable(env, name, exe):
1869 """StripExecutable returns a node representing the stripped version of |exe|.
1870 The stripped version will be given the basename |name|.
1871 NOTE: for now this only works with the untrusted toolchain.
1872 STRIP does not appear to be a first-class citizen in SCons and
1873 STRIP has only been set to point at the untrusted toolchain.
1878 action=[Action('${STRIPCOM} ${SOURCES} -o ${TARGET}', '${STRIPCOMSTR}')])
1880 pre_base_env.AddMethod(StripExecutable)
1883 # TODO(ncbray): pretty up the log output when running this builder.
1884 def DisabledCommand(target, source, env):
1887 pre_base_env['BUILDERS']['DisabledCommand'] = Builder(action=DisabledCommand)
1890 def AutoDepsCommand(env, name, command, extra_deps=[], posix_path=False,
1892 """AutoDepsCommand() takes a command as an array of arguments. Each
1893 argument may either be:
1896 * a Scons file object, e.g. one created with env.File() or as the
1897 result of another build target.
1899 In the second case, the file is automatically declared as a
1900 dependency of this command.
1902 command = list(command)
1904 for index, arg in enumerate(command):
1905 if not isinstance(arg, str):
1906 if len(Flatten(arg)) != 1:
1907 # Do not allow this, because it would cause "deps" to get out
1908 # of sync with the indexes in "command".
1909 # See http://code.google.com/p/nativeclient/issues/detail?id=1086
1910 raise AssertionError('Argument to AutoDepsCommand() actually contains '
1911 'multiple (or zero) arguments: %r' % arg)
1913 command[index] = '${SOURCES[%d].posix}' % len(deps)
1915 command[index] = '${SOURCES[%d].abspath}' % len(deps)
1918 # If built_elsewhere, build commands are replaced by no-ops, so make sure
1919 # the targets don't get removed first
1920 if env.Bit('built_elsewhere'):
1922 env.Depends(name, extra_deps)
1925 return env.DisabledCommand(name, deps)
1927 return env.Command(name, deps, ' '.join(command))
1930 pre_base_env.AddMethod(AutoDepsCommand)
1933 def GetPrintableCommandName(cmd):
1934 """Look at the first few elements of cmd to derive a suitable command name."""
1935 cmd_tokens = cmd.split()
1936 if "python" in cmd_tokens[0] and len(cmd_tokens) >= 2:
1937 cmd_name = cmd_tokens[1]
1939 cmd_name = cmd_tokens[0].split('(')[0]
1941 # undo some pretty printing damage done by hammer
1942 cmd_name = cmd_name.replace('________','')
1943 # use file name part of a path
1944 return cmd_name.split('/')[-1]
1947 def GetPrintableEnvironmentName(env):
1948 # use file name part of a obj root path as env name
1949 return env.subst('${TARGET_ROOT}').split('/')[-1]
1951 pre_base_env.AddMethod(GetPrintableEnvironmentName)
1954 def CustomCommandPrinter(cmd, targets, source, env):
1955 # Abuse the print hook to count the commands that are executed
1956 if env.Bit('target_stats'):
1957 cmd_name = GetPrintableCommandName(cmd)
1958 env_name = env.GetPrintableEnvironmentName()
1959 CMD_COUNTER[cmd_name] = CMD_COUNTER.get(cmd_name, 0) + 1
1960 ENV_COUNTER[env_name] = ENV_COUNTER.get(env_name, 0) + 1
1963 # Our pretty printer
1965 cmd_name = GetPrintableCommandName(cmd)
1966 env_name = env.GetPrintableEnvironmentName()
1967 sys.stdout.write('[%s] [%s] %s\n' % (cmd_name, env_name,
1968 targets[0].get_path()))
1970 # The SCons default (copied from print_cmd_line in Action.py)
1971 sys.stdout.write(cmd + u'\n')
1973 pre_base_env.Append(PRINT_CMD_LINE_FUNC=CustomCommandPrinter)
1976 def GetAbsDirArg(env, argument, target):
1977 """Fetch the named command-line argument and turn it into an absolute
1978 directory name. If the argument is missing, raise a UserError saying
1979 that the given target requires that argument be given."""
1980 dir = ARGUMENTS.get(argument)
1982 raise UserError('%s must be set when invoking %s' % (argument, target))
1983 return os.path.join(env.Dir('$MAIN_DIR').abspath, dir)
1985 pre_base_env.AddMethod(GetAbsDirArg)
1988 pre_base_env.Append(
1990 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
1991 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
1995 def MakeGTestEnv(env):
1996 # Create an environment to run unit tests using Gtest.
1997 gtest_env = env.Clone()
1999 # This became necessary for the arm cross TC v4.6
2000 # but probable applies to all new gcc TCs
2001 gtest_env.Append(LINKFLAGS=['-pthread'])
2003 # Define compile-time flag that communicates that we are compiling in the test
2004 # environment (rather than for the TCB).
2005 if gtest_env['NACL_BUILD_FAMILY'] == 'TRUSTED':
2006 gtest_env.Append(CCFLAGS=['-DNACL_TRUSTED_BUT_NOT_TCB'])
2008 # This is necessary for unittest_main.c which includes gtest/gtest.h
2009 # The problem is that gtest.h includes other files expecting the
2010 # include path to be set.
2011 gtest_env.Prepend(CPPPATH=['${SOURCE_ROOT}/testing/gtest/include'])
2013 # gtest does not compile with our stringent settings.
2014 if gtest_env.Bit('linux') or gtest_env.Bit('mac'):
2015 # "-pedantic" is because of: gtest-typed-test.h:236:46: error:
2016 # anonymous variadic macros were introduced in C99
2017 # Also, gtest does not compile successfully with "-Wundef".
2018 gtest_env.FilterOut(CCFLAGS=['-pedantic', '-Wundef'])
2019 gtest_env.FilterOut(CXXFLAGS=['-fno-rtti', '-Weffc++'])
2021 # gtest is incompatible with static linking due to obscure libstdc++
2022 # linking interactions.
2023 # See http://code.google.com/p/nativeclient/issues/detail?id=1987
2024 gtest_env.FilterOut(LINKFLAGS=['-static'])
2026 gtest_env.Prepend(LIBS=['gtest'])
2029 pre_base_env.AddMethod(MakeGTestEnv)
2031 def MakeUntrustedNativeEnv(env):
2032 native_env = nacl_env.Clone()
2033 if native_env.Bit('bitcode') and not native_env.Bit('target_mips32'):
2034 native_env = native_env.PNaClGetNNaClEnv()
2037 pre_base_env.AddMethod(MakeUntrustedNativeEnv)
2039 def MakeBaseTrustedEnv(platform=None):
2040 base_env = MakeArchSpecificEnv(platform)
2042 IS_BUILD_ENV = False,
2045 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
2046 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
2053 EXTRA_CXXFLAGS = [],
2055 CFLAGS = ['${EXTRA_CFLAGS}'],
2056 CXXFLAGS = ['${EXTRA_CXXFLAGS}'],
2058 if base_env.Bit('ncval_testing'):
2059 base_env.Append(CPPDEFINES = ['NCVAL_TESTING'])
2061 base_env.Append(BUILD_SCONSCRIPTS = [
2062 # KEEP THIS SORTED PLEASE
2063 'build/build.scons',
2064 'toolchain_build/build.scons',
2065 'src/shared/gio/build.scons',
2066 'src/shared/imc/build.scons',
2067 'src/shared/ldr/build.scons',
2068 'src/shared/platform/build.scons',
2069 'src/shared/serialization/build.scons',
2070 'src/shared/srpc/build.scons',
2071 'src/shared/utils/build.scons',
2072 'src/third_party_mod/gtest/build.scons',
2073 'src/tools/validator_tools/build.scons',
2074 'src/trusted/cpu_features/build.scons',
2075 'src/trusted/debug_stub/build.scons',
2076 'src/trusted/desc/build.scons',
2077 'src/trusted/desc_cacheability/build.scons',
2078 'src/trusted/fault_injection/build.scons',
2079 'src/trusted/generic_container/build.scons',
2080 'src/trusted/gio/build.scons',
2081 'src/trusted/interval_multiset/build.scons',
2082 'src/trusted/manifest_name_service_proxy/build.scons',
2083 'src/trusted/nacl_base/build.scons',
2084 'src/trusted/nonnacl_util/build.scons',
2085 'src/trusted/perf_counter/build.scons',
2086 'src/trusted/platform_qualify/build.scons',
2087 'src/trusted/python_bindings/build.scons',
2088 'src/trusted/reverse_service/build.scons',
2089 'src/trusted/seccomp_bpf/build.scons',
2090 'src/trusted/sel_universal/build.scons',
2091 'src/trusted/service_runtime/build.scons',
2092 'src/trusted/simple_service/build.scons',
2093 'src/trusted/threading/build.scons',
2094 'src/trusted/validator/build.scons',
2095 'src/trusted/validator/driver/build.scons',
2096 'src/trusted/validator/x86/32/build.scons',
2097 'src/trusted/validator/x86/64/build.scons',
2098 'src/trusted/validator/x86/build.scons',
2099 'src/trusted/validator/x86/decoder/build.scons',
2100 'src/trusted/validator/x86/decoder/generator/build.scons',
2101 'src/trusted/validator/x86/ncval_reg_sfi/build.scons',
2102 'src/trusted/validator/x86/ncval_seg_sfi/build.scons',
2103 'src/trusted/validator/x86/ncval_seg_sfi/generator/build.scons',
2104 'src/trusted/validator/x86/testing/enuminsts/build.scons',
2105 'src/trusted/validator_arm/build.scons',
2106 'src/trusted/validator_ragel/build.scons',
2107 'src/trusted/validator_x86/build.scons',
2108 'src/trusted/weak_ref/build.scons',
2109 'tests/common/build.scons',
2110 'tests/lock_manager/build.scons',
2111 'tests/performance/build.scons',
2112 'tests/python_version/build.scons',
2113 'tests/sel_ldr_seccomp/build.scons',
2114 'tests/srpc_message/build.scons',
2115 'tests/tools/build.scons',
2116 'tests/unittests/shared/srpc/build.scons',
2117 'tests/unittests/shared/imc/build.scons',
2118 'tests/unittests/shared/platform/build.scons',
2119 'tests/unittests/trusted/asan/build.scons',
2120 'tests/unittests/trusted/bits/build.scons',
2121 'tests/unittests/trusted/platform_qualify/build.scons',
2122 'tests/unittests/trusted/service_runtime/build.scons',
2125 base_env.AddMethod(SDKInstallBin)
2127 # The ARM and MIPS validators can be built for any target that doesn't use
2129 if not base_env.Bit('target_x86_64'):
2131 BUILD_SCONSCRIPTS = [
2132 'src/trusted/validator_mips/build.scons',
2135 base_env.AddChromeFilesFromGroup('trusted_scons_files')
2138 NACL_BUILD_FAMILY = 'TRUSTED',
2141 # Add optional scons files if present in the directory tree.
2142 if os.path.exists(pre_base_env.subst('${MAIN_DIR}/supplement/build.scons')):
2143 base_env.Append(BUILD_SCONSCRIPTS=['${MAIN_DIR}/supplement/build.scons'])
2148 # Select tests to run under coverage build.
2149 pre_base_env['COVERAGE_TARGETS'] = [
2150 'small_tests', 'medium_tests', 'large_tests',
2151 'chrome_browser_tests']
2154 pre_base_env.Help("""\
2155 ======================================================================
2157 ======================================================================
2162 * cleaning: scons -c
2164 * build mandel: scons --mode=nacl mandel.nexe
2165 * smoke test: scons --mode=nacl,opt-linux -k pp=1 smoke_tests
2167 * sel_ldr: scons --mode=opt-linux sel_ldr
2169 * build the plugin: scons --mode=opt-linux ppNaClPlugin
2170 * or: scons --mode=opt-linux src/trusted/plugin
2172 Targets to build trusted code destined for the SDK:
2173 * build trusted-code tools: scons build_bin
2174 * install trusted-code tools: scons install_bin bindir=...
2175 * These default to opt build, or add --mode=dbg-host for debug build.
2177 Targets to build untrusted code destined for the SDK:
2178 * build just libraries: scons build_lib
2179 * install just headers: scons install_headers includedir=...
2180 * install just libraries: scons install_lib libdir=...
2181 * install headers and libraries:scons install includedir=... libdir=...
2183 * dump system info: scons --mode=nacl,opt-linux dummy
2188 naclsdk_mode=<mode> where <mode>:
2190 'local': use locally installed sdk kit
2191 'download': use the download copy (default)
2192 'custom:<path>': use kit at <path>
2193 'manual': use settings from env vars NACL_SDK_xxx
2195 pnaclsdk_mode=<mode> where <mode:
2196 'default': use the default (typically the downloaded copy)
2197 'custom:<path>': use kit from <path>
2199 --prebuilt Do not build things, just do install steps
2201 --verbose Full command line logging before command execution
2203 pp=1 Use command line pretty printing (more concise output)
2205 sysinfo=1 Verbose system info printing
2207 naclsdk_validate=0 Suppress presence check of sdk
2211 Automagically generated help:
2212 -----------------------------
2216 def SetUpClang(env):
2217 env['CLANG_DIR'] = '${SOURCE_ROOT}/third_party/llvm-build/Release+Asserts/bin'
2218 env['CLANG_OPTS'] = []
2220 if not (env.Bit('host_linux') or env.Bit('host_mac')):
2221 raise UserError("ERROR: ASan is only available for Linux and Mac")
2222 env['CLANG_OPTS'].append('-fsanitize=address')
2223 if env.Bit('host_mac'):
2224 # The built executables will try to find this library at runtime
2225 # in the directory containing the executable itself. In the
2226 # Chromium build, the library just gets copied into that
2227 # directory. Here, there isn't a single directory from which
2228 # all the test binaries are run (sel_ldr is run from staging/
2229 # but other trusted test binaries are run from their respective
2230 # obj/.../ directories). So instead just point the dynamic linker
2231 # at the right directory using an environment variable.
2232 clang_lib_dir = '${CLANG_DIR}/../lib/clang/*/lib/darwin'
2233 env['ENV']['DYLD_LIBRARY_PATH'] = ':'.join([dir.abspath for dir in
2234 env.Glob(clang_lib_dir)])
2235 if 'PROPAGATE_ENV' not in env:
2236 env['PROPAGATE_ENV'] = []
2237 env['PROPAGATE_ENV'].append('DYLD_LIBRARY_PATH')
2239 env['CC'] = '${CLANG_DIR}/clang ${CLANG_OPTS}'
2240 env['CXX'] = '${CLANG_DIR}/clang++ ${CLANG_OPTS}'
2241 # Make sure we find Clang-supplied libraries like -lprofile_rt
2242 # in the Clang build we use, rather than from the system.
2243 # The system-installed versions go with the system-installed Clang
2244 # and might not be compatible with the Clang we're running.
2245 env.Append(LIBPATH=['${CLANG_DIR}/../lib'])
2247 def GenerateOptimizationLevels(env):
2248 if env.Bit('clang'):
2251 # Generate debug variant.
2252 debug_env = env.Clone(tools = ['target_debug'])
2253 debug_env['OPTIMIZATION_LEVEL'] = 'dbg'
2254 debug_env['BUILD_TYPE'] = debug_env.subst('$BUILD_TYPE')
2255 debug_env['BUILD_DESCRIPTION'] = debug_env.subst('$BUILD_DESCRIPTION')
2256 AddDualLibrary(debug_env)
2257 # Add to the list of fully described environments.
2258 environment_list.append(debug_env)
2260 # Generate opt variant.
2261 opt_env = env.Clone(tools = ['target_optimized'])
2262 opt_env['OPTIMIZATION_LEVEL'] = 'opt'
2263 opt_env['BUILD_TYPE'] = opt_env.subst('$BUILD_TYPE')
2264 opt_env['BUILD_DESCRIPTION'] = opt_env.subst('$BUILD_DESCRIPTION')
2265 AddDualLibrary(opt_env)
2266 # Add to the list of fully described environments.
2267 environment_list.append(opt_env)
2269 return (debug_env, opt_env)
2272 def SDKInstallBin(env, name, node, target=None):
2273 """Add the given node to the build_bin and install_bin targets.
2274 It will be installed under the given name with the build target appended.
2275 The optional target argument overrides the setting of what that target is."""
2276 env.Alias('build_bin', node)
2277 if 'install_bin' in COMMAND_LINE_TARGETS:
2278 dir = env.GetAbsDirArg('bindir', 'install_bin')
2280 target = env['TARGET_FULLARCH'].replace('-', '_')
2281 file_name, file_ext = os.path.splitext(name)
2282 output_name = file_name + '_' + target + file_ext
2283 install_node = env.InstallAs(os.path.join(dir, output_name), node)
2284 env.Alias('install_bin', install_node)
2287 def MakeWindowsEnv(platform=None):
2288 base_env = MakeBaseTrustedEnv(platform)
2289 windows_env = base_env.Clone(
2290 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-win',
2291 BUILD_TYPE_DESCRIPTION = 'Windows ${OPTIMIZATION_LEVEL} build',
2292 tools = ['target_platform_windows'],
2293 # Windows /SAFESEH linking requires either an .sxdata section be
2294 # present or that @feat.00 be defined as a local, absolute symbol
2295 # with an odd value.
2296 ASCOM = ('$ASPPCOM /E /D__ASSEMBLER__ | '
2297 '$WINASM -defsym @feat.00=1 -o $TARGET'),
2298 PDB = '${TARGET.base}.pdb',
2299 # Strict doesn't currently work for Windows since some of the system
2300 # libraries like wsock32 are magical.
2301 LIBS_STRICT = False,
2302 TARGET_ARCH='x86_64' if base_env.Bit('build_x86_64') else 'x86',
2307 ['NACL_WINDOWS', '1'],
2309 ['NACL_LINUX', '0'],
2310 ['NACL_ANDROID', '0'],
2311 ['_WIN32_WINNT', '0x0501'],
2312 ['__STDC_LIMIT_MACROS', '1'],
2314 # WIN32 is used by ppapi
2316 # WIN32_LEAN_AND_MEAN tells windows.h to omit obsolete and rarely
2317 # used #include files. This allows use of Winsock 2.0 which otherwise
2318 # would conflict with Winsock 1.x included by windows.h.
2319 ['WIN32_LEAN_AND_MEAN', ''],
2321 LIBS = ['ws2_32', 'advapi32'],
2322 # TODO(bsy) remove 4355 once cross-repo
2323 # NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
2324 CCFLAGS = ['/EHsc', '/WX', '/wd4355', '/wd4800'],
2327 # This linker option allows us to ensure our builds are compatible with
2328 # Chromium, which uses it.
2329 if windows_env.Bit('build_x86_32'):
2330 windows_env.Append(LINKFLAGS = "/safeseh")
2332 # We use the GNU assembler (gas) on Windows so that we can use the
2333 # same .S assembly files on all platforms. Microsoft's assembler uses
2334 # a completely different syntax for x86 code.
2335 if windows_env.Bit('build_x86_64'):
2336 # This assembler only works for x86-64 code.
2337 windows_env['WINASM'] = \
2338 windows_env.File('$SOURCE_ROOT/third_party/mingw-w64/mingw/bin/'
2339 'x86_64-w64-mingw32-as.exe').abspath
2341 # This assembler only works for x86-32 code.
2342 windows_env['WINASM'] = \
2343 windows_env.File('$SOURCE_ROOT/third_party/gnu_binutils/files/'
2348 windows_optimized_env) = GenerateOptimizationLevels(MakeWindowsEnv())
2350 def MakeUnixLikeEnv(platform=None):
2351 unix_like_env = MakeBaseTrustedEnv(platform)
2352 # -Wdeclaration-after-statement is desirable because MS studio does
2353 # not allow declarations after statements in a block, and since much
2354 # of our code is portable and primarily initially tested on Linux,
2355 # it'd be nice to get the build error earlier rather than later
2356 # (building and testing on Linux is faster).
2357 # TODO(nfullagar): should we consider switching to -std=c99 ?
2358 unix_like_env.Prepend(
2361 '-Wdeclaration-after-statement',
2362 # Require defining functions as "foo(void)" rather than
2363 # "foo()" because, in C (but not C++), the latter defines a
2364 # function with unspecified arguments rather than no
2366 '-Wstrict-prototypes',
2377 '-fdiagnostics-show-option',
2378 '-fvisibility=hidden',
2379 '-fstack-protector',
2381 CXXFLAGS=['-std=c++98'],
2382 # NOTE: pthread is only neeeded for libppNaClPlugin.so and on arm
2384 CPPDEFINES = [['__STDC_LIMIT_MACROS', '1'],
2385 ['__STDC_FORMAT_MACROS', '1'],
2389 if not unix_like_env.Bit('clang'):
2390 unix_like_env.Append(CCFLAGS=['--param', 'ssp-buffer-size=4'])
2392 if unix_like_env.Bit('enable_tmpfs_redirect_var'):
2393 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '1']])
2395 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '0']])
2396 return unix_like_env
2399 def MakeMacEnv(platform=None):
2400 mac_env = MakeUnixLikeEnv(platform).Clone(
2401 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-mac',
2402 BUILD_TYPE_DESCRIPTION = 'MacOS ${OPTIMIZATION_LEVEL} build',
2403 tools = ['target_platform_mac'],
2404 # TODO(bradnelson): this should really be able to live in unix_like_env
2405 # but can't due to what the target_platform_x module is
2408 PLUGIN_SUFFIX = '.bundle',
2411 # This should be kept in synch with mac_deployment_target
2412 # in build/common.gypi, which in turn should be kept in synch
2413 # with chromium/src/build/common.gypi.
2414 mac_deployment_target = '10.6'
2417 CCFLAGS=['-mmacosx-version-min=' + mac_deployment_target],
2418 LINKFLAGS=['-mmacosx-version-min=' + mac_deployment_target])
2420 subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
2422 CCFLAGS=[subarch_flag, '-fPIC'],
2423 ASFLAGS=[subarch_flag],
2424 LINKFLAGS=[subarch_flag, '-fPIC'],
2425 CPPDEFINES = [['NACL_WINDOWS', '0'],
2427 ['NACL_LINUX', '0'],
2428 ['NACL_ANDROID', '0'],
2429 # defining _DARWIN_C_SOURCE breaks 10.4
2430 #['_DARWIN_C_SOURCE', '1'],
2431 #['__STDC_LIMIT_MACROS', '1']
2436 (mac_debug_env, mac_optimized_env) = GenerateOptimizationLevels(MakeMacEnv())
2439 def which(cmd, paths=os.environ.get('PATH', '').split(os.pathsep)):
2441 if os.access(os.path.join(p, cmd), os.X_OK):
2446 def SetUpLinuxEnvArm(env):
2447 jail = '${SCONSTRUCT_DIR}/toolchain/linux_arm-trusted'
2448 if env.Bit('arm_hard_float'):
2449 arm_abi = 'gnueabihf'
2452 if not platform.machine().startswith('arm'):
2453 # Allow emulation on non-ARM hosts.
2454 env.Replace(EMULATOR=jail + '/run_under_qemu_arm')
2455 if env.Bit('built_elsewhere'):
2456 def FakeInstall(dest, source, env):
2457 print 'Not installing', dest
2458 # Replace build commands with no-ops
2459 env.Replace(CC='true', CXX='true', LD='true',
2460 AR='true', RANLIB='true', INSTALL=FakeInstall)
2463 for suffix in ['', '-4.5', '-4.6']:
2464 if which('arm-linux-%s-g++%s' % (arm_abi, suffix)):
2467 if arm_suffix is None:
2468 # This doesn't bail out completely here because we cannot
2469 # tell whether scons was run with just --mode=nacl, where
2470 # none of these settings will actually be used.
2471 print 'NOTE: arm trusted TC is not installed'
2472 bad = 'ERROR-missing-arm-trusted-toolchain'
2473 env.Replace(CC=bad, CXX=bad, LD=bad)
2476 env.Replace(CC='arm-linux-%s-gcc%s' % (arm_abi, arm_suffix),
2477 CXX='arm-linux-%s-g++%s' % (arm_abi, arm_suffix),
2478 LD='arm-linux-%s-ld%s' % (arm_abi, arm_suffix),
2480 LIBPATH=['${LIB_DIR}',
2481 '%s/usr/lib' % jail,
2483 '%s/usr/lib/arm-linux-%s' % (jail, arm_abi),
2484 '%s/lib/arm-linux-%s' % (jail, arm_abi),
2486 LINKFLAGS=['-Wl,-rpath-link=' + jail +
2487 '/lib/arm-linux-' + arm_abi]
2489 env.Prepend(CCFLAGS=['-march=armv7-a',
2490 '-marm', # force arm32
2492 if not env.Bit('android'):
2493 env.Prepend(CCFLAGS=['-isystem', jail + '/usr/include'])
2494 # /usr/lib makes sense for most configuration except this one
2495 # No ARM compatible libs can be found there.
2496 # So this just makes the command lines longer and sometimes results
2497 # in linker warnings referring to this directory.
2498 env.FilterOut(LIBPATH=['/usr/lib'])
2500 # get_plugin_dirname.cc has a dependency on dladdr
2501 env.Append(LIBS=['dl'])
2503 def SetUpAndroidEnv(env):
2504 env.FilterOut(CPPDEFINES=[['NACL_ANDROID', '0']])
2505 env.Prepend(CPPDEFINES=[['NACL_ANDROID', '1']])
2506 ndk = os.environ.get('ANDROID_NDK_ROOT')
2507 sdk = os.environ.get('ANDROID_SDK_ROOT')
2509 if env.Bit('build_arm'):
2510 ndk_target = 'arm-linux-androideabi'
2511 ndk_tctarget = ndk_target
2513 libarch = 'armeabi-v7a'
2514 arch_cflags += ['-march=armv7-a', '-mfloat-abi=softfp']
2515 elif env.Bit('build_mips32'):
2516 ndk_target = 'mipsel-linux-android'
2517 ndk_tctarget = ndk_target
2521 ndk_target = 'i686-linux-android'
2522 # x86 toolchain has strange location, not using GNU triplet
2523 ndk_tctarget = 'x86'
2527 if not ndk or not sdk:
2528 print 'Please define ANDROID_NDK_ROOT and ANDROID_SDK_ROOT'
2530 tc = '%s/toolchains/%s-%s/prebuilt/linux-x86_64/bin/' \
2531 % (ndk, ndk_tctarget, ndk_version)
2532 tc_prefix = '%s/%s-' % (tc, ndk_target)
2533 platform_prefix = '%s/platforms/android-14/arch-%s' % (ndk, arch)
2534 stl_path = '%s/sources/cxx-stl/gnu-libstdc++/%s' % (ndk, ndk_version)
2535 env.Replace(CC=tc_prefix + 'gcc',
2536 CXX=tc_prefix + 'g++',
2537 LD=tc_prefix + 'g++',
2538 EMULATOR=sdk + '/tools/emulator',
2539 LIBPATH=['${LIB_DIR}',
2540 '%s/libs/%s' % (stl_path, libarch),
2541 '%s/usr/lib' % (platform_prefix),
2543 LIBS=['gnustl_static', # Yes, that stdc++.
2548 # Second time, to have mutual libgcc<->libc deps resolved.
2552 env.Append(CCFLAGS=['--sysroot='+ platform_prefix,
2553 '-isystem='+ platform_prefix + '/usr/include',
2556 # Due to bogus warnings on uintptr_t formats.
2559 CXXFLAGS=['-I%s/include' % (stl_path),
2560 '-I%s/libs/%s/include' % (stl_path, libarch),
2564 LINKFLAGS=['-Wl,-rpath-link=' + platform_prefix + '/usr/lib',
2565 '-Wl,-Ttext,0x50000000',
2568 '-L%s/../lib/gcc/%s/%s' \
2569 % (tc, ndk_target, ndk_version),
2570 # Note that we have to use crtbegin_static.o
2571 # if compile -static, and crtbegin_dynamic.o
2572 # otherwise. Also, this apporach skips
2573 # all static initializers invocations.
2574 # TODO(olonho): implement proper static
2575 # initializers solution.
2576 platform_prefix + '/usr/lib/crtbegin_static.o',
2577 platform_prefix + '/usr/lib/crtend_android.o',
2580 # As we want static binary, not PIE.
2581 env.FilterOut(LINKFLAGS=['-pie'])
2584 def SetUpLinuxEnvMips(env):
2585 jail = '${SCONSTRUCT_DIR}/toolchain/linux_mips-trusted'
2586 if not platform.machine().startswith('mips'):
2587 # Allow emulation on non-MIPS hosts.
2588 env.Replace(EMULATOR=jail + '/run_under_qemu_mips32')
2589 if env.Bit('built_elsewhere'):
2590 def FakeInstall(dest, source, env):
2591 print 'Not installing', dest
2592 # Replace build commands with no-ops
2593 env.Replace(CC='true', CXX='true', LD='true',
2594 AR='true', RANLIB='true', INSTALL=FakeInstall)
2596 tc_dir = os.path.join(os.getcwd(), 'toolchain', 'linux_mips-trusted',
2598 if not which(os.path.join(tc_dir, 'mipsel-linux-gnu-gcc')):
2599 raise UserError("\nERRROR: "
2600 "MIPS trusted TC is not installed - try running:\n"
2601 "tools/trusted_cross_toolchains/trusted-toolchain-creator"
2602 ".mipsel.debian.sh nacl_sdk")
2603 env.Replace(CC=os.path.join(tc_dir, 'mipsel-linux-gnu-gcc'),
2604 CXX=os.path.join(tc_dir, 'mipsel-linux-gnu-g++'),
2605 LD=os.path.join(tc_dir, 'mipsel-linux-gnu-ld'),
2607 LIBPATH=['${LIB_DIR}',
2608 jail + '/sysroot/usr/lib'],
2610 os.path.join(jail, 'ld_script_mips_trusted')]
2613 env.Append(LIBS=['rt', 'dl', 'pthread'],
2614 CCFLAGS=['-march=mips32r2'])
2617 def MakeLinuxEnv(platform=None):
2618 linux_env = MakeUnixLikeEnv(platform).Clone(
2619 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-linux',
2620 BUILD_TYPE_DESCRIPTION = 'Linux ${OPTIMIZATION_LEVEL} build',
2621 tools = ['target_platform_linux'],
2622 # TODO(bradnelson): this should really be able to live in unix_like_env
2623 # but can't due to what the target_platform_x module is
2628 # Prepend so we can disable warnings via Append
2630 CPPDEFINES = [['NACL_WINDOWS', '0'],
2632 ['NACL_LINUX', '1'],
2633 ['NACL_ANDROID', '0'],
2634 ['_BSD_SOURCE', '1'],
2635 ['_POSIX_C_SOURCE', '199506'],
2636 ['_XOPEN_SOURCE', '600'],
2637 ['_GNU_SOURCE', '1'],
2638 ['_LARGEFILE64_SOURCE', '1'],
2643 if linux_env.Bit('build_x86_32'):
2646 LINKFLAGS = ['-m32'],
2648 elif linux_env.Bit('build_x86_64'):
2651 LINKFLAGS = ['-m64'],
2653 elif linux_env.Bit('build_arm'):
2654 SetUpLinuxEnvArm(linux_env)
2655 elif linux_env.Bit('build_mips32'):
2656 SetUpLinuxEnvMips(linux_env)
2658 Banner('Strange platform: %s' % GetTargetPlatform())
2660 # These are desireable options for every Linux platform:
2661 # _FORTIFY_SOURCE: general paranoia "hardening" option for library functions
2662 # -fPIE/-pie: create a position-independent executable
2663 # relro/now: "hardening" options for linking
2664 # noexecstack: ensure that the executable does not get a PT_GNU_STACK
2665 # header that causes the kernel to set the READ_IMPLIES_EXEC
2666 # personality flag, which disables NX page protection.
2668 CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']],
2669 LINKFLAGS=['-pie', '-Wl,-z,relro', '-Wl,-z,now', '-Wl,-z,noexecstack'],
2671 # The ARM toolchain has a linker that doesn't handle the code its
2672 # compiler generates under -fPIE.
2673 if linux_env.Bit('build_arm') or linux_env.Bit('build_mips32'):
2674 linux_env.Prepend(CCFLAGS=['-fPIC'])
2675 # TODO(mcgrathr): Temporarily punt _FORTIFY_SOURCE for ARM because
2676 # it causes a libc dependency newer than the old bots have installed.
2677 linux_env.FilterOut(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2679 linux_env.Prepend(CCFLAGS=['-fPIE'])
2681 # We always want to use the same flags for .S as for .c because
2682 # code-generation flags affect the predefines we might test there.
2683 linux_env.Replace(ASFLAGS=['${CCFLAGS}'])
2685 if linux_env.Bit('android'):
2686 SetUpAndroidEnv(linux_env)
2690 (linux_debug_env, linux_optimized_env) = \
2691 GenerateOptimizationLevels(MakeLinuxEnv())
2693 # Do this before the site_scons/site_tools/naclsdk.py stuff to pass it along.
2694 pre_base_env.Append(
2695 PNACL_BCLDFLAGS = ARGUMENTS.get('pnacl_bcldflags', '').split(':'))
2698 # The nacl_env is used to build native_client modules
2699 # using a special tool chain which produces platform
2700 # independent binaries
2701 # NOTE: this loads stuff from: site_scons/site_tools/naclsdk.py
2702 nacl_env = MakeArchSpecificEnv()
2703 nacl_env = nacl_env.Clone(
2704 tools = ['naclsdk'],
2705 NACL_BUILD_FAMILY = 'UNTRUSTED',
2706 BUILD_TYPE = 'nacl',
2707 BUILD_TYPE_DESCRIPTION = 'NaCl module build',
2711 # ${SOURCE_ROOT} for #include <ppapi/...>
2717 EXTRA_CXXFLAGS = [],
2719 EXTRA_LINKFLAGS = ARGUMENTS.get('nacl_linkflags', '').split(':'),
2721 # always optimize binaries
2724 '-fomit-frame-pointer',
2725 # This makes sure unwind/backtrace info is available for
2726 # all code locations. Note build/untrusted.gypi uses it too.
2727 '-fasynchronous-unwind-tables',
2730 '-fdiagnostics-show-option',
2735 CFLAGS = ['-std=gnu99',
2737 CXXFLAGS = ['-std=gnu++98',
2741 # This magic is copied from scons-2.0.1/engine/SCons/Defaults.py
2742 # where this pattern is used for _LIBDIRFLAGS, which produces -L
2743 # switches. Here we are producing a -Wl,-rpath-link,DIR for each
2744 # element of LIBPATH, i.e. for each -LDIR produced.
2745 RPATH_LINK_FLAGS = '$( ${_concat(RPATHLINKPREFIX, LIBPATH, RPATHLINKSUFFIX,'
2746 '__env__, RDirs, TARGET, SOURCE)} $)',
2747 RPATHLINKPREFIX = '-Wl,-rpath-link,',
2748 RPATHLINKSUFFIX = '',
2751 LINKFLAGS = ['${RPATH_LINK_FLAGS}'],
2753 # These are settings for in-tree, non-browser tests to use.
2754 # They use libraries that circumvent the IRT-based implementations
2755 # in the public libraries.
2756 # Note that pthread_private is part of NONIRT_LIBS for PNaCl because
2757 # libc++ depends on it.
2758 NONIRT_LIBS = (['nacl_sys_private'] +
2759 (['pthread_private'] if nacl_env.Bit('bitcode') else [])),
2760 PTHREAD_LIBS = ['pthread_private'],
2761 DYNCODE_LIBS = ['nacl_dyncode_private'],
2762 EXCEPTION_LIBS = ['nacl_exception_private'],
2763 LIST_MAPPINGS_LIBS = ['nacl_list_mappings_private'],
2766 def UsesAbiNote(env):
2767 """Return True if using a new-style GCC with .note.NaCl.ABI.* notes.
2768 This means there will always be an RODATA segment, even if just for the note."""
2769 return env.Bit('target_arm') and not env.Bit('bitcode')
2771 nacl_env.AddMethod(UsesAbiNote)
2773 def UnderWindowsCoverage(env):
2774 """Return True if using running on coverage under windows."""
2775 if 'TRUSTED_ENV' not in env:
2777 return env['TRUSTED_ENV'].Bit('coverage_enabled') and env.Bit('host_windows')
2779 nacl_env.AddMethod(UnderWindowsCoverage)
2781 def AllowNonStableBitcode(env):
2782 """ This modifies the environment to allow features that aren't part
2783 of PNaCl's stable ABI. If tests using these features should be
2784 skipped entirely, this returns False. Otherwise, on success, it
2787 if env.Bit('bitcode'):
2788 env.SetBits('nonstable_bitcode')
2789 return not env.Bit('skip_nonstable_bitcode')
2791 nacl_env.AddMethod(AllowNonStableBitcode)
2794 def AllowInlineAssembly(env):
2795 """ This modifies the environment to allow inline assembly in
2796 untrusted code. If the environment cannot be modified to allow
2797 inline assembly, it returns False. Otherwise, on success, it
2800 if env.Bit('bitcode'):
2801 # For each architecture, we only attempt to make our inline
2802 # assembly code work with one untrusted-code toolchain. For x86,
2803 # we target GCC, but not PNaCl/Clang, because the latter's
2804 # assembly support has various quirks that we don't want to have
2805 # to debug. For ARM, we target PNaCl/Clang, because that is the
2806 # only current ARM toolchain. One day, we will have an ARM GCC
2807 # toolchain, and we will no longer need to use inline assembly
2808 # with PNaCl/Clang at all.
2809 if not (env.Bit('target_arm') or env.Bit('target_mips32')):
2811 # Inline assembly does not work in pexes.
2812 if env.Bit('pnacl_generate_pexe'):
2814 env.AddBiasForPNaCl()
2815 env.PNaClForceNative()
2818 nacl_env.AddMethod(AllowInlineAssembly)
2821 # TODO(mseaborn): Enable this unconditionally once the C code on the
2822 # Chromium side compiles successfully with this warning.
2823 if not enable_chrome:
2824 nacl_env.Append(CFLAGS=['-Wstrict-prototypes'])
2826 # This is the address at which a user executable is expected to place its
2827 # data segment in order to be compatible with the integrated runtime (IRT)
2828 # library. This address should not be changed lightly.
2829 irt_compatible_rodata_addr = 0x10000000
2830 # This is the address at which the IRT's own code will be located.
2831 # It must be below irt_compatible_rodata and leave enough space for
2832 # the code segment of the IRT. It should be as close as possible to
2833 # irt_compatible_rodata so as to leave the maximum contiguous area
2834 # available for the dynamic code loading area that falls below it.
2835 # This can be adjusted as necessary for the actual size of the IRT code.
2836 irt_code_addr = irt_compatible_rodata_addr - (6 << 20) # max 6M IRT code
2837 # This is the address at which the IRT's own data will be located. The
2838 # 32-bit sandboxes limit the address space to 1GB; the initial thread's
2839 # stack sits at the top of the address space and extends down for
2840 # NACL_DEFAULT_STACK_MAX (src/trusted/service_runtime/sel_ldr.h) below.
2841 # So this must be below there, and leave enough space for the IRT's own
2842 # data segment. It should be as high as possible so as to leave the
2843 # maximum contiguous area available for the user's data and break below.
2844 # This can be adjusted as necessary for the actual size of the IRT data
2845 # (that is RODATA, rounded up to 64k, plus writable data).
2846 # 1G (address space) - 16M (NACL_DEFAULT_STACK_MAX) - 1MB (IRT rodata+data)
2847 irt_data_addr = (1 << 30) - (16 << 20) - (1 << 20)
2850 IRT_DATA_REGION_START = '%#.8x' % irt_compatible_rodata_addr,
2851 # Load addresses of the IRT's code and data segments.
2852 IRT_BLOB_CODE_START = '%#.8x' % irt_code_addr,
2853 IRT_BLOB_DATA_START = '%#.8x' % irt_data_addr,
2856 def TestsUsePublicListMappingsLib(env):
2857 """Use the public list_mappings library for in-tree tests."""
2858 env.Replace(LIST_MAPPINGS_LIBS=['nacl_list_mappings'])
2860 def TestsUsePublicLibs(env):
2861 """Change the environment so it uses public libraries for in-tree tests."""
2862 env.Replace(NONIRT_LIBS=['pthread'] if env.Bit('bitcode') else [],
2863 PTHREAD_LIBS=['pthread'],
2864 DYNCODE_LIBS=['nacl_dyncode', 'nacl'],
2865 EXCEPTION_LIBS=['nacl_exception', 'nacl'])
2867 # glibc is incompatible with libpthread_private and libnacl_sys_private.
2868 if nacl_env.Bit('nacl_glibc'):
2869 nacl_env.Replace(NONIRT_LIBS=[],
2870 PTHREAD_LIBS=['pthread'])
2872 # These add on to those set in pre_base_env, above.
2875 # This ensures that UINT32_MAX gets defined.
2876 ['__STDC_LIMIT_MACROS', '1'],
2877 # This ensures that PRId64 etc. get defined.
2878 ['__STDC_FORMAT_MACROS', '1'],
2879 # _GNU_SOURCE ensures that strtof() gets declared.
2881 # strdup, and other common stuff
2882 ['_BSD_SOURCE', '1'],
2883 ['_POSIX_C_SOURCE', '199506'],
2884 ['_XOPEN_SOURCE', '600'],
2886 ['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
2887 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ],
2889 ['NACL_WINDOWS', '0'],
2891 ['NACL_LINUX', '0'],
2892 ['NACL_ANDROID', '0'],
2896 def FixWindowsAssembler(env):
2897 if env.Bit('host_windows'):
2898 # NOTE: This is needed because Windows builds are case-insensitive.
2899 # Without this we use nacl-as, which doesn't handle include directives, etc.
2900 env.Replace(ASCOM='${CCCOM}')
2902 FixWindowsAssembler(nacl_env)
2904 # Look in the local include and lib directories before the toolchain's.
2905 nacl_env['INCLUDE_DIR'] = '${TARGET_ROOT}/include'
2906 # Remove the default $LIB_DIR element so that we prepend it without duplication.
2907 # Using PrependUnique alone would let it stay last, where we want it first.
2908 nacl_env.FilterOut(LIBPATH=['${LIB_DIR}'])
2909 nacl_env.PrependUnique(
2910 CPPPATH = ['${INCLUDE_DIR}'],
2911 LIBPATH = ['${LIB_DIR}'],
2914 if nacl_env.Bit('bitcode'):
2915 # passing -O when linking requests LTO, which does additional global
2916 # optimizations at link time
2917 nacl_env.Append(LINKFLAGS=['-O3'])
2918 if not nacl_env.Bit('nacl_glibc'):
2919 nacl_env.Append(LINKFLAGS=['-static'])
2921 if nacl_env.Bit('translate_fast'):
2922 nacl_env.Append(LINKFLAGS=['-Xlinker', '-translate-fast'])
2923 nacl_env.Append(TRANSLATEFLAGS=['-translate-fast'])
2925 # With pnacl's clang base/ code uses the "override" keyword.
2926 nacl_env.Append(CXXFLAGS=['-Wno-c++11-extensions'])
2927 # Allow extraneous semicolons. (Until these are removed.)
2928 # http://code.google.com/p/nativeclient/issues/detail?id=2861
2929 nacl_env.Append(CCFLAGS=['-Wno-extra-semi'])
2930 # Allow unused private fields. (Until these are removed.)
2931 # http://code.google.com/p/nativeclient/issues/detail?id=2861
2932 nacl_env.Append(CCFLAGS=['-Wno-unused-private-field'])
2934 # We use a special environment for building the IRT image because it must
2935 # always use the newlib toolchain, regardless of --nacl_glibc. We clone
2936 # it from nacl_env here, before too much other cruft has been added.
2937 # We do some more magic below to instantiate it the way we need it.
2938 nacl_irt_env = nacl_env.Clone(
2939 BUILD_TYPE = 'nacl_irt',
2940 BUILD_TYPE_DESCRIPTION = 'NaCl IRT build',
2941 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT',
2944 # Provide access to the IRT build environment from the default environment
2945 # which is needed when compiling custom IRT for testing purposes.
2946 nacl_env['NACL_IRT_ENV'] = nacl_irt_env
2948 # Since we don't build src/untrusted/pthread/nacl.scons in
2949 # nacl_irt_env, we must tell the IRT how to find the pthread.h header.
2950 nacl_irt_env.Append(CPPPATH='${MAIN_DIR}/src/untrusted/pthread')
2952 # Map certain flag bits to suffices on the build output. This needs to
2953 # happen pretty early, because it affects any concretized directory names.
2954 target_variant_map = [
2955 ('bitcode', 'pnacl'),
2956 ('translate_fast', 'fast'),
2957 ('nacl_pic', 'pic'),
2958 ('use_sandboxed_translator', 'sbtc'),
2959 ('nacl_glibc', 'glibc'),
2960 ('pnacl_generate_pexe', 'pexe'),
2962 for variant_bit, variant_suffix in target_variant_map:
2963 if nacl_env.Bit(variant_bit):
2964 nacl_env['TARGET_VARIANT'] += '-' + variant_suffix
2966 if nacl_env.Bit('bitcode'):
2967 nacl_env['TARGET_VARIANT'] += '-clang'
2969 nacl_env.Replace(TESTRUNNER_LIBS=['testrunner'])
2970 # TODO(mseaborn): Drop this once chrome side has inlined this.
2971 nacl_env.Replace(PPAPI_LIBS=['ppapi'])
2973 # TODO(mseaborn): Make nacl-glibc-based static linking work with just
2974 # "-static", without specifying a linker script.
2975 # See http://code.google.com/p/nativeclient/issues/detail?id=1298
2976 def GetLinkerScriptBaseName(env):
2977 if env.Bit('build_x86_64'):
2978 return 'elf_x86_64_nacl'
2980 return 'elf_i386_nacl'
2982 if (nacl_env.Bit('nacl_glibc') and
2983 nacl_env.Bit('nacl_static_link')):
2984 nacl_env.Append(LINKFLAGS=['-static'])
2985 if nacl_env.Bit('target_x86'):
2986 # The "-lc" is necessary because libgcc_eh depends on libc but for
2987 # some reason nacl-gcc is not linking with "--start-group/--end-group".
2988 nacl_env.Append(LINKFLAGS=[
2989 '-T', 'ldscripts/%s.x.static' % GetLinkerScriptBaseName(nacl_env),
2992 if nacl_env.Bit('running_on_valgrind'):
2993 nacl_env.Append(CCFLAGS = ['-g', '-Wno-overlength-strings',
2994 '-fno-optimize-sibling-calls'],
2995 CPPDEFINES = [['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
2996 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ]])
2997 # With GLibC, libvalgrind.so is preloaded at runtime.
2998 # With Newlib, it has to be linked in.
2999 if not nacl_env.Bit('nacl_glibc'):
3000 nacl_env.Append(LINKFLAGS = ['-Wl,-u,have_nacl_valgrind_interceptors'],
3001 LIBS = ['valgrind'])
3003 environment_list.append(nacl_env)
3005 if not nacl_env.Bit('nacl_glibc'):
3006 # These are all specific to nacl-newlib so we do not include them
3007 # when building against nacl-glibc. The functionality of
3008 # pthread/startup/stubs/nosys is provided by glibc. The valgrind
3009 # code currently assumes nc_threads.
3011 BUILD_SCONSCRIPTS = [
3012 #### ALPHABETICALLY SORTED ####
3013 'src/untrusted/pthread/nacl.scons',
3014 'src/untrusted/stubs/nacl.scons',
3015 'src/untrusted/nosys/nacl.scons',
3016 #### ALPHABETICALLY SORTED ####
3019 BUILD_SCONSCRIPTS = [
3020 #### ALPHABETICALLY SORTED ####
3021 'src/shared/gio/nacl.scons',
3022 'src/shared/imc/nacl.scons',
3023 'src/shared/ldr/nacl.scons',
3024 'src/shared/platform/nacl.scons',
3025 'src/shared/srpc/nacl.scons',
3026 'src/trusted/service_runtime/nacl.scons',
3027 'src/trusted/validator/nacl.scons',
3028 'src/trusted/weak_ref/nacl.scons',
3029 'src/untrusted/crash_dump/nacl.scons',
3030 'src/untrusted/minidump_generator/nacl.scons',
3031 'src/untrusted/nacl/nacl.scons',
3032 'src/untrusted/valgrind/nacl.scons',
3033 #### ALPHABETICALLY SORTED ####
3035 nacl_env.AddChromeFilesFromGroup('untrusted_scons_files')
3037 # These are tests that are worthwhile to run in IRT variant only.
3039 #### ALPHABETICALLY SORTED ####
3040 'tests/irt/nacl.scons',
3041 'tests/irt_compatibility/nacl.scons',
3042 'tests/random/nacl.scons',
3043 'tests/sbrk/nacl.scons',
3044 'tests/translator_size_limits/nacl.scons',
3047 # These are tests that are worthwhile to run in both IRT and non-IRT variants.
3048 # The nacl_irt_test mode runs them in the IRT variants.
3049 irt_variant_tests = [
3050 #### ALPHABETICALLY SORTED ####
3051 'tests/app_lib/nacl.scons',
3052 'tests/bigalloc/nacl.scons',
3053 'tests/bundle_size/nacl.scons',
3054 'tests/callingconv/nacl.scons',
3055 'tests/callingconv_ppapi/nacl.scons',
3056 'tests/callingconv_case_by_case/nacl.scons',
3057 'tests/clock/nacl.scons',
3058 'tests/common/nacl.scons',
3059 'tests/compiler_thread_suspension/nacl.scons',
3060 'tests/computed_gotos/nacl.scons',
3061 'tests/data_below_data_start/nacl.scons',
3062 'tests/data_not_executable/nacl.scons',
3063 'tests/dup/nacl.scons',
3064 'tests/dynamic_code_loading/nacl.scons',
3065 'tests/dynamic_linking/nacl.scons',
3066 'tests/egyptian_cotton/nacl.scons',
3067 'tests/environment_variables/nacl.scons',
3068 'tests/exception_test/nacl.scons',
3069 'tests/fib/nacl.scons',
3070 'tests/file/nacl.scons',
3071 'tests/fixedfeaturecpu/nacl.scons',
3072 'tests/futexes/nacl.scons',
3073 'tests/gc_instrumentation/nacl.scons',
3074 'tests/gdb/nacl.scons',
3075 'tests/glibc_file64_test/nacl.scons',
3076 'tests/glibc_static_test/nacl.scons',
3077 'tests/glibc_syscall_wrappers/nacl.scons',
3078 'tests/glibc_socket_wrappers/nacl.scons',
3079 'tests/hello_world/nacl.scons',
3080 'tests/imc_shm_mmap/nacl.scons',
3081 'tests/infoleak/nacl.scons',
3082 'tests/libc/nacl.scons',
3083 'tests/libc_free_hello_world/nacl.scons',
3084 'tests/list_mappings/nacl.scons',
3085 'tests/longjmp/nacl.scons',
3086 'tests/loop/nacl.scons',
3087 'tests/mandel/nacl.scons',
3088 'tests/manifest_file/nacl.scons',
3089 'tests/math/nacl.scons',
3090 'tests/memcheck_test/nacl.scons',
3091 'tests/mmap/nacl.scons',
3092 'tests/mmap_main_nexe/nacl.scons',
3093 'tests/mmap_prot_exec/nacl.scons',
3094 'tests/mmap_race_protect/nacl.scons',
3095 'tests/nacl_log/nacl.scons',
3096 'tests/nameservice/nacl.scons',
3097 'tests/nanosleep/nacl.scons',
3098 'tests/noop/nacl.scons',
3099 'tests/nrd_xfer/nacl.scons',
3100 'tests/nthread_nice/nacl.scons',
3101 'tests/null/nacl.scons',
3102 'tests/nullptr/nacl.scons',
3103 'tests/pagesize/nacl.scons',
3104 'tests/performance/nacl.scons',
3105 'tests/pnacl_abi/nacl.scons',
3106 'tests/pnacl_native_objects/nacl.scons',
3107 'tests/process_create/nacl.scons',
3108 'tests/redir/nacl.scons',
3109 'tests/rodata_not_writable/nacl.scons',
3110 'tests/sel_ldr/nacl.scons',
3111 'tests/sel_ldr_seccomp/nacl.scons',
3112 'tests/sel_main_chrome/nacl.scons',
3113 'tests/signal_handler/nacl.scons',
3114 'tests/sleep/nacl.scons',
3115 'tests/srpc/nacl.scons',
3116 'tests/srpc_hw/nacl.scons',
3117 'tests/srpc_message/nacl.scons',
3118 'tests/stack_alignment/nacl.scons',
3119 'tests/stubout_mode/nacl.scons',
3120 'tests/subprocess/nacl.scons',
3121 'tests/sysbasic/nacl.scons',
3122 'tests/syscall_return_regs/nacl.scons',
3123 'tests/syscall_return_sandboxing/nacl.scons',
3124 'tests/syscalls/nacl.scons',
3125 'tests/thread_capture/nacl.scons',
3126 'tests/threads/nacl.scons',
3127 'tests/time/nacl.scons',
3128 'tests/tls/nacl.scons',
3129 'tests/tls_perf/nacl.scons',
3130 'tests/tls_segment_x86_32/nacl.scons',
3131 'tests/toolchain/nacl.scons',
3132 'tests/toolchain/arm/nacl.scons',
3133 'tests/toolchain/mips/nacl.scons',
3134 'tests/unittests/shared/platform/nacl.scons',
3135 'tests/untrusted_check/nacl.scons',
3136 'tests/unwind_restores_regs/nacl.scons',
3137 #### ALPHABETICALLY SORTED ####
3138 # NOTE: The following tests are really IRT-only tests, but they
3139 # are in this category so that they can generate libraries (which
3140 # works in nacl_env but not in nacl_irt_test_env) while also
3141 # adding tests to nacl_irt_test_env.
3142 'tests/inbrowser_test_runner/nacl.scons',
3143 'tests/untrusted_crash_dump/nacl.scons',
3144 'tests/untrusted_minidump/nacl.scons',
3147 # These are tests that are NOT worthwhile to run in an IRT variant.
3148 # In some cases, that's because they are browser tests which always
3149 # use the IRT. In others, it's because they are special-case tests
3150 # that are incompatible with having an IRT loaded.
3151 nonvariant_tests = [
3152 #### ALPHABETICALLY SORTED ####
3153 'tests/barebones/nacl.scons',
3154 'tests/chrome_extension/nacl.scons',
3155 'tests/custom_desc/nacl.scons',
3156 'tests/debug_stub/nacl.scons',
3157 'tests/faulted_thread_queue/nacl.scons',
3158 'tests/imc_sockets/nacl.scons',
3159 'tests/minnacl/nacl.scons',
3160 'tests/multiple_sandboxes/nacl.scons',
3161 # Potential issue with running them:
3162 # http://code.google.com/p/nativeclient/issues/detail?id=2092
3163 # See also the comment in "buildbot/buildbot_standard.py"
3164 'tests/pnacl_shared_lib_test/nacl.scons',
3165 'tests/pwrite/nacl.scons',
3166 'tests/signal_handler_single_step/nacl.scons',
3167 'tests/thread_suspension/nacl.scons',
3168 'tests/trusted_crash/crash_in_syscall/nacl.scons',
3169 'tests/trusted_crash/osx_crash_filter/nacl.scons',
3170 'tests/trusted_crash/osx_crash_forwarding/nacl.scons',
3171 'tests/unittests/shared/imc/nacl.scons',
3172 'tests/unittests/shared/srpc/nacl.scons',
3173 #### ALPHABETICALLY SORTED ####
3176 nacl_env.Append(BUILD_SCONSCRIPTS=nonvariant_tests)
3177 nacl_env.AddChromeFilesFromGroup('nonvariant_test_scons_files')
3178 nacl_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3179 nacl_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3181 # Defines TESTS_TO_RUN_INBROWSER.
3182 SConscript('tests/inbrowser_test_runner/selection.scons',
3183 exports=['nacl_env'])
3185 # Possibly install a toolchain by downloading it
3186 # TODO: explore using a less heavy weight mechanism
3187 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3190 SCons.Script.AddOption('--download',
3194 action='store_true',
3195 help='deprecated - allow tools to download')
3197 if nacl_env.GetOption('download'):
3198 print '@@@@ --download is deprecated, use gclient runhooks --force'
3199 nacl_sync_env = nacl_env.Clone()
3200 nacl_sync_env['ENV'] = os.environ
3201 nacl_sync_env.Execute('gclient runhooks --force')
3204 def NaClSharedLibrary(env, lib_name, *args, **kwargs):
3205 env_shared = env.Clone(COMPONENT_STATIC=False)
3206 soname = SCons.Util.adjustixes(lib_name, 'lib', '.so')
3207 env_shared.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s' % (soname)])
3208 return env_shared.ComponentLibrary(lib_name, *args, **kwargs)
3210 nacl_env.AddMethod(NaClSharedLibrary)
3212 def NaClSdkLibrary(env, lib_name, *args, **kwargs):
3213 n = [env.ComponentLibrary(lib_name, *args, **kwargs)]
3214 if not env.Bit('nacl_disable_shared'):
3215 n.append(env.NaClSharedLibrary(lib_name, *args, **kwargs))
3218 nacl_env.AddMethod(NaClSdkLibrary)
3221 # Special environment for untrusted test binaries that use raw syscalls
3222 def RawSyscallObjects(env, sources):
3223 raw_syscall_env = env.Clone()
3224 raw_syscall_env.Append(
3226 ['USE_RAW_SYSCALLS', '1'],
3227 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
3228 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
3229 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
3230 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
3234 for source_file in sources:
3235 target_name = 'raw_' + os.path.basename(source_file).rstrip('.c')
3236 object = raw_syscall_env.ComponentObject(target_name,
3238 objects.append(object)
3241 nacl_env.AddMethod(RawSyscallObjects)
3244 # The IRT-building environment was cloned from nacl_env, but it should
3245 # ignore the --nacl_glibc, nacl_pic=1 and bitcode=1 switches.
3246 # We have to reinstantiate the naclsdk.py magic after clearing those flags,
3247 # so it regenerates the tool paths right.
3248 # TODO(mcgrathr,bradnelson): could get cleaner if naclsdk.py got folded back in.
3249 nacl_irt_env.ClearBits('nacl_glibc')
3250 nacl_irt_env.ClearBits('nacl_pic')
3251 # We build the IRT using the nnacl TC even when the pnacl TC is used otherwise.
3252 if nacl_irt_env.Bit('target_mips32') or nacl_irt_env.Bit('target_x86_64'):
3253 nacl_irt_env.SetBits('bitcode')
3255 nacl_irt_env.ClearBits('bitcode')
3256 nacl_irt_env.ClearBits('pnacl_generate_pexe')
3257 nacl_irt_env.ClearBits('use_sandboxed_translator')
3258 nacl_irt_env.Tool('naclsdk')
3259 # These are unfortunately clobbered by running Tool, which
3260 # we needed to do to get the destination directory reset.
3261 # We want all the same values from nacl_env.
3262 nacl_irt_env.Replace(EXTRA_CFLAGS=nacl_env['EXTRA_CFLAGS'],
3263 EXTRA_CXXFLAGS=nacl_env['EXTRA_CXXFLAGS'],
3264 CCFLAGS=nacl_env['CCFLAGS'],
3265 CFLAGS=nacl_env['CFLAGS'],
3266 CXXFLAGS=nacl_env['CXXFLAGS'])
3267 FixWindowsAssembler(nacl_irt_env)
3268 # Make it find the libraries it builds, rather than the SDK ones.
3269 nacl_irt_env.Replace(LIBPATH='${LIB_DIR}')
3271 if nacl_irt_env.Bit('bitcode'):
3272 if nacl_irt_env.Bit('target_x86_64'):
3273 nacl_irt_env.Append(CCFLAGS=['--target=x86_64-nacl'])
3274 nacl_irt_env.Append(LINKFLAGS=['--target=x86_64-nacl',
3275 '--pnacl-allow-translate',
3278 # The IRT is C only, don't link with the C++ linker so that it doesn't
3279 # start depending on the C++ standard library and (in the case of
3281 nacl_irt_env.Replace(LINK=(nacl_irt_env['LINK'].
3282 replace('pnacl-clang++', 'pnacl-clang')))
3284 if nacl_irt_env.Bit('bitcode'):
3285 nacl_irt_env.Append(LINKFLAGS=['--pnacl-allow-native'])
3287 # All IRT code must avoid direct use of the TLS ABI register, which
3288 # is reserved for user TLS. Instead, ensure all TLS accesses use a
3289 # call to __nacl_read_tp, which the IRT code overrides to segregate
3290 # IRT-private TLS from user TLS. This only applies to mips now, on
3291 # other platforms we modify the TLS register through tls_edit as a
3293 if nacl_irt_env.Bit('target_mips32'):
3294 nacl_irt_env.Append(LINKFLAGS=['-Wt,-mtls-use-call'])
3296 # TODO(mcgrathr): Clean up uses of these methods.
3297 def AddLibraryDummy(env, nodes):
3299 nacl_irt_env.AddMethod(AddLibraryDummy, 'AddLibraryToSdk')
3301 def AddObjectInternal(env, nodes):
3302 return env.Replicate('${LIB_DIR}', nodes)
3303 nacl_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3304 nacl_irt_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3306 def IrtNaClSdkLibrary(env, lib_name, *args, **kwargs):
3307 env.ComponentLibrary(lib_name, *args, **kwargs)
3308 nacl_irt_env.AddMethod(IrtNaClSdkLibrary, 'NaClSdkLibrary')
3310 nacl_irt_env.AddMethod(SDKInstallBin)
3312 # Populate the internal include directory when AddHeaderToSdk
3313 # is used inside nacl_env.
3314 def AddHeaderInternal(env, nodes, subdir='nacl'):
3315 dir = '${INCLUDE_DIR}'
3316 if subdir is not None:
3318 n = env.Replicate(dir, nodes)
3321 nacl_irt_env.AddMethod(AddHeaderInternal, 'AddHeaderToSdk')
3323 def PublishHeader(env, nodes, subdir):
3324 if ('install' in COMMAND_LINE_TARGETS or
3325 'install_headers' in COMMAND_LINE_TARGETS):
3326 dir = env.GetAbsDirArg('includedir', 'install_headers')
3327 if subdir is not None:
3329 n = env.Install(dir, nodes)
3330 env.Alias('install', env.Alias('install_headers', n))
3333 def PublishLibrary(env, nodes):
3334 env.Alias('build_lib', nodes)
3336 if ('install' in COMMAND_LINE_TARGETS or
3337 'install_lib' in COMMAND_LINE_TARGETS):
3338 dir = env.GetAbsDirArg('libdir', 'install_lib')
3339 n = env.Install(dir, nodes)
3340 env.Alias('install', env.Alias('install_lib', n))
3343 def NaClAddHeader(env, nodes, subdir='nacl'):
3344 n = AddHeaderInternal(env, nodes, subdir)
3345 PublishHeader(env, n, subdir)
3347 nacl_env.AddMethod(NaClAddHeader, 'AddHeaderToSdk')
3349 def NaClAddLibrary(env, nodes):
3350 nodes = env.Replicate('${LIB_DIR}', nodes)
3351 PublishLibrary(env, nodes)
3353 nacl_env.AddMethod(NaClAddLibrary, 'AddLibraryToSdk')
3355 def NaClAddObject(env, nodes):
3356 lib_nodes = env.Replicate('${LIB_DIR}', nodes)
3357 PublishLibrary(env, lib_nodes)
3359 nacl_env.AddMethod(NaClAddObject, 'AddObjectToSdk')
3361 # We want to do this for nacl_env when not under --nacl_glibc,
3362 # but for nacl_irt_env whether or not under --nacl_glibc, so
3363 # we do it separately for each after making nacl_irt_env and
3364 # clearing its Bit('nacl_glibc').
3365 def AddImplicitLibs(env):
3368 # Require the pnacl_irt_shim for pnacl x86-64 and arm.
3369 # Use -B to have the compiler look for the fresh libpnacl_irt_shim.a.
3370 if ( env.Bit('bitcode') and
3371 (env.Bit('target_x86_64') or env.Bit('target_arm'))
3372 and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT'):
3373 # Note: without this hack ibpnacl_irt_shim.a will be deleted
3374 # when "built_elsewhere=1"
3375 # Since we force the build in a previous step the dependency
3376 # is not really needed.
3377 # Note: the "precious" mechanism did not work in this case
3378 if not env.Bit('built_elsewhere'):
3379 if env.Bit('enable_chrome_side'):
3380 implicit_libs += ['libpnacl_irt_shim.a']
3382 if not env.Bit('nacl_glibc'):
3383 # These are automatically linked in by the compiler, either directly
3384 # or via the linker script that is -lc. In the non-glibc build, we
3385 # are the ones providing these files, so we need dependencies.
3386 # The ComponentProgram method (site_scons/site_tools/component_builders.py)
3387 # adds dependencies on env['IMPLICIT_LIBS'] if that's set.
3388 if env.Bit('bitcode'):
3389 implicit_libs += ['libnacl.a']
3391 implicit_libs += ['crt1.o',
3395 # TODO(mcgrathr): multilib nonsense defeats -B! figure out a better way.
3396 if GetTargetPlatform() == 'x86-32':
3397 implicit_libs.append(os.path.join('32', 'crt1.o'))
3399 if implicit_libs != []:
3400 env['IMPLICIT_LIBS'] = [env.File(os.path.join('${LIB_DIR}', file))
3401 for file in implicit_libs]
3402 # The -B<dir>/ flag is necessary to tell gcc to look for crt[1in].o there.
3403 env.Prepend(LINKFLAGS=['-B${LIB_DIR}/'])
3405 AddImplicitLibs(nacl_env)
3406 AddImplicitLibs(nacl_irt_env)
3408 nacl_irt_env.Append(
3409 BUILD_SCONSCRIPTS = [
3410 'src/shared/gio/nacl.scons',
3411 'src/shared/platform/nacl.scons',
3412 'src/shared/srpc/nacl.scons',
3413 'src/tools/tls_edit/build.scons',
3414 'src/untrusted/irt/nacl.scons',
3415 'src/untrusted/nacl/nacl.scons',
3416 'src/untrusted/stubs/nacl.scons',
3417 'tests/irt_private_pthread/nacl.scons',
3419 nacl_irt_env.AddChromeFilesFromGroup('untrusted_irt_scons_files')
3421 environment_list.append(nacl_irt_env)
3423 # Since browser_tests already use the IRT normally, those are fully covered
3424 # in nacl_env. But the non_browser_tests don't use the IRT in nacl_env.
3425 # We want additional variants of those tests with the IRT, so we make
3426 # another environment and repeat them with that adjustment.
3427 nacl_irt_test_env = nacl_env.Clone(
3428 BUILD_TYPE = 'nacl_irt_test',
3429 BUILD_TYPE_DESCRIPTION = 'NaCl tests build with IRT',
3430 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT_TESTS',
3432 INCLUDE_DIR = nacl_env.Dir('${INCLUDE_DIR}'),
3433 LIB_DIR = nacl_env.Dir('${LIB_DIR}'),
3434 BUILD_SCONSCRIPTS = [],
3436 nacl_irt_test_env.SetBits('tests_use_irt')
3437 if nacl_irt_test_env.Bit('enable_chrome_side'):
3438 nacl_irt_test_env.Replace(TESTRUNNER_LIBS=['testrunner_browser'])
3440 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3441 nacl_irt_test_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3442 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_only_tests)
3443 TestsUsePublicLibs(nacl_irt_test_env)
3444 TestsUsePublicListMappingsLib(nacl_irt_test_env)
3446 # If a tests/.../nacl.scons file builds a library, we will just use
3447 # the one already built in nacl_env instead.
3448 def IrtTestDummyLibrary(*args, **kwargs):
3450 nacl_irt_test_env.AddMethod(IrtTestDummyLibrary, 'ComponentLibrary')
3452 def IrtTestAddNodeToTestSuite(env, node, suite_name, node_name=None,
3453 is_broken=False, is_flaky=False,
3454 disable_irt_suffix=False):
3455 # The disable_irt_suffix argument is there for allowing tests
3456 # defined in nacl_irt_test_env to be part of chrome_browser_tests
3457 # (rather than part of chrome_browser_tests_irt).
3458 # TODO(mseaborn): But really, all of chrome_browser_tests should be
3459 # placed in nacl_irt_test_env rather than in nacl_env.
3460 if not disable_irt_suffix:
3461 if node_name is not None:
3463 suite_name = [name + '_irt' for name in suite_name]
3464 # NOTE: This needs to be called directly to as we're overriding the
3466 return AddNodeToTestSuite(env, node, suite_name, node_name,
3467 is_broken, is_flaky)
3468 nacl_irt_test_env.AddMethod(IrtTestAddNodeToTestSuite, 'AddNodeToTestSuite')
3470 environment_list.append(nacl_irt_test_env)
3473 windows_coverage_env = windows_debug_env.Clone(
3474 tools = ['code_coverage'],
3475 BUILD_TYPE = 'coverage-win',
3476 BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
3477 # TODO(bradnelson): switch nacl to common testing process so this won't be
3479 MANIFEST_FILE = None,
3480 COVERAGE_ANALYZER_DIR=r'..\third_party\coverage_analyzer\bin',
3481 COVERAGE_ANALYZER='$COVERAGE_ANALYZER_DIR\coverage_analyzer.exe',
3483 # TODO(bradnelson): Switch nacl to common testing process so this won't be
3484 # needed. Ignoring instrumentation failure as that's easier
3485 # than trying to gate out the ones with asm we can't handle.
3486 windows_coverage_env['LINKCOM'] = windows_coverage_env.Action([
3487 windows_coverage_env.get('LINKCOM', []),
3488 '-$COVERAGE_VSINSTR /COVERAGE ${TARGET}'])
3489 windows_coverage_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
3490 AddDualLibrary(windows_coverage_env)
3491 environment_list.append(windows_coverage_env)
3493 mac_coverage_env = mac_debug_env.Clone(
3494 tools = ['code_coverage'],
3495 BUILD_TYPE = 'coverage-mac',
3496 BUILD_TYPE_DESCRIPTION = 'MacOS code coverage build',
3497 # Strict doesnt't currently work for coverage because the path to gcov is
3498 # magically baked into the compiler.
3499 LIBS_STRICT = False,
3501 AddDualLibrary(mac_coverage_env)
3502 environment_list.append(mac_coverage_env)
3504 linux_coverage_env = linux_debug_env.Clone(
3505 tools = ['code_coverage'],
3506 BUILD_TYPE = 'coverage-linux',
3507 BUILD_TYPE_DESCRIPTION = 'Linux code coverage build',
3508 # Strict doesnt't currently work for coverage because the path to gcov is
3509 # magically baked into the compiler.
3510 LIBS_STRICT = False,
3513 linux_coverage_env.FilterOut(CCFLAGS=['-fPIE'])
3514 linux_coverage_env.Append(CCFLAGS=['-fPIC'])
3516 linux_coverage_env['OPTIONAL_COVERAGE_LIBS'] = '$COVERAGE_LIBS'
3517 AddDualLibrary(linux_coverage_env)
3518 environment_list.append(linux_coverage_env)
3521 # Environment Massaging
3522 RELEVANT_CONFIG = ['NACL_BUILD_FAMILY',
3526 'BUILD_TYPE_DESCRIPTION',
3529 MAYBE_RELEVANT_CONFIG = ['BUILD_OS',
3530 'BUILD_ARCHITECTURE',
3533 'TARGET_ARCHITECTURE',
3537 def DumpCompilerVersion(cc, env):
3539 env.Execute(env.Action('set'))
3540 env.Execute(env.Action('${CC} -v -c'))
3541 env.Execute(env.Action('${CC} -print-search-dirs'))
3542 env.Execute(env.Action('${CC} -print-libgcc-file-name'))
3543 elif cc.startswith('cl'):
3546 p = subprocess.Popen(env.subst('${CC} /V'),
3548 stdout=subprocess.PIPE,
3549 stderr=subprocess.PIPE)
3550 stdout, stderr = p.communicate()
3551 print stderr[0:stderr.find("\r")]
3552 except WindowsError:
3553 # If vcvars was not run before running SCons, we won't be able to find
3554 # the compiler at this point. SCons has built in functions for finding
3555 # the compiler, but they haven't run yet.
3556 print 'Can not find the compiler, assuming SCons will find it later.'
3558 print "UNKNOWN COMPILER"
3561 def SanityCheckEnvironments(all_envs):
3562 # simple completeness check
3563 for env in all_envs:
3564 for tag in RELEVANT_CONFIG:
3565 assert tag in env, repr(tag)
3566 assert env[tag], repr(env[tag])
3569 def LinkTrustedEnv(selected_envs):
3570 # Collect build families and ensure that we have only one env per family.
3572 for env in selected_envs:
3573 family = env['NACL_BUILD_FAMILY']
3574 if family not in family_map:
3575 family_map[family] = env
3577 msg = 'You are using incompatible environments simultaneously\n'
3578 msg += '%s vs %s\n' % (env['BUILD_TYPE'],
3579 family_map[family]['BUILD_TYPE'])
3580 msg += ('Please specfy the exact environments you require, e.g. '
3581 'MODE=dbg-host,nacl')
3582 raise Exception(msg)
3584 # Set TRUSTED_ENV so that tests of untrusted code can locate sel_ldr
3585 # etc. We set this on trusted envs too because some tests on
3586 # trusted envs run sel_ldr (e.g. using checked-in binaries).
3587 if 'TRUSTED' in family_map:
3588 for env in selected_envs:
3589 env['TRUSTED_ENV'] = family_map['TRUSTED']
3590 # Propagate some environment variables from the trusted environment,
3591 # in case some (e.g. Mac's DYLD_LIBRARY_PATH) are necessary for
3592 # running sel_ldr et al in untrusted environments' tests.
3593 for var in env['TRUSTED_ENV'].get('PROPAGATE_ENV', []):
3594 env['ENV'][var] = env['TRUSTED_ENV']['ENV'][var]
3595 if 'TRUSTED' not in family_map or 'UNTRUSTED' not in family_map:
3596 Banner('Warning: "--mode" did not specify both trusted and untrusted '
3597 'build environments. As a result, many tests will not be run.')
3600 build_platform = GetBuildPlatform()
3602 # Build Platform Base Function
3603 platform_func_map = {
3604 'win32' : MakeWindowsEnv,
3605 'cygwin': MakeWindowsEnv,
3606 'linux' : MakeLinuxEnv,
3607 'linux2': MakeLinuxEnv,
3608 'darwin': MakeMacEnv,
3610 if sys.platform not in platform_func_map:
3611 raise UserError('Unrecognized host platform: %s', sys.platform)
3612 make_env_func = platform_func_map[sys.platform]
3614 build_env = make_env_func(build_platform)
3615 build_env['IS_BUILD_ENV'] = True
3617 # Building tls_edit depends on gio, platform, and validator_ragel.
3618 build_env['BUILD_SCONSCRIPTS'] = [
3619 # KEEP THIS SORTED PLEASE
3620 'src/shared/gio/build.scons',
3621 'src/shared/platform/build.scons',
3622 'src/trusted/validator_ragel/build.scons',
3625 # The build environment is only used for intermediate steps and should
3626 # not be creating any targets. Aliases are used as means to add targets
3627 # to builds (IE, all_programs, all_libraries...etc.). Since we want to
3628 # share all of our build scripts but not define any aliases, we should
3629 # override the alias function and essentially stub it out.
3630 build_env.Alias = lambda env, target, source=[], actions=None, **kw : []
3634 def LinkBuildEnv(selected_envs):
3636 'opt': opt_build_env,
3637 'dbg': dbg_build_env,
3640 # We need to find the optimization level in order to know which
3641 # build environment we want to use
3643 for env in selected_envs:
3644 if env.get('OPTIMIZATION_LEVEL', None):
3645 opt_level = env['OPTIMIZATION_LEVEL']
3648 build_env = build_env_map.get(opt_level, opt_build_env)
3649 for env in selected_envs:
3650 env['BUILD_ENV'] = build_env
3652 # If the build environment is different from all the selected environments,
3653 # we will need to also append it to the selected environments so the targets
3655 build_env_root = build_env.subst('${TARGET_ROOT}')
3656 for env in selected_envs:
3657 if build_env_root == env.subst('${TARGET_ROOT}'):
3660 # Did not find a matching environment, append the build environment now.
3661 selected_envs.append(build_env)
3663 def DumpEnvironmentInfo(selected_envs):
3664 if VerboseConfigInfo(pre_base_env):
3665 Banner("The following environments have been configured")
3666 for env in selected_envs:
3667 for tag in RELEVANT_CONFIG:
3668 assert tag in env, repr(tag)
3669 print "%s: %s" % (tag, env.subst(env.get(tag)))
3670 for tag in MAYBE_RELEVANT_CONFIG:
3671 print "%s: %s" % (tag, env.subst(env.get(tag)))
3672 cc = env.subst('${CC}')
3674 asppcom = env.subst('${ASPPCOM}')
3675 print 'ASPPCOM:', asppcom
3676 DumpCompilerVersion(cc, env)
3678 rev_file = 'toolchain/pnacl_linux_x86/REV'
3679 if os.path.exists(rev_file):
3680 for line in open(rev_file).read().split('\n'):
3681 if "Revision:" in line:
3682 print "PNACL : %s" % line
3684 def PnaclSetEmulatorForSandboxedTranslator(selected_envs):
3685 # Slip in emulator flags if necessary, for the sandboxed pnacl translator
3686 # on ARM, once emulator is actually known (vs in naclsdk.py, where it
3687 # is not yet known).
3688 for env in selected_envs:
3689 if (env.Bit('bitcode')
3690 and env.Bit('use_sandboxed_translator')
3691 and env.UsingEmulator()):
3692 # This must modify the LINK command itself, since LINKFLAGS may
3693 # be filtered (e.g., in barebones tests).
3694 env.Append(LINK=' --pnacl-use-emulator')
3695 env.Append(TRANSLATE=' --pnacl-use-emulator')
3698 # Blank out defaults.
3701 # Apply optional supplement if present in the directory tree.
3702 if os.path.exists(pre_base_env.subst('$MAIN_DIR/supplement/supplement.scons')):
3703 SConscript('supplement/supplement.scons', exports=['environment_list'])
3705 # print sytem info (optionally)
3706 if VerboseConfigInfo(pre_base_env):
3707 Banner('SCONS ARGS:' + str(sys.argv))
3708 os.system(pre_base_env.subst('${PYTHON} tools/sysinfo.py'))
3712 SanityCheckEnvironments(environment_list)
3713 selected_envs = FilterEnvironments(environment_list)
3715 # If we are building NaCl, build nacl_irt too. This works around it being
3716 # a separate mode due to the vagaries of scons when we'd really rather it
3717 # not be, while not requiring that every bot command line using --mode be
3718 # changed to list '...,nacl,nacl_irt' explicitly.
3719 if nacl_env in selected_envs:
3720 selected_envs.append(nacl_irt_env)
3722 # The nacl_irt_test_env requires nacl_env to build things correctly.
3723 if nacl_irt_test_env in selected_envs and nacl_env not in selected_envs:
3724 selected_envs.append(nacl_env)
3726 DumpEnvironmentInfo(selected_envs)
3727 LinkTrustedEnv(selected_envs)
3729 # When building NaCl, any intermediate build tool that is used during the
3730 # build process must be built using the current build environment, not the
3731 # target. Create a build environment for this purpose and link it into
3732 # the selected environments
3733 dbg_build_env, opt_build_env = GenerateOptimizationLevels(MakeBuildEnv())
3734 LinkBuildEnv(selected_envs)
3736 # This must happen after LinkTrustedEnv, since that is where TRUSTED_ENV
3737 # is finally set, and env.UsingEmulator() checks TRUSTED_ENV for the emulator.
3738 # This must also happen before BuildEnvironments.
3739 PnaclSetEmulatorForSandboxedTranslator(selected_envs)
3741 BuildEnvironments(selected_envs)
3743 # Change default to build everything, but not run tests.
3744 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
3747 # Sanity check whether we are ready to build nacl modules
3748 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3749 if nacl_env.Bit('naclsdk_validate') and (nacl_env in selected_envs or
3750 nacl_irt_env in selected_envs):
3751 nacl_env.ValidateSdk()
3753 if BROKEN_TEST_COUNT > 0:
3754 msg = "There are %d broken tests." % BROKEN_TEST_COUNT
3755 if GetOption('brief_comstr'):
3756 msg += " Add --verbose to the command line for more information."
3759 # separate warnings from actual build output
3760 Banner('B U I L D - O U T P U T:')