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 toolchain to use. The default toolchain will be
190 # a combination of the other arguments. Example toolchains:
191 # NaCl (newlib): nacl_PLATFORM_newlib
192 # NaCl (glibc): nacl_PLATFORM_glibc
193 # pnacl: pnacl_PLATFORM
195 # Allows overriding the version number in the toolchain's
196 # FEATURE_VERSION file. This is used for PNaCl ABI compatibility
198 'toolchain_feature_version',
202 # Overly general to provide compatibility with existing build bots, etc.
203 # In the future it might be worth restricting the values that are accepted.
204 _TRUE_STRINGS = set(['1', 'true', 'yes'])
205 _FALSE_STRINGS = set(['0', 'false', 'no'])
208 # Converts a string representing a Boolean value, of some sort, into an actual
209 # Boolean value. Python's built in type coercion does not work because
210 # bool('False') == True
211 def StringValueToBoolean(value):
212 # ExpandArguments may stick non-string values in ARGUMENTS. Be accommodating.
213 if isinstance(value, bool):
216 if not isinstance(value, basestring):
217 raise Exception("Expecting a string but got a %s" % repr(type(value)))
219 if value.lower() in _TRUE_STRINGS:
221 elif value.lower() in _FALSE_STRINGS:
224 raise Exception("Cannot convert '%s' to a Boolean value" % value)
227 def GetBinaryArgumentValue(arg_name, default):
228 if not isinstance(default, bool):
229 raise Exception("Default value for '%s' must be a Boolean" % arg_name)
230 if arg_name not in ARGUMENTS:
232 return StringValueToBoolean(ARGUMENTS[arg_name])
235 # name is the name of the bit
236 # arg_name is the name of the command-line argument, if it differs from the bit
237 def BitFromArgument(env, name, default, desc, arg_name=None):
238 # In most cases the bit name matches the argument name
242 DeclareBit(name, desc)
243 assert arg_name not in ACCEPTABLE_ARGUMENTS, repr(arg_name)
244 ACCEPTABLE_ARGUMENTS.add(arg_name)
246 if GetBinaryArgumentValue(arg_name, default):
252 # SetUpArgumentBits declares binary command-line arguments and converts them to
253 # bits. For example, one of the existing declarations would result in the
254 # argument "bitcode=1" causing env.Bit('bitcode') to evaluate to true.
255 # NOTE Command-line arguments are a SCons-ism that is separate from
256 # command-line options. Options are prefixed by "-" or "--" whereas arguments
257 # are not. The function SetBitFromOption can be used for options.
258 # NOTE This function must be called before the bits are used
259 # NOTE This function must be called after all modifications of ARGUMENTS have
260 # been performed. See: ExpandArguments
261 def SetUpArgumentBits(env):
262 BitFromArgument(env, 'bitcode', default=False,
263 desc='We are building bitcode')
265 BitFromArgument(env, 'translate_fast', default=False,
266 desc='When using pnacl TC (bitcode=1) use accelerated translation step')
268 BitFromArgument(env, 'built_elsewhere', default=False,
269 desc='The programs have already been built by another system')
271 BitFromArgument(env, 'skip_trusted_tests', default=False,
272 desc='Only run untrusted tests - useful for translator testing'
273 ' (also skips tests of the IRT itself')
275 BitFromArgument(env, 'nacl_pic', default=False,
276 desc='generate position indepent code for (P)NaCl modules')
278 BitFromArgument(env, 'nacl_static_link', default=not env.Bit('nacl_glibc'),
279 desc='Whether to use static linking instead of dynamic linking '
280 'for building NaCl executables during tests. '
281 'For nacl-newlib, the default is 1 (static linking). '
282 'For nacl-glibc, the default is 0 (dynamic linking).')
284 BitFromArgument(env, 'nacl_disable_shared', default=not env.Bit('nacl_glibc'),
285 desc='Do not build shared versions of libraries. '
286 'For nacl-newlib, the default is 1 (static libraries only). '
287 'For nacl-glibc, the default is 0 (both static and shared libraries).')
289 # Defaults on when --verbose is specified.
290 # --verbose sets 'brief_comstr' to False, so this looks a little strange
291 BitFromArgument(env, 'target_stats', default=not GetOption('brief_comstr'),
292 desc='Collect and display information about which commands are executed '
293 'during the build process')
295 BitFromArgument(env, 'werror', default=True,
296 desc='Treat warnings as errors (-Werror)')
298 BitFromArgument(env, 'disable_nosys_linker_warnings', default=False,
299 desc='Disable warning mechanism in src/untrusted/nosys/warning.h')
301 BitFromArgument(env, 'naclsdk_validate', default=True,
302 desc='Verify the presence of the SDK')
304 BitFromArgument(env, 'running_on_valgrind', default=False,
305 desc='Compile and test using valgrind')
307 BitFromArgument(env, 'enable_tmpfs_redirect_var', default=False,
308 desc='Allow redirecting tmpfs location for shared memory '
309 '(by default, /dev/shm is used)')
311 BitFromArgument(env, 'pp', default=False,
312 desc='Enable pretty printing')
314 # Defaults on when --verbose is specified
315 # --verbose sets 'brief_comstr' to False, so this looks a little strange
316 BitFromArgument(env, 'sysinfo', default=not GetOption('brief_comstr'),
317 desc='Print verbose system information')
319 BitFromArgument(env, 'disable_flaky_tests', default=False,
320 desc='Do not run potentially flaky tests - used on Chrome bots')
322 BitFromArgument(env, 'use_sandboxed_translator', default=False,
323 desc='use pnacl sandboxed translator for linking (not available for arm)')
325 BitFromArgument(env, 'pnacl_generate_pexe', default=env.Bit('bitcode'),
326 desc='use pnacl to generate pexes and translate in a separate step')
328 BitFromArgument(env, 'translate_in_build_step', default=True,
329 desc='Run translation during build phase (e.g. if do_not_run_tests=1)')
331 BitFromArgument(env, 'pnacl_unsandboxed', default=False,
332 desc='Translate pexe to an unsandboxed, host executable')
334 BitFromArgument(env, 'browser_headless', default=False,
335 desc='Where possible, set up a dummy display to run the browser on '
336 'when running browser tests. On Linux, this runs the browser through '
337 'xvfb-run. This Scons does not need to be run with an X11 display '
338 'and we do not open a browser window on the user\'s desktop. '
339 'Unfortunately there is no equivalent on Mac OS X.')
341 BitFromArgument(env, 'disable_crash_dialog', default=True,
342 desc='Disable Windows\' crash dialog box, which Windows pops up when a '
343 'process exits with an unhandled fault. Windows enables this by '
344 'default for processes launched from the command line or from the '
345 'GUI. Our default is to disable it, because the dialog turns crashes '
346 'into hangs on Buildbot, and our test suite includes various crash '
349 BitFromArgument(env, 'do_not_run_tests', default=False,
350 desc='Prevents tests from running. This lets SCons build the files needed '
351 'to run the specified test(s) without actually running them. This '
352 'argument is a counterpart to built_elsewhere.')
354 BitFromArgument(env, 'validator_ragel', default=True,
355 desc='Use the R-DFA validator instead of the original validators.')
357 # TODO(shcherbina): add support for other golden-based tests, not only
358 # run_x86_*_validator_testdata_tests.
359 BitFromArgument(env, 'regenerate_golden', default=False,
360 desc='When running golden-based tests, instead of comparing results '
361 'save actual output as golden data.')
363 BitFromArgument(env, 'x86_64_zero_based_sandbox', default=False,
364 desc='Use the zero-address-based x86-64 sandbox model instead of '
365 'the r15-based model.')
367 BitFromArgument(env, 'android', default=False,
368 desc='Build for Android target')
370 BitFromArgument(env, 'arm_hard_float', default=True,
371 desc='Build for hard float ARM ABI')
373 BitFromArgument(env, 'skip_nonstable_bitcode', default=False,
374 desc='Skip tests involving non-stable bitcode')
376 #########################################################################
378 # This is for generating a testing library for use within private test
379 # enuminsts, where we want to compare and test different validators.
381 BitFromArgument(env, 'ncval_testing', default=False,
382 desc='EXPERIMENTAL: Compile validator code for testing within enuminsts')
384 # PNaCl sanity checks
385 if ((env.Bit('pnacl_generate_pexe') or env.Bit('use_sandboxed_translator'))
386 and not env.Bit('bitcode')):
387 raise UserError("pnacl_generate_pexe and use_sandboxed_translator"
388 " don't make sense without bitcode")
390 # Sandboxed translator only accepts stable bitcode. Hence we must disallow
391 # nonstable bitcodes.
392 if env.Bit('use_sandboxed_translator'):
393 env.SetBits('skip_nonstable_bitcode')
395 def CheckArguments():
396 for key in ARGUMENTS:
397 if key not in ACCEPTABLE_ARGUMENTS:
398 raise UserError('bad argument: %s' % key)
401 # Sets a command line argument. Dies if an argument with this name is already
403 def SetArgument(key, value):
404 print ' %s=%s' % (key, str(value))
406 raise UserError('ERROR: %s redefined' % (key, ))
407 ARGUMENTS[key] = value
409 # Expands "macro" command line arguments.
410 def ExpandArguments():
411 if ARGUMENTS.get('buildbot') == 'memcheck':
412 print 'buildbot=memcheck expands to the following arguments:'
413 SetArgument('run_under',
414 ARGUMENTS.get('memcheck_command',
415 'src/third_party/valgrind/memcheck.sh') +
416 ',--error-exitcode=1')
417 SetArgument('scale_timeout', 20)
418 SetArgument('running_on_valgrind', True)
419 elif ARGUMENTS.get('buildbot') == 'tsan':
420 print 'buildbot=tsan expands to the following arguments:'
421 SetArgument('run_under',
422 ARGUMENTS.get('tsan_command',
423 'src/third_party/valgrind/tsan.sh') +
424 ',--nacl-untrusted,--error-exitcode=1,' +
425 '--suppressions=src/third_party/valgrind/tests.supp')
426 SetArgument('scale_timeout', 20)
427 SetArgument('running_on_valgrind', True)
428 elif ARGUMENTS.get('buildbot') == 'tsan-trusted':
429 print 'buildbot=tsan-trusted expands to the following arguments:'
430 SetArgument('run_under',
431 ARGUMENTS.get('tsan_command',
432 'src/third_party/valgrind/tsan.sh') +
433 ',--error-exitcode=1,' +
434 '--suppressions=src/third_party/valgrind/tests.supp')
435 SetArgument('scale_timeout', 20)
436 SetArgument('running_on_valgrind', True)
437 elif ARGUMENTS.get('buildbot') == 'memcheck-browser-tests':
438 print 'buildbot=memcheck-browser-tests expands to the following arguments:'
439 SetArgument('browser_test_tool', 'memcheck')
440 SetArgument('scale_timeout', 20)
441 SetArgument('running_on_valgrind', True)
442 elif ARGUMENTS.get('buildbot') == 'tsan-browser-tests':
443 print 'buildbot=tsan-browser-tests expands to the following arguments:'
444 SetArgument('browser_test_tool', 'tsan')
445 SetArgument('scale_timeout', 20)
446 SetArgument('running_on_valgrind', True)
447 elif ARGUMENTS.get('buildbot'):
448 raise UserError('ERROR: unexpected argument buildbot="%s"' % (
449 ARGUMENTS.get('buildbot'), ))
453 def GetTargetPlatform():
454 return pynacl.platform.GetArch3264(ARGUMENTS.get('platform', 'x86-32'))
456 def GetBuildPlatform():
457 return pynacl.platform.GetArch3264()
460 environment_list = []
462 # Base environment for both nacl and non-nacl variants.
464 if ARGUMENTS.get('DESTINATION_ROOT') is not None:
465 kwargs['DESTINATION_ROOT'] = ARGUMENTS.get('DESTINATION_ROOT')
466 pre_base_env = Environment(
467 # Use the environment that scons was run in to run scons invoked commands.
468 # This allows in things like externally provided PATH, PYTHONPATH.
469 ENV = os.environ.copy(),
470 tools = ['component_setup'],
471 # SOURCE_ROOT is one leave above the native_client directory.
472 SOURCE_ROOT = Dir('#/..').abspath,
473 # Publish dlls as final products (to staging).
474 COMPONENT_LIBRARY_PUBLISH = True,
476 # Use workaround in special scons version.
478 LIBS_DO_SUBST = True,
480 # Select where to find coverage tools.
481 COVERAGE_MCOV = '../third_party/lcov/bin/mcov',
482 COVERAGE_GENHTML = '../third_party/lcov/bin/genhtml',
487 breakpad_tools_dir = ARGUMENTS.get('breakpad_tools_dir')
488 if breakpad_tools_dir is not None:
489 pre_base_env['BREAKPAD_TOOLS_DIR'] = pre_base_env.Dir(
490 os.path.abspath(breakpad_tools_dir))
494 DeclareBit('clang', 'Use clang to build trusted code')
495 pre_base_env.SetBitFromOption('clang', False)
498 'Use AddressSanitizer to build trusted code (implies --clang)')
499 pre_base_env.SetBitFromOption('asan', False)
500 if pre_base_env.Bit('asan'):
501 pre_base_env.SetBits('clang')
505 DeclareBit('coverage_enabled', 'The build should be instrumented to generate'
506 'coverage information')
508 # If the environment variable BUILDBOT_BUILDERNAME is set, we can determine
509 # if we are running in a VM by the lack of a '-bare-' (aka bare metal) in the
510 # bot name. Otherwise if the builder name is not set, then assume real HW.
511 DeclareBit('running_on_vm', 'Returns true when environment is running in a VM')
512 builder = os.environ.get('BUILDBOT_BUILDERNAME')
513 if builder and builder.find('-bare-') == -1:
514 pre_base_env.SetBits('running_on_vm')
516 pre_base_env.ClearBits('running_on_vm')
518 DeclareBit('nacl_glibc', 'Use nacl-glibc for building untrusted code')
519 pre_base_env.SetBitFromOption('nacl_glibc', False)
521 # This function should be called ASAP after the environment is created, but
522 # after ExpandArguments.
523 SetUpArgumentBits(pre_base_env)
525 # Register PrintFinalReport only after SetUpArgumentBits since it references
526 # bits that get declared in SetUpArgumentBits
527 atexit.register(PrintFinalReport)
529 def DisableCrashDialog():
530 if sys.platform == 'win32':
533 # The double call is to preserve existing flags, as discussed at
534 # http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
535 new_flags = win32con.SEM_NOGPFAULTERRORBOX
536 existing_flags = win32api.SetErrorMode(new_flags)
537 win32api.SetErrorMode(existing_flags | new_flags)
539 if pre_base_env.Bit('disable_crash_dialog'):
542 # We want to pull CYGWIN setup in our environment or at least set flag
543 # nodosfilewarning. It does not do anything when CYGWIN is not involved
544 # so let's do it in all cases.
545 pre_base_env['ENV']['CYGWIN'] = os.environ.get('CYGWIN', 'nodosfilewarning')
547 # Note: QEMU_PREFIX_HOOK may influence test runs and sb translator invocations
548 pre_base_env['ENV']['QEMU_PREFIX_HOOK'] = os.environ.get('QEMU_PREFIX_HOOK', '')
550 # Allow the zero-based sandbox model to run insecurely.
551 # TODO(arbenson): remove this once binutils bug is fixed (see
552 # src/trusted/service_runtime/arch/x86_64/sel_addrspace_posix_x86_64.c)
553 if pre_base_env.Bit('x86_64_zero_based_sandbox'):
554 pre_base_env['ENV']['NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX'] = 1
556 if pre_base_env.Bit('werror'):
557 werror_flags = ['-Werror']
561 # Allow variadic macros
562 werror_flags = werror_flags + ['-Wno-variadic-macros']
564 if pre_base_env.Bit('clang'):
565 # Allow 'default' label in switch even when all enumeration cases
567 werror_flags += ['-Wno-covered-switch-default']
568 # Allow C++11 extensions (for "override")
569 werror_flags += ['-Wno-c++11-extensions']
572 # Method to make sure -pedantic, etc, are not stripped from the
573 # default env, since occasionally an engineer will be tempted down the
574 # dark -- but wide and well-trodden -- path of expediency and stray
575 # from the path of correctness.
577 def EnsureRequiredBuildWarnings(env):
578 if env.Bit('linux') or env.Bit('mac'):
579 required_env_flags = set(['-pedantic', '-Wall'] + werror_flags)
580 ccflags = set(env.get('CCFLAGS'))
582 if not required_env_flags.issubset(ccflags):
583 raise UserError('required build flags missing: '
584 + ' '.join(required_env_flags.difference(ccflags)))
586 # windows get a pass for now
589 pre_base_env.AddMethod(EnsureRequiredBuildWarnings)
591 # Expose MakeTempDir and MakeTempFile to scons scripts
592 pre_base_env.AddMethod(test_lib.MakeTempDir)
593 pre_base_env.AddMethod(test_lib.MakeTempFile)
595 # Method to add target suffix to name.
596 def NaClTargetArchSuffix(env, name):
597 return name + '_' + env['TARGET_FULLARCH'].replace('-', '_')
599 pre_base_env.AddMethod(NaClTargetArchSuffix)
602 # Generic Test Wrapper
604 # Add list of Flaky or Bad tests to skip per platform. A
605 # platform is defined as build type
606 # <BUILD_TYPE>-<SUBARCH>
611 # This is a list of tests that do not yet pass when using nacl-glibc.
612 # TODO(mseaborn): Enable more of these tests!
613 nacl_glibc_skiplist = set([
614 # Struct layouts differ.
616 # Syscall wrappers not implemented yet.
619 # Fails because clock() is not hooked up.
620 'run_timefuncs_test',
621 # Needs further investigation.
623 # run_srpc_sysv_shm_test fails because:
624 # 1) it uses fstat(), while we only have an fstat64() wrapper;
625 # 2) the test needs an explicit fflush(stdout) call because the
626 # process is killed without exit() being called.
627 'run_srpc_sysv_shm_test',
628 # This test fails with nacl-glibc: glibc reports an internal
629 # sanity check failure in free().
630 # TODO(robertm): This needs further investigation.
631 'run_ppapi_event_test',
632 'run_srpc_ro_file_test',
633 'run_ppapi_geturl_valid_test',
634 'run_ppapi_geturl_invalid_test',
635 # http://code.google.com/p/chromium/issues/detail?id=108131
636 # we would need to list all of the glibc components as
637 # web accessible resources in the extensions's manifest.json,
638 # not just the nexe and nmf file.
639 'run_ppapi_extension_mime_handler_browser_test',
641 nacl_glibc_skiplist.update(['%s_irt' % test for test in nacl_glibc_skiplist])
644 # If a test is not in one of these suites, it will probally not be run on a
645 # regular basis. These are the suites that will be run by the try bot or that
646 # a large number of users may run by hand.
647 MAJOR_TEST_SUITES = set([
651 # Tests using the pepper plugin, only run with chrome
652 # TODO(ncbray): migrate pepper_browser_tests to chrome_browser_tests
653 'pepper_browser_tests',
654 # Lightweight browser tests
655 'chrome_browser_tests',
657 'memcheck_bot_tests',
659 # Special testing environment for testing comparing x86 validators.
661 # Environment for validator difference testing
662 'validator_diff_tests',
665 # These are the test suites we know exist, but aren't run on a regular basis.
666 # These test suites are essentially shortcuts that run a specific subset of the
668 ACCEPTABLE_TEST_SUITES = set([
670 'dynamic_load_tests',
671 'eh_tests', # Tests for C++ exception handling
672 'exception_tests', # Tests for hardware exception handling
679 'sel_ldr_sled_tests',
682 'validator_modeling',
684 # Special testing of the decoder for the ARM validator.
688 # Under --mode=nacl_irt_test we build variants of numerous tests normally
689 # built under --mode=nacl. The test names and suite names for these
690 # variants are set (in IrtTestAddNodeToTestSuite, below) by appending _irt
691 # to the names used for the --mode=nacl version of the same tests.
692 MAJOR_TEST_SUITES |= set([name + '_irt'
693 for name in MAJOR_TEST_SUITES])
694 ACCEPTABLE_TEST_SUITES |= set([name + '_irt'
695 for name in ACCEPTABLE_TEST_SUITES])
697 # The major test suites are also acceptable names. Suite names are checked
698 # against this set in order to catch typos.
699 ACCEPTABLE_TEST_SUITES.update(MAJOR_TEST_SUITES)
702 def ValidateTestSuiteNames(suite_name, node_name):
703 if node_name is None:
704 node_name = '<unknown>'
706 # Prevent a silent failiure - strings are iterable!
707 if not isinstance(suite_name, (list, tuple)):
708 raise Exception("Test suites for %s should be specified as a list, "
709 "not as a %s: %s" % (node_name, type(suite_name).__name__,
713 raise Exception("No test suites are specified for %s. Set the 'broken' "
714 "parameter on AddNodeToTestSuite in the cases where there's a known "
715 "issue and you don't want the test to run" % (node_name,))
717 # Make sure each test is in at least one test suite we know will run
718 major_suites = set(suite_name).intersection(MAJOR_TEST_SUITES)
720 raise Exception("None of the test suites %s for %s are run on a "
721 "regular basis" % (repr(suite_name), node_name))
723 # Make sure a wierd test suite hasn't been inadvertantly specified
725 if s not in ACCEPTABLE_TEST_SUITES:
726 raise Exception("\"%s\" is not a known test suite. Either this is "
727 "a typo for %s, or it should be added to ACCEPTABLE_TEST_SUITES in "
728 "SConstruct" % (s, node_name))
730 BROKEN_TEST_COUNT = 0
733 def GetPlatformString(env):
734 build = env['BUILD_TYPE']
736 # If we are testing 'NACL' we really need the trusted info
737 if build=='nacl' and 'TRUSTED_ENV' in env:
738 trusted_env = env['TRUSTED_ENV']
739 build = trusted_env['BUILD_TYPE']
740 subarch = trusted_env['BUILD_SUBARCH']
742 subarch = env['BUILD_SUBARCH']
744 # Build the test platform string
745 return build + '-' + subarch
747 pre_base_env.AddMethod(GetPlatformString)
750 tests_to_disable_qemu = set([
751 # These tests do not work under QEMU but do work on ARM hardware.
753 # You should use the is_broken argument in preference to adding
754 # tests to this list.
756 # TODO(dschuff) some of these tests appear to work with the new QEMU.
758 # http://code.google.com/p/nativeclient/issues/detail?id=2437
759 # Note, for now these tests disable both the irt and non-irt variants
760 'run_atomic_ops_test', # still broken with qemu 2012/06/12
761 'run_atomic_ops_nexe_test',
762 'run_egyptian_cotton_test', # still broken with qemu 2012/06/12
763 'run_many_threads_sequential_test',
764 'run_mmap_atomicity_test', # still broken with qemu 2012/06/12
765 # http://code.google.com/p/nativeclient/issues/detail?id=2142
766 'run_nacl_semaphore_test',
767 'run_nacl_tls_unittest',
768 # subprocess needs to also have qemu prefix, which isn't supported
769 'run_subprocess_test',
770 # The next 2 tests seem flaky on QEMU
771 'run_srpc_manifest_file_test',
772 'run_srpc_message_untrusted_test',
773 'run_thread_stack_alloc_test',
774 'run_thread_suspension_test',
776 'run_dynamic_modify_test',
777 # qemu has bugs that make TestCatchingFault flaky (see
778 # http://code.google.com/p/nativeclient/issues/detail?id=3239), and
779 # we don't particularly need to measure performance under qemu.
780 'run_performance_test',
783 tests_to_disable = set()
784 if ARGUMENTS.get('disable_tests', '') != '':
785 tests_to_disable.update(ARGUMENTS['disable_tests'].split(','))
788 def ShouldSkipTest(env, node_name):
789 if (env.Bit('skip_trusted_tests')
790 and (env['NACL_BUILD_FAMILY'] == 'TRUSTED'
791 or env['NACL_BUILD_FAMILY'] == 'UNTRUSTED_IRT')):
794 if env.Bit('do_not_run_tests'):
795 # This hack is used for pnacl testing where we might build tests
796 # without running them on one bot and then transfer and run them on another.
797 # The skip logic only takes the first bot into account e.g. qemu
798 # restrictions, while it really should be skipping based on the second
799 # bot. By simply disabling the skipping completely we work around this.
802 # There are no known-to-fail tests any more, but this code is left
803 # in so that if/when we port to a new architecture or add a test
804 # that is known to fail on some platform(s), we can continue to have
805 # a central location to disable tests from running. NB: tests that
806 # don't *build* on some platforms need to be omitted in another way.
808 if node_name in tests_to_disable:
811 if env.UsingEmulator():
812 if node_name in tests_to_disable_qemu:
814 # For now also disable the irt variant
815 if node_name.endswith('_irt') and node_name[:-4] in tests_to_disable_qemu:
818 # Retrieve list of tests to skip on this platform
819 skiplist = bad_build_lists.get(env.GetPlatformString(), [])
820 if node_name in skiplist:
823 if env.Bit('nacl_glibc') and node_name in nacl_glibc_skiplist:
828 pre_base_env.AddMethod(ShouldSkipTest)
831 def AddNodeToTestSuite(env, node, suite_name, node_name, is_broken=False,
833 global BROKEN_TEST_COUNT
835 # CommandTest can return an empty list when it silently discards a test
839 assert node_name is not None
840 test_name_regex = r'run_.*_(unit)?test.*$'
841 assert re.match(test_name_regex, node_name), (
842 'test %r does not match "run_..._test" naming convention '
843 '(precise regex is %s)' % (node_name, test_name_regex))
845 ValidateTestSuiteNames(suite_name, node_name)
849 if is_broken or is_flaky and env.Bit('disable_flaky_tests'):
850 # Only print if --verbose is specified
851 if not GetOption('brief_comstr'):
852 print '*** BROKEN ', node_name
853 BROKEN_TEST_COUNT += 1
854 env.Alias('broken_tests', node)
855 elif env.ShouldSkipTest(node_name):
856 print '*** SKIPPING ', env.GetPlatformString(), ':', node_name
857 env.Alias('broken_tests', node)
859 env.Alias('all_tests', node)
865 env.ComponentTestOutput(node_name, node)
866 test_name = node_name
868 # This is rather shady, but the tests need a name without dots so they match
870 # TODO(ncbray) node_name should not be optional.
871 test_name = os.path.basename(str(node[0].path))
872 if test_name.endswith('.out'):
873 test_name = test_name[:-4]
874 test_name = test_name.replace('.', '_')
875 SetTestName(node, test_name)
877 pre_base_env.AddMethod(AddNodeToTestSuite)
880 def TestBindsFixedTcpPort(env, node):
881 # This tells Scons that tests that bind a fixed TCP port should not
882 # run concurrently, because they would interfere with each other.
883 # These tests are typically tests for NaCl's GDB debug stub. The
884 # dummy filename used below is an arbitrary token that just has to
885 # match across the tests.
886 SideEffect(env.File('${SCONSTRUCT_DIR}/test_binds_fixed_tcp_port'), node)
888 pre_base_env.AddMethod(TestBindsFixedTcpPort)
891 # Convenient testing aliases
892 # NOTE: work around for scons non-determinism in the following two lines
893 Alias('sel_ldr_sled_tests', [])
895 Alias('small_tests', [])
896 Alias('medium_tests', [])
897 Alias('large_tests', [])
899 Alias('small_tests_irt', [])
900 Alias('medium_tests_irt', [])
901 Alias('large_tests_irt', [])
903 Alias('pepper_browser_tests', [])
904 Alias('chrome_browser_tests', [])
906 Alias('unit_tests', 'small_tests')
907 Alias('smoke_tests', ['small_tests', 'medium_tests'])
909 if pre_base_env.Bit('nacl_glibc'):
910 Alias('memcheck_bot_tests', ['small_tests'])
911 Alias('tsan_bot_tests', ['small_tests'])
913 Alias('memcheck_bot_tests', ['small_tests', 'medium_tests', 'large_tests'])
914 Alias('tsan_bot_tests', [])
922 pre_base_env.AddMethod(Banner)
926 # Define the platforms, and use them to define the path for the
927 # scons-out directory (aka TARGET_ROOT)
929 # Various variables in the scons environment are related to this, e.g.
931 # BUILD_ARCH: (arm, mips, x86)
932 # BUILD_SUBARCH: (32, 64)
935 DeclareBit('build_x86_32', 'Building binaries for the x86-32 architecture',
936 exclusive_groups='build_arch')
937 DeclareBit('build_x86_64', 'Building binaries for the x86-64 architecture',
938 exclusive_groups='build_arch')
939 DeclareBit('build_mips32', 'Building binaries for the MIPS architecture',
940 exclusive_groups='build_arch')
941 DeclareBit('build_arm_arm', 'Building binaries for the ARM architecture',
942 exclusive_groups='build_arch')
943 DeclareBit('target_x86_32', 'Tools being built will process x86-32 binaries',
944 exclusive_groups='target_arch')
945 DeclareBit('target_x86_64', 'Tools being built will process x86-36 binaries',
946 exclusive_groups='target_arch')
947 DeclareBit('target_mips32', 'Tools being built will process MIPS binaries',
948 exclusive_groups='target_arch')
949 DeclareBit('target_arm_arm', 'Tools being built will process ARM binaries',
950 exclusive_groups='target_arch')
952 # Shorthand for either the 32 or 64 bit version of x86.
953 DeclareBit('build_x86', 'Building binaries for the x86 architecture')
954 DeclareBit('target_x86', 'Tools being built will process x86 binaries')
956 DeclareBit('build_arm', 'Building binaries for the arm architecture')
957 DeclareBit('target_arm', 'Tools being built will process arm binaries')
960 def MakeArchSpecificEnv(platform=None):
961 env = pre_base_env.Clone()
963 platform = GetTargetPlatform()
965 arch = pynacl.platform.GetArch(platform)
966 if pynacl.platform.IsArch64Bit(platform):
971 env.Replace(BUILD_FULLARCH=platform)
972 env.Replace(BUILD_ARCHITECTURE=arch)
973 env.Replace(BUILD_SUBARCH=subarch)
974 env.Replace(TARGET_FULLARCH=platform)
975 env.Replace(TARGET_ARCHITECTURE=arch)
976 env.Replace(TARGET_SUBARCH=subarch)
978 # Example: PlatformBit('build', 'x86-32') -> build_x86_32
979 def PlatformBit(prefix, platform):
980 return "%s_%s" % (prefix, platform.replace('-', '_'))
982 env.SetBits(PlatformBit('build', platform))
983 env.SetBits(PlatformBit('target', platform))
985 if env.Bit('build_x86_32') or env.Bit('build_x86_64'):
986 env.SetBits('build_x86')
987 if env.Bit('build_arm_arm'):
988 env.SetBits('build_arm')
990 if env.Bit('target_x86_32') or env.Bit('target_x86_64'):
991 env.SetBits('target_x86')
992 if env.Bit('target_arm_arm'):
993 env.SetBits('target_arm')
995 env.Replace(BUILD_ISA_NAME=platform)
997 if env.Bit('target_mips32'):
998 # This is a silent default on MIPS.
999 env.SetBits('bitcode')
1001 # Determine where the object files go
1002 env.Replace(BUILD_TARGET_NAME=platform)
1003 # This may be changed later; see target_variant_map, below.
1004 env.Replace(TARGET_VARIANT='')
1005 env.Replace(TARGET_ROOT=
1006 '${DESTINATION_ROOT}/${BUILD_TYPE}-${BUILD_TARGET_NAME}${TARGET_VARIANT}')
1011 pre_base_env.AddMethod(lambda self: ARGUMENTS.get('running_on_valgrind'),
1012 'IsRunningUnderValgrind')
1014 DeclareBit('with_leakcheck', 'Running under Valgrind leak checker')
1016 def RunningUnderLeakCheck():
1017 run_under = ARGUMENTS.get('run_under')
1019 extra_args = ARGUMENTS.get('run_under_extra_args')
1021 run_under += extra_args
1022 if run_under.find('leak-check=full') > 0:
1026 if RunningUnderLeakCheck():
1027 pre_base_env.SetBits('with_leakcheck')
1030 def HasSuffix(item, suffix):
1031 if isinstance(item, str):
1032 return item.endswith(suffix)
1033 elif hasattr(item, '__getitem__'):
1034 return HasSuffix(item[0], suffix)
1036 return item.path.endswith(suffix)
1039 def StripSuffix(string, suffix):
1040 assert string.endswith(suffix)
1041 return string[:-len(suffix)]
1044 def DualLibrary(env, lib_name, *args, **kwargs):
1045 """Builder to build both .a and _shared.a library in one step.
1048 env: Environment in which we were called.
1049 lib_name: Library name.
1050 args: Positional arguments.
1051 kwargs: Keyword arguments.
1053 static_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.os')]
1054 shared_objs = [i for i in Flatten(args[0]) if not HasSuffix(i, '.o')]
1055 # Built static library as ususal.
1056 env.ComponentLibrary(lib_name, static_objs, **kwargs)
1057 # For coverage bots, we only want one object file since two versions would
1058 # write conflicting information to the same .gdca/.gdna files.
1059 if env.Bit('coverage_enabled'): return
1060 # Build a static library using -fPIC for the .o's.
1061 if env.Bit('linux'):
1062 env_shared = env.Clone(OBJSUFFIX='.os')
1063 env_shared.Append(CCFLAGS=['-fPIC'])
1064 # -fPIE overrides -fPIC, and shared libraries should not be linked
1066 env_shared.FilterOut(CCFLAGS=['-fPIE'])
1067 env_shared.ComponentLibrary(lib_name + '_shared', shared_objs, **kwargs)
1068 # for arm trusted we usually build -static
1069 env_shared.FilterOut(LINKFLAGS=['-static'])
1071 def DualObject(env, *args, **kwargs):
1072 """Builder to build both .o and .os in one step.
1075 env: Environment in which we were called.
1076 args: Positional arguments.
1077 kwargs: Keyword arguments.
1079 # Built static library as ususal.
1080 ret = env.ComponentObject(*args, **kwargs)
1081 # For coverage bots, we only want one object file since two versions would
1082 # write conflicting information to the same .gdca/.gdna files.
1083 if env.Bit('coverage_enabled'): return ret
1084 # Build a static library using -fPIC for the .o's.
1085 if env.Bit('linux'):
1086 env_shared = env.Clone(OBJSUFFIX='.os')
1087 env_shared.Append(CCFLAGS=['-fPIC'])
1088 ret += env_shared.ComponentObject(*args, **kwargs)
1092 def AddDualLibrary(env):
1093 env.AddMethod(DualLibrary)
1094 env.AddMethod(DualObject)
1095 # For coverage bots we only build one set of objects and we always set
1096 # '-fPIC' so we do not need a "special" library.
1097 if env.Bit('coverage_enabled'):
1098 env['SHARED_LIBS_SPECIAL'] = False
1100 env['SHARED_LIBS_SPECIAL'] = env.Bit('linux')
1103 # In prebuild mode we ignore the dependencies so that stuff does
1104 # NOT get build again
1105 # Optionally ignore the build process.
1106 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
1107 pre_base_env.SetBitFromOption('prebuilt', False)
1110 # HELPERS FOR TEST INVOLVING TRUSTED AND UNTRUSTED ENV
1111 def GetEmulator(env):
1112 emulator = ARGUMENTS.get('force_emulator')
1113 if emulator is None and 'TRUSTED_ENV' in env:
1114 emulator = env['TRUSTED_ENV'].get('EMULATOR')
1117 pre_base_env.AddMethod(GetEmulator)
1119 def UsingEmulator(env):
1120 return bool(env.GetEmulator())
1122 pre_base_env.AddMethod(UsingEmulator)
1125 def GetValidator(env, validator):
1126 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1127 if 'TRUSTED_ENV' not in env:
1130 if validator is None:
1131 if env.Bit('build_arm'):
1132 validator = 'arm-ncval-core'
1133 elif env.Bit('build_mips32'):
1134 validator = 'mips-ncval-core'
1136 if env.Bit('validator_ragel'):
1137 validator = 'ncval_new'
1141 trusted_env = env['TRUSTED_ENV']
1142 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}%s${PROGSUFFIX}' %
1145 pre_base_env.AddMethod(GetValidator)
1148 # Perform os.path.abspath rooted at the directory SConstruct resides in.
1149 def SConstructAbsPath(env, path):
1150 return os.path.normpath(os.path.join(env['MAIN_DIR'], path))
1152 pre_base_env.AddMethod(SConstructAbsPath)
1155 def GetPlatformBuildTargetDir(env):
1156 # Currently we do not support any cross OS compiles, eventually the OS name
1157 # will probably be passed in through arguments.
1158 os_name = pynacl.platform.GetOS()
1160 # Currently 32/64 share the same tool build target directory. When we have
1161 # separate toolchains for each the architectures will probably have to use
1162 # the Arch3264() variant.
1163 build_arch = pynacl.platform.GetArch(GetBuildPlatform())
1165 return '%s_%s' % (os_name, build_arch)
1167 pre_base_env.AddMethod(GetPlatformBuildTargetDir)
1170 def GetToolchainName(env, target_arch=None, is_pnacl=None, lib_name=None):
1171 toolchain = ARGUMENTS.get('toolchain', None)
1172 if toolchain is None:
1173 if is_pnacl is None:
1174 is_pnacl = env.Bit('bitcode')
1175 if lib_name is None:
1176 if is_pnacl or not env.Bit('nacl_glibc'):
1181 build_arch = pynacl.platform.GetArch(GetBuildPlatform())
1182 if target_arch is None:
1183 target_arch = pynacl.platform.GetArch(GetTargetPlatform())
1186 target_env = 'pnacl'
1188 target_env = 'nacl_%s' % target_arch
1190 toolchain = '%s_%s' % (target_env, lib_name)
1194 pre_base_env.AddMethod(GetToolchainName)
1197 def GetToolchainDir(env, platform_build_dir=None, toolchain_name=None):
1198 if platform_build_dir is None:
1199 platform_build_dir = env.GetPlatformBuildTargetDir()
1200 if toolchain_name is None:
1201 toolchain_name = env.GetToolchainName()
1203 toolchain_sub_dir = os.path.join(
1208 return env.SConstructAbsPath(toolchain_sub_dir)
1210 pre_base_env.AddMethod(GetToolchainDir)
1214 sel_ldr = ARGUMENTS.get('force_sel_ldr')
1216 return env.File(env.SConstructAbsPath(sel_ldr))
1218 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1219 if 'TRUSTED_ENV' not in env:
1222 trusted_env = env['TRUSTED_ENV']
1223 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}sel_ldr${PROGSUFFIX}')
1225 pre_base_env.AddMethod(GetSelLdr)
1228 def GetSelLdrSeccomp(env):
1229 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1230 if 'TRUSTED_ENV' not in env:
1233 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1236 trusted_env = env['TRUSTED_ENV']
1237 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}'
1238 'sel_ldr_seccomp${PROGSUFFIX}')
1240 pre_base_env.AddMethod(GetSelLdrSeccomp)
1243 def SupportsSeccompBpfSandbox(env):
1244 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1247 # The gcov runtime does some extra calls (such as 'access') that
1248 # are not permitted by the policy.
1249 if env.Bit('coverage_enabled'):
1252 # This is a lame detection if seccomp bpf filters are supported by the kernel.
1253 # We suppose that any Linux kernel v3.2+ supports it, but it is only true
1254 # for Ubuntu kernels. Seccomp BPF filters reached the mainline at 3.5,
1255 # so this check will be wrong on some relatively old non-Ubuntu Linux distros.
1256 kernel_version = map(int, platform.release().split('.', 2)[:2])
1257 return kernel_version >= [3, 2]
1259 pre_base_env.AddMethod(SupportsSeccompBpfSandbox)
1262 def GetBootstrap(env):
1263 if 'TRUSTED_ENV' in env:
1264 trusted_env = env['TRUSTED_ENV']
1265 if trusted_env.Bit('linux'):
1266 template_digits = 'X' * 16
1267 return (trusted_env.File('${STAGING_DIR}/nacl_helper_bootstrap'),
1268 ['--r_debug=0x' + template_digits,
1269 '--reserved_at_zero=0x' + template_digits])
1272 pre_base_env.AddMethod(GetBootstrap)
1274 def AddBootstrap(env, executable, args):
1275 bootstrap, bootstrap_args = env.GetBootstrap()
1276 if bootstrap is None:
1277 return [executable] + args
1279 return [bootstrap, executable] + bootstrap_args + args
1281 pre_base_env.AddMethod(AddBootstrap)
1284 def GetIrtNexe(env, chrome_irt=False):
1285 image = ARGUMENTS.get('force_irt')
1287 return env.SConstructAbsPath(image)
1290 return nacl_irt_env.File('${STAGING_DIR}/irt.nexe')
1292 return nacl_irt_env.File('${STAGING_DIR}/irt_core.nexe')
1294 pre_base_env.AddMethod(GetIrtNexe)
1296 def ApplyTLSEdit(env, nexe_name, raw_nexe):
1297 # If the environment was built elsewhere, we do not need to apply tls_edit
1298 # since it only needs to be done during building.
1299 if env.Bit('built_elsewhere'):
1300 return env.File(nexe_name)
1302 tls_edit_exe = env['BUILD_ENV'].File('${STAGING_DIR}/tls_edit${PROGSUFFIX}')
1305 [tls_edit_exe, raw_nexe],
1306 '${SOURCES[0]} --verbose ${SOURCES[1:]} ${TARGET}')
1308 pre_base_env.AddMethod(ApplyTLSEdit)
1310 def CommandValidatorTestNacl(env, name, image,
1311 validator_flags=None,
1315 validator = env.GetValidator(validator)
1316 if validator is None:
1317 print 'WARNING: no validator found. Skipping test %s' % name
1320 if validator_flags is None:
1321 validator_flags = []
1323 if env.Bit('pnacl_generate_pexe'):
1326 command = [validator] + validator_flags + [image]
1327 return env.CommandTest(name, command, size, **extra)
1329 pre_base_env.AddMethod(CommandValidatorTestNacl)
1332 def ExtractPublishedFiles(env, target_name):
1333 run_files = ['$STAGING_DIR/' + os.path.basename(published_file.path)
1334 for published_file in env.GetPublished(target_name, 'run')]
1335 nexe = '$STAGING_DIR/%s${PROGSUFFIX}' % target_name
1336 return [env.File(file) for file in run_files + [nexe]]
1338 pre_base_env.AddMethod(ExtractPublishedFiles)
1341 # Only include the chrome side of the build if present.
1342 if os.path.exists(pre_base_env.File(
1343 '#/../ppapi/native_client/chrome_main.scons').abspath):
1344 SConscript('#/../ppapi/native_client/chrome_main.scons',
1345 exports=['pre_base_env'])
1346 enable_chrome = True
1348 def AddChromeFilesFromGroup(env, file_group):
1350 pre_base_env.AddMethod(AddChromeFilesFromGroup)
1351 enable_chrome = False
1352 DeclareBit('enable_chrome_side',
1353 'Is the chrome side present.')
1354 pre_base_env.SetBitFromOption('enable_chrome_side', enable_chrome)
1356 def ProgramNameForNmf(env, basename):
1357 """ Create an architecture-specific filename that can be used in an NMF URL.
1359 if env.Bit('pnacl_generate_pexe'):
1362 return '%s_%s' % (basename, env.get('TARGET_FULLARCH'))
1364 pre_base_env.AddMethod(ProgramNameForNmf)
1367 def SelUniversalTest(env,
1371 sel_universal_flags=None,
1373 # The dynamic linker's ability to receive arguments over IPC at
1374 # startup currently requires it to reject the plugin's first
1375 # connection, but this interferes with the sel_universal-based
1376 # testing because sel_universal does not retry the connection.
1377 # TODO(mseaborn): Fix by retrying the connection or by adding an
1378 # option to ld.so to disable its argv-over-IPC feature.
1379 if env.Bit('nacl_glibc') and not env.Bit('nacl_static_link'):
1382 # TODO(petarj): Sel_universal hangs on qemu-mips. Enable when fixed.
1383 if env.Bit('target_mips32') and env.UsingEmulator():
1386 if sel_universal_flags is None:
1387 sel_universal_flags = []
1389 # When run under qemu, sel_universal must sneak in qemu to the execv
1390 # call that spawns sel_ldr.
1391 if env.UsingEmulator():
1392 sel_universal_flags.append('--command_prefix')
1393 sel_universal_flags.append(env.GetEmulator())
1395 if 'TRUSTED_ENV' not in env:
1397 sel_universal = env['TRUSTED_ENV'].File(
1398 '${STAGING_DIR}/${PROGPREFIX}sel_universal${PROGSUFFIX}')
1400 # Point to sel_ldr using an environment variable.
1401 sel_ldr = env.GetSelLdr()
1403 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1405 kwargs.setdefault('osenv', []).append('NACL_SEL_LDR=' + sel_ldr.abspath)
1406 bootstrap, _ = env.GetBootstrap()
1407 if bootstrap is not None:
1408 kwargs['osenv'].append('NACL_SEL_LDR_BOOTSTRAP=%s' % bootstrap.abspath)
1410 node = CommandSelLdrTestNacl(env,
1414 loader=sel_universal,
1415 sel_ldr_flags=sel_universal_flags,
1416 skip_bootstrap=True,
1418 if not env.Bit('built_elsewhere'):
1419 env.Depends(node, sel_ldr)
1420 if bootstrap is not None:
1421 env.Depends(node, bootstrap)
1424 pre_base_env.AddMethod(SelUniversalTest)
1427 def MakeNaClLogOption(env, target):
1428 """ Make up a filename related to the [target], for use with NACLLOG.
1429 The file should end up in the build directory (scons-out/...).
1431 # NOTE: to log to the source directory use file.srcnode().abspath instead.
1432 # See http://www.scons.org/wiki/File%28%29
1433 return env.File(target + '.nacllog').abspath
1435 pre_base_env.AddMethod(MakeNaClLogOption)
1437 def MakeVerboseExtraOptions(env, target, log_verbosity, extra):
1438 """ Generates **extra options that will give access to service runtime logs,
1439 at a given log_verbosity. Slips the options into the given extra dict. """
1440 log_file = env.MakeNaClLogOption(target)
1441 extra['log_file'] = log_file
1442 extra_env = ['NACLLOG=%s' % log_file,
1443 'NACLVERBOSITY=%d' % log_verbosity]
1444 extra['osenv'] = extra.get('osenv', []) + extra_env
1446 pre_base_env.AddMethod(MakeVerboseExtraOptions)
1448 def ShouldUseVerboseOptions(env, extra):
1449 """ Heuristic for setting up Verbose NACLLOG options. """
1450 return ('process_output_single' in extra or
1451 'log_golden' in extra)
1453 pre_base_env.AddMethod(ShouldUseVerboseOptions)
1456 DeclareBit('tests_use_irt', 'Non-browser tests also load the IRT image', False)
1458 # Bit to be set by individual test/nacl.scons files that need to opt out.
1459 DeclareBit('nonstable_bitcode', 'Tests use non-stable bitcode features', False)
1462 def GetFinalizedPexe(env, pexe):
1463 """ Prep and finalize the ABI for a given pexe if needed.
1465 if not env.Bit('pnacl_generate_pexe') or env.Bit('nonstable_bitcode'):
1468 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1469 # file instead. There are currently some canned nexe tests in build.scons.
1470 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1473 # Otherwise, finalize during the build step, since there is no finalize tool
1474 # that can run on triggered bots such as the ARM HW bots.
1475 pexe_name = pexe.abspath
1476 final_name = StripSuffix(pexe_name, '.nonfinal.pexe') + '.final.pexe'
1477 # Make sure the pexe doesn't get removed by the fake builders when
1480 node = env.Command(target=final_name, source=[pexe_name],
1481 action=[Action('${PNACLFINALIZECOM}',
1482 '${PNACLFINALIZECOMSTR}')])
1483 assert len(node) == 1, node
1487 # Translate the given pexe.
1488 def GetTranslatedNexe(env, pexe):
1489 # First finalize the pexe.
1490 pexe = GetFinalizedPexe(env, pexe)
1492 # Then check if we need to translate.
1493 # Check if we started with a pexe, so there is actually a translation step.
1494 if not env.Bit('pnacl_generate_pexe'):
1497 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1498 # file instead. There are currently some canned nexe tests in build.scons.
1499 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1502 # Often there is a build step (do_not_run_tests=1) and a test step
1503 # (which is run with -j1). Normally we want to translate in the build step
1504 # so we can translate in parallel. However when we do sandboxed translation
1505 # on arm hw, we do the build step on x86 and translation on arm, so we have
1506 # to force the translation to be done in the test step. Hence,
1507 # we check the bit 'translate_in_build_step' / check if we are
1509 if not env.Bit('translate_in_build_step') and env.Bit('do_not_run_tests'):
1512 pexe_name = pexe.abspath
1513 # Tidy up the suffix (remove the .final.pexe or .nonfinal.pexe),
1514 # depending on whether or not the pexe was finalized.
1515 suffix_to_strip = '.final.pexe'
1516 if not pexe_name.endswith(suffix_to_strip):
1517 suffix_to_strip = '.nonfinal.pexe'
1518 nexe_name = StripSuffix(pexe_name, suffix_to_strip) + '.nexe'
1519 # Make sure the pexe doesn't get removed by the fake builders when
1522 if env.Bit('nonstable_bitcode'):
1523 env.Append(TRANSLATEFLAGS=['--allow-llvm-bitcode-input'])
1524 node = env.Command(target=nexe_name, source=[pexe_name],
1525 action=[Action('${TRANSLATECOM}', '${TRANSLATECOMSTR}')])
1526 assert len(node) == 1, node
1529 pre_base_env.AddMethod(GetTranslatedNexe)
1532 def CommandTestFileDumpCheck(env,
1537 """Create a test that disassembles a binary (|target|) and checks for
1538 patterns in the |check_file|. Disassembly is done using |objdump_flags|.
1541 # Do not try to run OBJDUMP if 'built_elsewhere', since that *might* mean
1542 # that a toolchain is not even present. E.g., the arm hw buildbots do
1543 # not have the pnacl toolchain. We should be able to look for the host
1544 # ARM objdump though... a TODO(jvoung) for when there is time.
1545 if env.Bit('built_elsewhere'):
1547 target = env.GetTranslatedNexe(target)
1548 return env.CommandTestFileCheck(name,
1549 ['${OBJDUMP}', objdump_flags, target],
1552 pre_base_env.AddMethod(CommandTestFileDumpCheck)
1555 def CommandTestFileCheck(env, name, cmd, check_file):
1556 """Create a test that runs a |cmd| (array of strings),
1557 which is expected to print to stdout. The results
1558 of stdout will then be piped to the file_check.py tool which
1559 will search for the regexes specified in |check_file|. """
1561 return env.CommandTest(name,
1563 env.File('${SCONSTRUCT_DIR}/tools/file_check.py'),
1565 # don't run ${PYTHON} under the emulator.
1566 direct_emulation=False)
1568 pre_base_env.AddMethod(CommandTestFileCheck)
1570 def CommandSelLdrTestNacl(env, name, nexe,
1576 # True for *.nexe statically linked with glibc
1578 skip_bootstrap=False,
1579 wrapper_program_prefix=None,
1580 # e.g., [ 'python', 'time_check.py', '--' ]
1582 # Disable all sel_ldr tests for windows under coverage.
1583 # Currently several .S files block sel_ldr from being instrumented.
1584 # See http://code.google.com/p/nativeclient/issues/detail?id=831
1585 if ('TRUSTED_ENV' in env and
1586 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1587 env['TRUSTED_ENV'].Bit('windows')):
1590 # The nexe might be a pexe that needs finalization, and translation.
1591 nexe = env.GetTranslatedNexe(nexe)
1594 if args is not None:
1597 if env.Bit('pnacl_unsandboxed'):
1598 # Run unsandboxed executable directly, without sel_ldr.
1599 return env.CommandTest(name, command, size, **extra)
1602 loader = env.GetSelLdr()
1604 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1607 # Avoid problems with [] as default arguments
1608 if sel_ldr_flags is None:
1611 # Avoid modifying original list
1612 sel_ldr_flags = list(sel_ldr_flags)
1614 # Disable the validator if running a GLibC test under Valgrind.
1615 # http://code.google.com/p/nativeclient/issues/detail?id=1799
1616 if env.IsRunningUnderValgrind() and env.Bit('nacl_glibc'):
1617 sel_ldr_flags += ['-cc']
1618 # https://code.google.com/p/nativeclient/issues/detail?id=3158
1619 # We don't currently have valgrind.so for LD_PRELOAD to use. That .so
1620 # is not used for newlib.
1621 # TODO(sehr): add valgrind.so built for NaCl.
1624 # Skip platform qualification checks on configurations with known issues.
1625 if env.GetEmulator() or env.IsRunningUnderValgrind():
1626 sel_ldr_flags += ['-Q']
1628 # Skip validation if we are using the x86-64 zero-based sandbox.
1629 # TODO(arbenson): remove this once the validator supports the x86-64
1630 # zero-based sandbox model.
1631 if env.Bit('x86_64_zero_based_sandbox'):
1632 sel_ldr_flags += ['-c']
1634 # The glibc modifications only make sense for nacl_env tests.
1635 # But this function gets used by some base_env (i.e. src/trusted/...)
1636 # tests too. Don't add the --nacl_glibc changes to the command
1637 # line for those cases.
1638 if env.Bit('nacl_glibc') and env['NACL_BUILD_FAMILY'] != 'TRUSTED':
1639 if not glibc_static and not env.Bit('nacl_static_link'):
1640 command = ['${NACL_SDK_LIB}/runnable-ld.so',
1641 # Locally-built shared libraries come from ${LIB_DIR}
1642 # while toolchain-provided ones come from ${NACL_SDK_LIB}.
1643 '--library-path', '${LIB_DIR}:${NACL_SDK_LIB}'] + command
1644 # Enable file access.
1645 sel_ldr_flags += ['-a']
1647 # Turn off sandbox for mac so coverage files can be written out.
1648 if ('TRUSTED_ENV' in env and
1649 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1650 env.Bit('host_mac') and
1651 '-a' not in sel_ldr_flags):
1652 sel_ldr_flags += ['-a']
1654 if env.Bit('tests_use_irt'):
1655 sel_ldr_flags += ['-B', nacl_env.GetIrtNexe()]
1658 loader_cmd = [loader]
1660 loader_cmd = env.AddBootstrap(loader, [])
1662 command = loader_cmd + sel_ldr_flags + ['--'] + command
1664 if env.Bit('host_linux'):
1665 extra['using_nacl_signal_handler'] = True
1667 if env.ShouldUseVerboseOptions(extra):
1668 env.MakeVerboseExtraOptions(name, log_verbosity, extra)
1670 node = env.CommandTest(name, command, size, posix_path=True,
1671 wrapper_program_prefix=wrapper_program_prefix, **extra)
1672 if env.Bit('tests_use_irt'):
1673 env.Alias('irt_tests', node)
1676 pre_base_env.AddMethod(CommandSelLdrTestNacl)
1679 TEST_EXTRA_ARGS = ['stdin', 'log_file',
1680 'stdout_golden', 'stderr_golden', 'log_golden',
1681 'filter_regex', 'filter_inverse', 'filter_group_only',
1682 'osenv', 'arch', 'subarch', 'exit_status', 'track_cmdtime',
1683 'num_runs', 'process_output_single',
1684 'process_output_combined', 'using_nacl_signal_handler',
1685 'declares_exit_status', 'time_warning', 'time_error']
1687 TEST_TIME_THRESHOLD = {
1694 # Valgrind handles SIGSEGV in a way our testing tools do not expect.
1695 UNSUPPORTED_VALGRIND_EXIT_STATUS = ['trusted_sigabrt',
1696 'untrusted_sigill' ,
1697 'untrusted_segfault',
1698 'untrusted_sigsegv_or_equivalent',
1700 'trusted_sigsegv_or_equivalent']
1703 def GetPerfEnvDescription(env):
1704 """Return a string describing architecture, library, etc. options.
1706 This function attempts to gather a string that might inform why a performance
1707 change has occurred.
1709 description_list = [env['TARGET_FULLARCH']]
1710 # Using a list to keep the order consistent.
1711 bit_to_description = [ ('bitcode', ('pnacl', 'nnacl')),
1712 ('translate_fast', ('fast', '')),
1713 ('nacl_glibc', ('glibc', 'newlib')),
1714 ('nacl_static_link', ('static', 'dynamic')),
1716 for (bit, (descr_yes, descr_no)) in bit_to_description:
1718 additional = descr_yes
1720 additional = descr_no
1722 description_list.append(additional)
1723 return '_'.join(description_list)
1725 pre_base_env.AddMethod(GetPerfEnvDescription)
1730 def GetTestName(target):
1731 key = str(target.path)
1732 return TEST_NAME_MAP.get(key, key)
1734 pre_base_env['GetTestName'] = GetTestName
1737 def SetTestName(node, name):
1738 for target in Flatten(node):
1739 TEST_NAME_MAP[str(target.path)] = name
1742 def ApplyTestWrapperCommand(command_args, extra_deps):
1743 new_args = ARGUMENTS['test_wrapper'].split()
1744 for input_file in extra_deps:
1745 new_args.extend(['-F', input_file])
1746 for arg in command_args:
1747 if isinstance(arg, str):
1748 new_args.extend(['-a', arg])
1750 new_args.extend(['-f', arg])
1754 def CommandTest(env, name, command, size='small', direct_emulation=True,
1755 extra_deps=[], posix_path=False, capture_output=True,
1756 capture_stderr=True, wrapper_program_prefix=None,
1757 scale_timeout=None, **extra):
1758 if not name.endswith('.out') or name.startswith('$'):
1759 raise Exception('ERROR: bad test filename for test output %r' % name)
1761 if env.IsRunningUnderValgrind():
1763 elif env.Bit('asan'):
1764 skip = 'AddressSanitizer'
1767 # Valgrind tends to break crash tests by changing the exit status.
1768 # So far, tests using declares_exit_status are crash tests. If this
1769 # changes, we will have to find a way to make declares_exit_status
1770 # work with Valgrind.
1771 if (skip is not None and
1772 (extra.get('exit_status') in UNSUPPORTED_VALGRIND_EXIT_STATUS or
1773 bool(int(extra.get('declares_exit_status', 0))))):
1774 print 'Skipping death test "%s" under %s' % (name, skip)
1778 extra.setdefault('osenv', [])
1779 # Ensure that 'osenv' is a list.
1780 if isinstance(extra['osenv'], str):
1781 extra['osenv'] = [extra['osenv']]
1782 # ASan normally intercepts SIGSEGV and disables our SIGSEGV signal
1783 # handler, which interferes with various NaCl tests, including the
1784 # platform qualification test built into sel_ldr. We fix this by
1785 # telling ASan not to mess with SIGSEGV.
1786 asan_options = ['handle_segv=0']
1787 if env.Bit('host_mac') and int(platform.mac_ver()[0].split('.')[1]) < 7:
1788 # MacOS 10.6 has a bug in the libsandbox system library where it
1789 # makes a memcmp call that reads off the end of a malloc'd block.
1790 # The bug appears to be harmless, but trips an ASan report. So
1791 # tell ASan to suppress memcmp checks.
1792 asan_options.append('strict_memcmp=0')
1793 # Note that the ASan runtime doesn't use : specifically as a separator.
1794 # It actually just looks for "foo=" anywhere in the string with strstr,
1795 # so any separator will do. The most obvious choices, ' ', ',', and ';'
1796 # all cause command_tester.py to split things up and get confused.
1797 extra['osenv'].append('ASAN_OPTIONS=' + ':'.join(asan_options))
1799 name = '${TARGET_ROOT}/test_results/' + name
1800 # NOTE: using the long version of 'name' helps distinguish opt vs dbg
1801 max_time = TEST_TIME_THRESHOLD[size]
1802 if 'scale_timeout' in ARGUMENTS:
1803 max_time = max_time * int(ARGUMENTS['scale_timeout'])
1805 max_time = max_time * scale_timeout
1807 if env.Bit('nacl_glibc'):
1808 suite = 'nacl_glibc'
1810 suite = 'nacl_newlib'
1811 if env.Bit('bitcode'):
1814 script_flags = ['--name', '%s.${GetTestName(TARGET)}' % suite,
1815 '--time_warning', str(max_time),
1816 '--time_error', str(10 * max_time),
1819 run_under = ARGUMENTS.get('run_under')
1821 run_under_extra_args = ARGUMENTS.get('run_under_extra_args')
1822 if run_under_extra_args:
1823 run_under = run_under + ',' + run_under_extra_args
1824 script_flags.append('--run_under')
1825 script_flags.append(run_under)
1827 emulator = env.GetEmulator()
1828 if emulator and direct_emulation:
1829 command = [emulator] + command
1831 # test wrapper should go outside of emulators like qemu, since the
1832 # test wrapper code is not emulated.
1833 if wrapper_program_prefix is not None:
1834 command = wrapper_program_prefix + command
1836 script_flags.append('--perf_env_description')
1837 script_flags.append(env.GetPerfEnvDescription())
1839 # Add architecture info.
1840 extra['arch'] = env['BUILD_ARCHITECTURE']
1841 extra['subarch'] = env['BUILD_SUBARCH']
1843 for flag_name, flag_value in extra.iteritems():
1844 assert flag_name in TEST_EXTRA_ARGS, repr(flag_name)
1845 if isinstance(flag_value, list):
1846 # Options to command_tester.py which are actually lists must not be
1847 # separated by whitespace. This stringifies the lists with a separator
1848 # char to satisfy command_tester.
1849 flag_value = command_tester.StringifyList(flag_value)
1850 # do not add --flag + |flag_name| |flag_value| if
1851 # |flag_value| is false (empty).
1853 script_flags.append('--' + flag_name)
1854 # Make sure flag values are strings (or SCons objects) when building
1855 # up the command. Right now, this only means convert ints to strings.
1856 if isinstance(flag_value, int):
1857 flag_value = str(flag_value)
1858 script_flags.append(flag_value)
1861 if not capture_output:
1862 script_flags.extend(['--capture_output', '0'])
1863 if not capture_stderr:
1864 script_flags.extend(['--capture_stderr', '0'])
1866 # Set command_tester.py's output filename. We skip this when using
1867 # test_wrapper because the run_test_via_ssh.py wrapper does not have
1868 # the ability to copy result files back from the remote host.
1869 if 'test_wrapper' not in ARGUMENTS:
1870 script_flags.extend(['--report', name])
1872 test_script = env.File('${SCONSTRUCT_DIR}/tools/command_tester.py')
1873 extra_deps = extra_deps + [env.File('${SCONSTRUCT_DIR}/tools/test_lib.py')]
1874 command = ['${PYTHON}', test_script] + script_flags + command
1875 if 'test_wrapper' in ARGUMENTS:
1876 command = ApplyTestWrapperCommand(command, extra_deps)
1877 return env.AutoDepsCommand(name, command,
1878 extra_deps=extra_deps, posix_path=posix_path,
1879 disabled=env.Bit('do_not_run_tests'))
1881 pre_base_env.AddMethod(CommandTest)
1884 def FileSizeTest(env, name, envFile, max_size=None):
1885 """FileSizeTest() returns a scons node like the other XYZTest generators.
1886 It logs the file size of envFile in a perf-buildbot-recognizable format.
1887 Optionally, it can cause a test failure if the file is larger than max_size.
1889 def doSizeCheck(target, source, env):
1890 filepath = source[0].abspath
1891 actual_size = os.stat(filepath).st_size
1892 command_tester.LogPerfResult(name,
1893 env.GetPerfEnvDescription(),
1894 '%.3f' % (actual_size / 1024.0),
1896 # Also get zipped size.
1897 nexe_file = open(filepath, 'rb')
1898 zipped_size = len(zlib.compress(nexe_file.read()))
1900 command_tester.LogPerfResult(name,
1901 'ZIPPED_' + env.GetPerfEnvDescription(),
1902 '%.3f' % (zipped_size / 1024.0),
1904 # Finally, do the size check.
1905 if max_size is not None and actual_size > max_size:
1906 # NOTE: this exception only triggers a failure for this particular test,
1907 # just like any other test failure.
1908 raise Exception("File %s larger than expected: expected up to %i, got %i"
1909 % (filepath, max_size, actual_size))
1910 # If 'built_elsewhere', the file should should have already been built.
1911 # Do not try to built it and/or its pieces.
1912 if env.Bit('built_elsewhere'):
1913 env.Ignore(name, envFile)
1914 return env.Command(name, envFile, doSizeCheck)
1916 pre_base_env.AddMethod(FileSizeTest)
1918 def StripExecutable(env, name, exe):
1919 """StripExecutable returns a node representing the stripped version of |exe|.
1920 The stripped version will be given the basename |name|.
1921 NOTE: for now this only works with the untrusted toolchain.
1922 STRIP does not appear to be a first-class citizen in SCons and
1923 STRIP has only been set to point at the untrusted toolchain.
1928 action=[Action('${STRIPCOM} ${SOURCES} -o ${TARGET}', '${STRIPCOMSTR}')])
1930 pre_base_env.AddMethod(StripExecutable)
1933 # TODO(ncbray): pretty up the log output when running this builder.
1934 def DisabledCommand(target, source, env):
1937 pre_base_env['BUILDERS']['DisabledCommand'] = Builder(action=DisabledCommand)
1940 def AutoDepsCommand(env, name, command, extra_deps=[], posix_path=False,
1942 """AutoDepsCommand() takes a command as an array of arguments. Each
1943 argument may either be:
1946 * a Scons file object, e.g. one created with env.File() or as the
1947 result of another build target.
1949 In the second case, the file is automatically declared as a
1950 dependency of this command.
1952 command = list(command)
1954 for index, arg in enumerate(command):
1955 if not isinstance(arg, str):
1956 if len(Flatten(arg)) != 1:
1957 # Do not allow this, because it would cause "deps" to get out
1958 # of sync with the indexes in "command".
1959 # See http://code.google.com/p/nativeclient/issues/detail?id=1086
1960 raise AssertionError('Argument to AutoDepsCommand() actually contains '
1961 'multiple (or zero) arguments: %r' % arg)
1963 command[index] = '${SOURCES[%d].posix}' % len(deps)
1965 command[index] = '${SOURCES[%d].abspath}' % len(deps)
1968 # If built_elsewhere, build commands are replaced by no-ops, so make sure
1969 # the targets don't get removed first
1970 if env.Bit('built_elsewhere'):
1972 env.Depends(name, extra_deps)
1975 return env.DisabledCommand(name, deps)
1977 return env.Command(name, deps, ' '.join(command))
1980 pre_base_env.AddMethod(AutoDepsCommand)
1983 def GetPrintableCommandName(cmd):
1984 """Look at the first few elements of cmd to derive a suitable command name."""
1985 cmd_tokens = cmd.split()
1986 if "python" in cmd_tokens[0] and len(cmd_tokens) >= 2:
1987 cmd_name = cmd_tokens[1]
1989 cmd_name = cmd_tokens[0].split('(')[0]
1991 # undo some pretty printing damage done by hammer
1992 cmd_name = cmd_name.replace('________','')
1993 # use file name part of a path
1994 return cmd_name.split('/')[-1]
1997 def GetPrintableEnvironmentName(env):
1998 # use file name part of a obj root path as env name
1999 return env.subst('${TARGET_ROOT}').split('/')[-1]
2001 pre_base_env.AddMethod(GetPrintableEnvironmentName)
2004 def CustomCommandPrinter(cmd, targets, source, env):
2005 # Abuse the print hook to count the commands that are executed
2006 if env.Bit('target_stats'):
2007 cmd_name = GetPrintableCommandName(cmd)
2008 env_name = env.GetPrintableEnvironmentName()
2009 CMD_COUNTER[cmd_name] = CMD_COUNTER.get(cmd_name, 0) + 1
2010 ENV_COUNTER[env_name] = ENV_COUNTER.get(env_name, 0) + 1
2013 # Our pretty printer
2015 cmd_name = GetPrintableCommandName(cmd)
2016 env_name = env.GetPrintableEnvironmentName()
2017 sys.stdout.write('[%s] [%s] %s\n' % (cmd_name, env_name,
2018 targets[0].get_path()))
2020 # The SCons default (copied from print_cmd_line in Action.py)
2021 sys.stdout.write(cmd + u'\n')
2023 pre_base_env.Append(PRINT_CMD_LINE_FUNC=CustomCommandPrinter)
2026 def GetAbsDirArg(env, argument, target):
2027 """Fetch the named command-line argument and turn it into an absolute
2028 directory name. If the argument is missing, raise a UserError saying
2029 that the given target requires that argument be given."""
2030 dir = ARGUMENTS.get(argument)
2032 raise UserError('%s must be set when invoking %s' % (argument, target))
2033 return os.path.join(env.Dir('$MAIN_DIR').abspath, dir)
2035 pre_base_env.AddMethod(GetAbsDirArg)
2038 pre_base_env.Append(
2040 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
2041 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
2045 def MakeGTestEnv(env):
2046 # Create an environment to run unit tests using Gtest.
2047 gtest_env = env.Clone()
2049 # This became necessary for the arm cross TC v4.6
2050 # but probable applies to all new gcc TCs
2051 gtest_env.Append(LINKFLAGS=['-pthread'])
2053 # Define compile-time flag that communicates that we are compiling in the test
2054 # environment (rather than for the TCB).
2055 if gtest_env['NACL_BUILD_FAMILY'] == 'TRUSTED':
2056 gtest_env.Append(CCFLAGS=['-DNACL_TRUSTED_BUT_NOT_TCB'])
2058 # This is necessary for unittest_main.c which includes gtest/gtest.h
2059 # The problem is that gtest.h includes other files expecting the
2060 # include path to be set.
2061 gtest_env.Prepend(CPPPATH=['${SOURCE_ROOT}/testing/gtest/include'])
2063 # gtest does not compile with our stringent settings.
2064 if gtest_env.Bit('linux') or gtest_env.Bit('mac'):
2065 # "-pedantic" is because of: gtest-typed-test.h:236:46: error:
2066 # anonymous variadic macros were introduced in C99
2067 # Also, gtest does not compile successfully with "-Wundef".
2068 gtest_env.FilterOut(CCFLAGS=['-pedantic', '-Wundef'])
2069 gtest_env.FilterOut(CXXFLAGS=['-fno-rtti', '-Weffc++'])
2071 # gtest is incompatible with static linking due to obscure libstdc++
2072 # linking interactions.
2073 # See http://code.google.com/p/nativeclient/issues/detail?id=1987
2074 gtest_env.FilterOut(LINKFLAGS=['-static'])
2076 gtest_env.Prepend(LIBS=['gtest'])
2079 pre_base_env.AddMethod(MakeGTestEnv)
2081 def MakeUntrustedNativeEnv(env):
2082 native_env = nacl_env.Clone()
2083 if native_env.Bit('bitcode') and not native_env.Bit('target_mips32'):
2084 native_env = native_env.PNaClGetNNaClEnv()
2087 pre_base_env.AddMethod(MakeUntrustedNativeEnv)
2089 def MakeBaseTrustedEnv(platform=None):
2090 base_env = MakeArchSpecificEnv(platform)
2092 IS_BUILD_ENV = False,
2095 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
2096 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
2103 EXTRA_CXXFLAGS = [],
2105 CFLAGS = ['${EXTRA_CFLAGS}'],
2106 CXXFLAGS = ['${EXTRA_CXXFLAGS}'],
2108 if base_env.Bit('ncval_testing'):
2109 base_env.Append(CPPDEFINES = ['NCVAL_TESTING'])
2111 base_env.Append(BUILD_SCONSCRIPTS = [
2112 # KEEP THIS SORTED PLEASE
2113 'build/package_version/build.scons',
2114 'pynacl/build.scons',
2115 'src/shared/gio/build.scons',
2116 'src/shared/imc/build.scons',
2117 'src/shared/ldr/build.scons',
2118 'src/shared/platform/build.scons',
2119 'src/shared/serialization/build.scons',
2120 'src/shared/srpc/build.scons',
2121 'src/shared/utils/build.scons',
2122 'src/third_party_mod/gtest/build.scons',
2123 'src/tools/validator_tools/build.scons',
2124 'src/trusted/cpu_features/build.scons',
2125 'src/trusted/debug_stub/build.scons',
2126 'src/trusted/desc/build.scons',
2127 'src/trusted/desc_cacheability/build.scons',
2128 'src/trusted/fault_injection/build.scons',
2129 'src/trusted/generic_container/build.scons',
2130 'src/trusted/gio/build.scons',
2131 'src/trusted/interval_multiset/build.scons',
2132 'src/trusted/manifest_name_service_proxy/build.scons',
2133 'src/trusted/nacl_base/build.scons',
2134 'src/trusted/nonnacl_util/build.scons',
2135 'src/trusted/perf_counter/build.scons',
2136 'src/trusted/platform_qualify/build.scons',
2137 'src/trusted/python_bindings/build.scons',
2138 'src/trusted/reverse_service/build.scons',
2139 'src/trusted/seccomp_bpf/build.scons',
2140 'src/trusted/sel_universal/build.scons',
2141 'src/trusted/service_runtime/build.scons',
2142 'src/trusted/simple_service/build.scons',
2143 'src/trusted/threading/build.scons',
2144 'src/trusted/validator/build.scons',
2145 'src/trusted/validator/driver/build.scons',
2146 'src/trusted/validator/x86/32/build.scons',
2147 'src/trusted/validator/x86/64/build.scons',
2148 'src/trusted/validator/x86/build.scons',
2149 'src/trusted/validator/x86/decoder/build.scons',
2150 'src/trusted/validator/x86/decoder/generator/build.scons',
2151 'src/trusted/validator/x86/ncval_reg_sfi/build.scons',
2152 'src/trusted/validator/x86/ncval_seg_sfi/build.scons',
2153 'src/trusted/validator/x86/ncval_seg_sfi/generator/build.scons',
2154 'src/trusted/validator/x86/testing/enuminsts/build.scons',
2155 'src/trusted/validator_arm/build.scons',
2156 'src/trusted/validator_ragel/build.scons',
2157 'src/trusted/validator_x86/build.scons',
2158 'src/trusted/weak_ref/build.scons',
2159 'tests/common/build.scons',
2160 'tests/lock_manager/build.scons',
2161 'tests/performance/build.scons',
2162 'tests/python_version/build.scons',
2163 'tests/sel_ldr_seccomp/build.scons',
2164 'tests/srpc_message/build.scons',
2165 'tests/tools/build.scons',
2166 'tests/unittests/shared/srpc/build.scons',
2167 'tests/unittests/shared/imc/build.scons',
2168 'tests/unittests/shared/platform/build.scons',
2169 'tests/unittests/trusted/asan/build.scons',
2170 'tests/unittests/trusted/bits/build.scons',
2171 'tests/unittests/trusted/platform_qualify/build.scons',
2172 'tests/unittests/trusted/service_runtime/build.scons',
2173 'toolchain_build/build.scons',
2176 base_env.AddMethod(SDKInstallBin)
2178 # The ARM and MIPS validators can be built for any target that doesn't use
2180 if not base_env.Bit('target_x86_64'):
2182 BUILD_SCONSCRIPTS = [
2183 'src/trusted/validator_mips/build.scons',
2186 base_env.AddChromeFilesFromGroup('trusted_scons_files')
2189 NACL_BUILD_FAMILY = 'TRUSTED',
2192 # Add optional scons files if present in the directory tree.
2193 if os.path.exists(pre_base_env.subst('${MAIN_DIR}/supplement/build.scons')):
2194 base_env.Append(BUILD_SCONSCRIPTS=['${MAIN_DIR}/supplement/build.scons'])
2199 # Select tests to run under coverage build.
2200 pre_base_env['COVERAGE_TARGETS'] = [
2201 'small_tests', 'medium_tests', 'large_tests',
2202 'chrome_browser_tests']
2205 pre_base_env.Help("""\
2206 ======================================================================
2208 ======================================================================
2213 * cleaning: scons -c
2215 * build mandel: scons --mode=nacl mandel.nexe
2216 * smoke test: scons --mode=nacl,opt-linux -k pp=1 smoke_tests
2218 * sel_ldr: scons --mode=opt-linux sel_ldr
2220 * build the plugin: scons --mode=opt-linux ppNaClPlugin
2221 * or: scons --mode=opt-linux src/trusted/plugin
2223 Targets to build trusted code destined for the SDK:
2224 * build trusted-code tools: scons build_bin
2225 * install trusted-code tools: scons install_bin bindir=...
2226 * These default to opt build, or add --mode=dbg-host for debug build.
2228 Targets to build untrusted code destined for the SDK:
2229 * build just libraries: scons build_lib
2230 * install just headers: scons install_headers includedir=...
2231 * install just libraries: scons install_lib libdir=...
2232 * install headers and libraries:scons install includedir=... libdir=...
2234 * dump system info: scons --mode=nacl,opt-linux dummy
2239 naclsdk_mode=<mode> where <mode>:
2241 'local': use locally installed sdk kit
2242 'download': use the download copy (default)
2243 'custom:<path>': use kit at <path>
2244 'manual': use settings from env vars NACL_SDK_xxx
2246 pnaclsdk_mode=<mode> where <mode:
2247 'default': use the default (typically the downloaded copy)
2248 'custom:<path>': use kit from <path>
2250 --prebuilt Do not build things, just do install steps
2252 --verbose Full command line logging before command execution
2254 pp=1 Use command line pretty printing (more concise output)
2256 sysinfo=1 Verbose system info printing
2258 naclsdk_validate=0 Suppress presence check of sdk
2262 Automagically generated help:
2263 -----------------------------
2267 def SetUpClang(env):
2268 env['CLANG_DIR'] = '${SOURCE_ROOT}/third_party/llvm-build/Release+Asserts/bin'
2269 env['CLANG_OPTS'] = []
2271 if not (env.Bit('host_linux') or env.Bit('host_mac')):
2272 raise UserError("ERROR: ASan is only available for Linux and Mac")
2273 env['CLANG_OPTS'].append('-fsanitize=address')
2274 if env.Bit('host_mac'):
2275 # The built executables will try to find this library at runtime
2276 # in the directory containing the executable itself. In the
2277 # Chromium build, the library just gets copied into that
2278 # directory. Here, there isn't a single directory from which
2279 # all the test binaries are run (sel_ldr is run from staging/
2280 # but other trusted test binaries are run from their respective
2281 # obj/.../ directories). So instead just point the dynamic linker
2282 # at the right directory using an environment variable.
2283 clang_lib_dir = '${CLANG_DIR}/../lib/clang/*/lib/darwin'
2284 env['ENV']['DYLD_LIBRARY_PATH'] = ':'.join([dir.abspath for dir in
2285 env.Glob(clang_lib_dir)])
2286 if 'PROPAGATE_ENV' not in env:
2287 env['PROPAGATE_ENV'] = []
2288 env['PROPAGATE_ENV'].append('DYLD_LIBRARY_PATH')
2290 env['CC'] = '${CLANG_DIR}/clang ${CLANG_OPTS}'
2291 env['CXX'] = '${CLANG_DIR}/clang++ ${CLANG_OPTS}'
2292 # Make sure we find Clang-supplied libraries like -lprofile_rt
2293 # in the Clang build we use, rather than from the system.
2294 # The system-installed versions go with the system-installed Clang
2295 # and might not be compatible with the Clang we're running.
2296 env.Append(LIBPATH=['${CLANG_DIR}/../lib'])
2298 def GenerateOptimizationLevels(env):
2299 if env.Bit('clang'):
2302 # Generate debug variant.
2303 debug_env = env.Clone(tools = ['target_debug'])
2304 debug_env['OPTIMIZATION_LEVEL'] = 'dbg'
2305 debug_env['BUILD_TYPE'] = debug_env.subst('$BUILD_TYPE')
2306 debug_env['BUILD_DESCRIPTION'] = debug_env.subst('$BUILD_DESCRIPTION')
2307 AddDualLibrary(debug_env)
2308 # Add to the list of fully described environments.
2309 environment_list.append(debug_env)
2311 # Generate opt variant.
2312 opt_env = env.Clone(tools = ['target_optimized'])
2313 opt_env['OPTIMIZATION_LEVEL'] = 'opt'
2314 opt_env['BUILD_TYPE'] = opt_env.subst('$BUILD_TYPE')
2315 opt_env['BUILD_DESCRIPTION'] = opt_env.subst('$BUILD_DESCRIPTION')
2316 AddDualLibrary(opt_env)
2317 # Add to the list of fully described environments.
2318 environment_list.append(opt_env)
2320 return (debug_env, opt_env)
2323 def SDKInstallBin(env, name, node, target=None):
2324 """Add the given node to the build_bin and install_bin targets.
2325 It will be installed under the given name with the build target appended.
2326 The optional target argument overrides the setting of what that target is."""
2327 env.Alias('build_bin', node)
2328 if 'install_bin' in COMMAND_LINE_TARGETS:
2329 dir = env.GetAbsDirArg('bindir', 'install_bin')
2331 target = env['TARGET_FULLARCH'].replace('-', '_')
2332 file_name, file_ext = os.path.splitext(name)
2333 output_name = file_name + '_' + target + file_ext
2334 install_node = env.InstallAs(os.path.join(dir, output_name), node)
2335 env.Alias('install_bin', install_node)
2338 def MakeWindowsEnv(platform=None):
2339 base_env = MakeBaseTrustedEnv(platform)
2340 windows_env = base_env.Clone(
2341 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-win',
2342 BUILD_TYPE_DESCRIPTION = 'Windows ${OPTIMIZATION_LEVEL} build',
2343 tools = ['target_platform_windows'],
2344 # Windows /SAFESEH linking requires either an .sxdata section be
2345 # present or that @feat.00 be defined as a local, absolute symbol
2346 # with an odd value.
2347 ASCOM = ('$ASPPCOM /E /D__ASSEMBLER__ | '
2348 '$WINASM -defsym @feat.00=1 -o $TARGET'),
2349 PDB = '${TARGET.base}.pdb',
2350 # Strict doesn't currently work for Windows since some of the system
2351 # libraries like wsock32 are magical.
2352 LIBS_STRICT = False,
2353 TARGET_ARCH='x86_64' if base_env.Bit('build_x86_64') else 'x86',
2358 ['NACL_WINDOWS', '1'],
2360 ['NACL_LINUX', '0'],
2361 ['NACL_ANDROID', '0'],
2362 ['_WIN32_WINNT', '0x0501'],
2363 ['__STDC_LIMIT_MACROS', '1'],
2365 # WIN32 is used by ppapi
2367 # WIN32_LEAN_AND_MEAN tells windows.h to omit obsolete and rarely
2368 # used #include files. This allows use of Winsock 2.0 which otherwise
2369 # would conflict with Winsock 1.x included by windows.h.
2370 ['WIN32_LEAN_AND_MEAN', ''],
2372 LIBS = ['ws2_32', 'advapi32'],
2373 # TODO(bsy) remove 4355 once cross-repo
2374 # NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
2375 CCFLAGS = ['/EHsc', '/WX', '/wd4355', '/wd4800'],
2378 # This linker option allows us to ensure our builds are compatible with
2379 # Chromium, which uses it.
2380 if windows_env.Bit('build_x86_32'):
2381 windows_env.Append(LINKFLAGS = "/safeseh")
2383 # We use the GNU assembler (gas) on Windows so that we can use the
2384 # same .S assembly files on all platforms. Microsoft's assembler uses
2385 # a completely different syntax for x86 code.
2386 if windows_env.Bit('build_x86_64'):
2387 # This assembler only works for x86-64 code.
2388 windows_env['WINASM'] = \
2389 windows_env.File('$SOURCE_ROOT/third_party/mingw-w64/mingw/bin/'
2390 'x86_64-w64-mingw32-as.exe').abspath
2392 # This assembler only works for x86-32 code.
2393 windows_env['WINASM'] = \
2394 windows_env.File('$SOURCE_ROOT/third_party/gnu_binutils/files/'
2399 windows_optimized_env) = GenerateOptimizationLevels(MakeWindowsEnv())
2401 def MakeUnixLikeEnv(platform=None):
2402 unix_like_env = MakeBaseTrustedEnv(platform)
2403 # -Wdeclaration-after-statement is desirable because MS studio does
2404 # not allow declarations after statements in a block, and since much
2405 # of our code is portable and primarily initially tested on Linux,
2406 # it'd be nice to get the build error earlier rather than later
2407 # (building and testing on Linux is faster).
2408 # TODO(nfullagar): should we consider switching to -std=c99 ?
2409 unix_like_env.Prepend(
2412 '-Wdeclaration-after-statement',
2413 # Require defining functions as "foo(void)" rather than
2414 # "foo()" because, in C (but not C++), the latter defines a
2415 # function with unspecified arguments rather than no
2417 '-Wstrict-prototypes',
2428 '-fdiagnostics-show-option',
2429 '-fvisibility=hidden',
2430 '-fstack-protector',
2432 CXXFLAGS=['-std=c++98'],
2433 # NOTE: pthread is only neeeded for libppNaClPlugin.so and on arm
2435 CPPDEFINES = [['__STDC_LIMIT_MACROS', '1'],
2436 ['__STDC_FORMAT_MACROS', '1'],
2440 if not unix_like_env.Bit('clang'):
2441 unix_like_env.Append(CCFLAGS=['--param', 'ssp-buffer-size=4'])
2443 if unix_like_env.Bit('enable_tmpfs_redirect_var'):
2444 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '1']])
2446 unix_like_env.Append(CPPDEFINES=[['NACL_ENABLE_TMPFS_REDIRECT_VAR', '0']])
2447 return unix_like_env
2450 def MakeMacEnv(platform=None):
2451 mac_env = MakeUnixLikeEnv(platform).Clone(
2452 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-mac',
2453 BUILD_TYPE_DESCRIPTION = 'MacOS ${OPTIMIZATION_LEVEL} build',
2454 tools = ['target_platform_mac'],
2455 # TODO(bradnelson): this should really be able to live in unix_like_env
2456 # but can't due to what the target_platform_x module is
2459 PLUGIN_SUFFIX = '.bundle',
2461 # On Mac, only the newer clang toolchains can parse some of the trusted
2462 # code's assembly syntax, so turn clang on by default.
2463 mac_env.SetBits('clang')
2465 # This should be kept in synch with mac_deployment_target
2466 # in build/common.gypi, which in turn should be kept in synch
2467 # with chromium/src/build/common.gypi.
2468 mac_deployment_target = '10.6'
2471 CCFLAGS=['-mmacosx-version-min=' + mac_deployment_target],
2472 LINKFLAGS=['-mmacosx-version-min=' + mac_deployment_target])
2474 subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
2476 CCFLAGS=[subarch_flag, '-fPIC'],
2477 ASFLAGS=[subarch_flag],
2478 LINKFLAGS=[subarch_flag, '-fPIC'],
2479 CPPDEFINES = [['NACL_WINDOWS', '0'],
2481 ['NACL_LINUX', '0'],
2482 ['NACL_ANDROID', '0'],
2483 # defining _DARWIN_C_SOURCE breaks 10.4
2484 #['_DARWIN_C_SOURCE', '1'],
2485 #['__STDC_LIMIT_MACROS', '1']
2490 (mac_debug_env, mac_optimized_env) = GenerateOptimizationLevels(MakeMacEnv())
2493 def which(cmd, paths=os.environ.get('PATH', '').split(os.pathsep)):
2495 if os.access(os.path.join(p, cmd), os.X_OK):
2500 def SetUpLinuxEnvArm(env):
2501 jail = env.GetToolchainDir(toolchain_name='arm_trusted')
2502 if env.Bit('arm_hard_float'):
2503 arm_abi = 'gnueabihf'
2506 if not platform.machine().startswith('arm'):
2507 # Allow emulation on non-ARM hosts.
2508 env.Replace(EMULATOR=jail + '/run_under_qemu_arm')
2509 if env.Bit('built_elsewhere'):
2510 def FakeInstall(dest, source, env):
2511 print 'Not installing', dest
2512 # Replace build commands with no-ops
2513 env.Replace(CC='true', CXX='true', LD='true',
2514 AR='true', RANLIB='true', INSTALL=FakeInstall)
2517 for suffix in ['', '-4.5', '-4.6']:
2518 if which('arm-linux-%s-g++%s' % (arm_abi, suffix)):
2521 if arm_suffix is None:
2522 # This doesn't bail out completely here because we cannot
2523 # tell whether scons was run with just --mode=nacl, where
2524 # none of these settings will actually be used.
2525 print 'NOTE: arm trusted TC is not installed'
2526 bad = 'ERROR-missing-arm-trusted-toolchain'
2527 env.Replace(CC=bad, CXX=bad, LD=bad)
2530 env.Replace(CC='arm-linux-%s-gcc%s' % (arm_abi, arm_suffix),
2531 CXX='arm-linux-%s-g++%s' % (arm_abi, arm_suffix),
2532 LD='arm-linux-%s-ld%s' % (arm_abi, arm_suffix),
2534 LIBPATH=['${LIB_DIR}',
2535 '%s/usr/lib' % jail,
2537 '%s/usr/lib/arm-linux-%s' % (jail, arm_abi),
2538 '%s/lib/arm-linux-%s' % (jail, arm_abi),
2540 LINKFLAGS=['-Wl,-rpath-link=' + jail +
2541 '/lib/arm-linux-' + arm_abi]
2543 env.Prepend(CCFLAGS=['-march=armv7-a',
2544 '-marm', # force arm32
2546 if not env.Bit('android'):
2547 env.Prepend(CCFLAGS=['-isystem', jail + '/usr/include'])
2548 # /usr/lib makes sense for most configuration except this one
2549 # No ARM compatible libs can be found there.
2550 # So this just makes the command lines longer and sometimes results
2551 # in linker warnings referring to this directory.
2552 env.FilterOut(LIBPATH=['/usr/lib'])
2554 # get_plugin_dirname.cc has a dependency on dladdr
2555 env.Append(LIBS=['dl'])
2557 def SetUpAndroidEnv(env):
2558 env.FilterOut(CPPDEFINES=[['NACL_ANDROID', '0']])
2559 env.Prepend(CPPDEFINES=[['NACL_ANDROID', '1']])
2560 ndk = os.environ.get('ANDROID_NDK_ROOT')
2561 sdk = os.environ.get('ANDROID_SDK_ROOT')
2563 if env.Bit('build_arm'):
2564 ndk_target = 'arm-linux-androideabi'
2565 ndk_tctarget = ndk_target
2567 libarch = 'armeabi-v7a'
2568 arch_cflags += ['-march=armv7-a', '-mfloat-abi=softfp']
2569 elif env.Bit('build_mips32'):
2570 ndk_target = 'mipsel-linux-android'
2571 ndk_tctarget = ndk_target
2575 ndk_target = 'i686-linux-android'
2576 # x86 toolchain has strange location, not using GNU triplet
2577 ndk_tctarget = 'x86'
2581 if not ndk or not sdk:
2582 print 'Please define ANDROID_NDK_ROOT and ANDROID_SDK_ROOT'
2584 tc = '%s/toolchains/%s-%s/prebuilt/linux-x86_64/bin/' \
2585 % (ndk, ndk_tctarget, ndk_version)
2586 tc_prefix = '%s/%s-' % (tc, ndk_target)
2587 platform_prefix = '%s/platforms/android-14/arch-%s' % (ndk, arch)
2588 stl_path = '%s/sources/cxx-stl/gnu-libstdc++/%s' % (ndk, ndk_version)
2589 env.Replace(CC=tc_prefix + 'gcc',
2590 CXX=tc_prefix + 'g++',
2591 LD=tc_prefix + 'g++',
2592 EMULATOR=sdk + '/tools/emulator',
2593 LIBPATH=['${LIB_DIR}',
2594 '%s/libs/%s' % (stl_path, libarch),
2595 '%s/usr/lib' % (platform_prefix),
2597 LIBS=['gnustl_static', # Yes, that stdc++.
2602 # Second time, to have mutual libgcc<->libc deps resolved.
2606 env.Append(CCFLAGS=['--sysroot='+ platform_prefix,
2607 '-isystem='+ platform_prefix + '/usr/include',
2610 # Due to bogus warnings on uintptr_t formats.
2613 CXXFLAGS=['-I%s/include' % (stl_path),
2614 '-I%s/libs/%s/include' % (stl_path, libarch),
2618 LINKFLAGS=['-Wl,-rpath-link=' + platform_prefix + '/usr/lib',
2619 '-Wl,-Ttext,0x50000000',
2622 '-L%s/../lib/gcc/%s/%s' \
2623 % (tc, ndk_target, ndk_version),
2624 # Note that we have to use crtbegin_static.o
2625 # if compile -static, and crtbegin_dynamic.o
2626 # otherwise. Also, this apporach skips
2627 # all static initializers invocations.
2628 # TODO(olonho): implement proper static
2629 # initializers solution.
2630 platform_prefix + '/usr/lib/crtbegin_static.o',
2631 platform_prefix + '/usr/lib/crtend_android.o',
2634 # As we want static binary, not PIE.
2635 env.FilterOut(LINKFLAGS=['-pie'])
2638 def SetUpLinuxEnvMips(env):
2639 jail = env.GetToolchainDir(toolchain_name='mips_trusted')
2640 if not platform.machine().startswith('mips'):
2641 # Allow emulation on non-MIPS hosts.
2642 env.Replace(EMULATOR=jail + '/run_under_qemu_mips32')
2643 if env.Bit('built_elsewhere'):
2644 def FakeInstall(dest, source, env):
2645 print 'Not installing', dest
2646 # Replace build commands with no-ops
2647 env.Replace(CC='true', CXX='true', LD='true',
2648 AR='true', RANLIB='true', INSTALL=FakeInstall)
2650 tc_dir = os.path.join(jail, 'bin')
2651 if not which(os.path.join(tc_dir, 'mipsel-linux-gnu-gcc')):
2652 raise UserError("\nERRROR: "
2653 "MIPS trusted TC is not installed - try running:\n"
2654 "tools/trusted_cross_toolchains/trusted-toolchain-creator"
2655 ".mipsel.debian.sh nacl_sdk")
2656 env.Replace(CC=os.path.join(tc_dir, 'mipsel-linux-gnu-gcc'),
2657 CXX=os.path.join(tc_dir, 'mipsel-linux-gnu-g++'),
2658 LD=os.path.join(tc_dir, 'mipsel-linux-gnu-ld'),
2660 LIBPATH=['${LIB_DIR}',
2661 jail + '/sysroot/usr/lib'],
2663 os.path.join(jail, 'ld_script_mips_trusted')]
2666 env.Append(LIBS=['rt', 'dl', 'pthread'],
2667 CCFLAGS=['-march=mips32r2'])
2670 def MakeLinuxEnv(platform=None):
2671 linux_env = MakeUnixLikeEnv(platform).Clone(
2672 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-linux',
2673 BUILD_TYPE_DESCRIPTION = 'Linux ${OPTIMIZATION_LEVEL} build',
2674 tools = ['target_platform_linux'],
2675 # TODO(bradnelson): this should really be able to live in unix_like_env
2676 # but can't due to what the target_platform_x module is
2681 # Prepend so we can disable warnings via Append
2683 CPPDEFINES = [['NACL_WINDOWS', '0'],
2685 ['NACL_LINUX', '1'],
2686 ['NACL_ANDROID', '0'],
2687 ['_BSD_SOURCE', '1'],
2688 ['_POSIX_C_SOURCE', '199506'],
2689 ['_XOPEN_SOURCE', '600'],
2690 ['_GNU_SOURCE', '1'],
2691 ['_LARGEFILE64_SOURCE', '1'],
2696 if linux_env.Bit('build_x86_32'):
2699 LINKFLAGS = ['-m32'],
2701 elif linux_env.Bit('build_x86_64'):
2704 LINKFLAGS = ['-m64'],
2706 elif linux_env.Bit('build_arm'):
2707 SetUpLinuxEnvArm(linux_env)
2708 elif linux_env.Bit('build_mips32'):
2709 SetUpLinuxEnvMips(linux_env)
2711 Banner('Strange platform: %s' % GetTargetPlatform())
2713 # These are desireable options for every Linux platform:
2714 # _FORTIFY_SOURCE: general paranoia "hardening" option for library functions
2715 # -fPIE/-pie: create a position-independent executable
2716 # relro/now: "hardening" options for linking
2717 # noexecstack: ensure that the executable does not get a PT_GNU_STACK
2718 # header that causes the kernel to set the READ_IMPLIES_EXEC
2719 # personality flag, which disables NX page protection.
2721 CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']],
2722 LINKFLAGS=['-pie', '-Wl,-z,relro', '-Wl,-z,now', '-Wl,-z,noexecstack'],
2724 # The ARM toolchain has a linker that doesn't handle the code its
2725 # compiler generates under -fPIE.
2726 if linux_env.Bit('build_arm') or linux_env.Bit('build_mips32'):
2727 linux_env.Prepend(CCFLAGS=['-fPIC'])
2728 # TODO(mcgrathr): Temporarily punt _FORTIFY_SOURCE for ARM because
2729 # it causes a libc dependency newer than the old bots have installed.
2730 linux_env.FilterOut(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2732 linux_env.Prepend(CCFLAGS=['-fPIE'])
2734 # We always want to use the same flags for .S as for .c because
2735 # code-generation flags affect the predefines we might test there.
2736 linux_env.Replace(ASFLAGS=['${CCFLAGS}'])
2738 if linux_env.Bit('android'):
2739 SetUpAndroidEnv(linux_env)
2743 (linux_debug_env, linux_optimized_env) = \
2744 GenerateOptimizationLevels(MakeLinuxEnv())
2746 # Do this before the site_scons/site_tools/naclsdk.py stuff to pass it along.
2747 pre_base_env.Append(
2748 PNACL_BCLDFLAGS = ARGUMENTS.get('pnacl_bcldflags', '').split(':'))
2751 # The nacl_env is used to build native_client modules
2752 # using a special tool chain which produces platform
2753 # independent binaries
2754 # NOTE: this loads stuff from: site_scons/site_tools/naclsdk.py
2755 nacl_env = MakeArchSpecificEnv()
2756 nacl_env = nacl_env.Clone(
2757 tools = ['naclsdk'],
2758 NACL_BUILD_FAMILY = 'UNTRUSTED',
2759 BUILD_TYPE = 'nacl',
2760 BUILD_TYPE_DESCRIPTION = 'NaCl module build',
2764 # ${SOURCE_ROOT} for #include <ppapi/...>
2770 EXTRA_CXXFLAGS = [],
2772 EXTRA_LINKFLAGS = ARGUMENTS.get('nacl_linkflags', '').split(':'),
2774 # always optimize binaries
2777 '-fomit-frame-pointer',
2778 # This makes sure unwind/backtrace info is available for
2779 # all code locations. Note build/untrusted.gypi uses it too.
2780 '-fasynchronous-unwind-tables',
2783 '-fdiagnostics-show-option',
2788 CFLAGS = ['-std=gnu99',
2790 CXXFLAGS = ['-std=gnu++98',
2794 # This magic is copied from scons-2.0.1/engine/SCons/Defaults.py
2795 # where this pattern is used for _LIBDIRFLAGS, which produces -L
2796 # switches. Here we are producing a -Wl,-rpath-link,DIR for each
2797 # element of LIBPATH, i.e. for each -LDIR produced.
2798 RPATH_LINK_FLAGS = '$( ${_concat(RPATHLINKPREFIX, LIBPATH, RPATHLINKSUFFIX,'
2799 '__env__, RDirs, TARGET, SOURCE)} $)',
2800 RPATHLINKPREFIX = '-Wl,-rpath-link,',
2801 RPATHLINKSUFFIX = '',
2804 LINKFLAGS = ['${RPATH_LINK_FLAGS}'],
2806 # These are settings for in-tree, non-browser tests to use.
2807 # They use libraries that circumvent the IRT-based implementations
2808 # in the public libraries.
2809 # Note that pthread_private is part of NONIRT_LIBS for PNaCl because
2810 # libc++ depends on it.
2811 NONIRT_LIBS = (['nacl_sys_private'] +
2812 (['pthread_private'] if nacl_env.Bit('bitcode') else [])),
2813 PTHREAD_LIBS = ['pthread_private'],
2814 DYNCODE_LIBS = ['nacl_dyncode_private'],
2815 EXCEPTION_LIBS = ['nacl_exception_private'],
2816 LIST_MAPPINGS_LIBS = ['nacl_list_mappings_private'],
2819 def UsesAbiNote(env):
2820 """Return True if using a new-style GCC with .note.NaCl.ABI.* notes.
2821 This means there will always be an RODATA segment, even if just for the note."""
2822 return env.Bit('target_arm') and not env.Bit('bitcode')
2824 nacl_env.AddMethod(UsesAbiNote)
2826 def UnderWindowsCoverage(env):
2827 """Return True if using running on coverage under windows."""
2828 if 'TRUSTED_ENV' not in env:
2830 return env['TRUSTED_ENV'].Bit('coverage_enabled') and env.Bit('host_windows')
2832 nacl_env.AddMethod(UnderWindowsCoverage)
2834 def AllowNonStableBitcode(env):
2835 """ This modifies the environment to allow features that aren't part
2836 of PNaCl's stable ABI. If tests using these features should be
2837 skipped entirely, this returns False. Otherwise, on success, it
2840 if env.Bit('bitcode'):
2841 env.SetBits('nonstable_bitcode')
2842 return not env.Bit('skip_nonstable_bitcode')
2844 nacl_env.AddMethod(AllowNonStableBitcode)
2847 def AllowInlineAssembly(env):
2848 """ This modifies the environment to allow inline assembly in
2849 untrusted code. If the environment cannot be modified to allow
2850 inline assembly, it returns False. Otherwise, on success, it
2853 if env.Bit('bitcode'):
2854 # For each architecture, we only attempt to make our inline
2855 # assembly code work with one untrusted-code toolchain. For x86,
2856 # we target GCC, but not PNaCl/Clang, because the latter's
2857 # assembly support has various quirks that we don't want to have
2858 # to debug. For ARM, we target PNaCl/Clang, because that is the
2859 # only current ARM toolchain. One day, we will have an ARM GCC
2860 # toolchain, and we will no longer need to use inline assembly
2861 # with PNaCl/Clang at all.
2862 if not (env.Bit('target_arm') or env.Bit('target_mips32')):
2864 # Inline assembly does not work in pexes.
2865 if env.Bit('pnacl_generate_pexe'):
2867 env.AddBiasForPNaCl()
2868 env.PNaClForceNative()
2871 nacl_env.AddMethod(AllowInlineAssembly)
2874 # TODO(mseaborn): Enable this unconditionally once the C code on the
2875 # Chromium side compiles successfully with this warning.
2876 if not enable_chrome:
2877 nacl_env.Append(CFLAGS=['-Wstrict-prototypes'])
2879 # This is the address at which a user executable is expected to place its
2880 # data segment in order to be compatible with the integrated runtime (IRT)
2881 # library. This address should not be changed lightly.
2882 irt_compatible_rodata_addr = 0x10000000
2883 # This is the address at which the IRT's own code will be located.
2884 # It must be below irt_compatible_rodata and leave enough space for
2885 # the code segment of the IRT. It should be as close as possible to
2886 # irt_compatible_rodata so as to leave the maximum contiguous area
2887 # available for the dynamic code loading area that falls below it.
2888 # This can be adjusted as necessary for the actual size of the IRT code.
2889 irt_code_addr = irt_compatible_rodata_addr - (6 << 20) # max 6M IRT code
2890 # This is the address at which the IRT's own data will be located. The
2891 # 32-bit sandboxes limit the address space to 1GB; the initial thread's
2892 # stack sits at the top of the address space and extends down for
2893 # NACL_DEFAULT_STACK_MAX (src/trusted/service_runtime/sel_ldr.h) below.
2894 # So this must be below there, and leave enough space for the IRT's own
2895 # data segment. It should be as high as possible so as to leave the
2896 # maximum contiguous area available for the user's data and break below.
2897 # This can be adjusted as necessary for the actual size of the IRT data
2898 # (that is RODATA, rounded up to 64k, plus writable data).
2899 # 1G (address space) - 16M (NACL_DEFAULT_STACK_MAX) - 1MB (IRT rodata+data)
2900 irt_data_addr = (1 << 30) - (16 << 20) - (1 << 20)
2903 IRT_DATA_REGION_START = '%#.8x' % irt_compatible_rodata_addr,
2904 # Load addresses of the IRT's code and data segments.
2905 IRT_BLOB_CODE_START = '%#.8x' % irt_code_addr,
2906 IRT_BLOB_DATA_START = '%#.8x' % irt_data_addr,
2909 def TestsUsePublicListMappingsLib(env):
2910 """Use the public list_mappings library for in-tree tests."""
2911 env.Replace(LIST_MAPPINGS_LIBS=['nacl_list_mappings'])
2913 def TestsUsePublicLibs(env):
2914 """Change the environment so it uses public libraries for in-tree tests."""
2915 env.Replace(NONIRT_LIBS=['pthread'] if env.Bit('bitcode') else [],
2916 PTHREAD_LIBS=['pthread'],
2917 DYNCODE_LIBS=['nacl_dyncode', 'nacl'],
2918 EXCEPTION_LIBS=['nacl_exception', 'nacl'])
2920 # glibc is incompatible with libpthread_private and libnacl_sys_private.
2921 if nacl_env.Bit('nacl_glibc'):
2922 nacl_env.Replace(NONIRT_LIBS=[],
2923 PTHREAD_LIBS=['pthread'])
2925 # These add on to those set in pre_base_env, above.
2928 # This ensures that UINT32_MAX gets defined.
2929 ['__STDC_LIMIT_MACROS', '1'],
2930 # This ensures that PRId64 etc. get defined.
2931 ['__STDC_FORMAT_MACROS', '1'],
2932 # _GNU_SOURCE ensures that strtof() gets declared.
2934 # strdup, and other common stuff
2935 ['_BSD_SOURCE', '1'],
2936 ['_POSIX_C_SOURCE', '199506'],
2937 ['_XOPEN_SOURCE', '600'],
2939 ['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
2940 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ],
2942 ['NACL_WINDOWS', '0'],
2944 ['NACL_LINUX', '0'],
2945 ['NACL_ANDROID', '0'],
2949 def FixWindowsAssembler(env):
2950 if env.Bit('host_windows'):
2951 # NOTE: This is needed because Windows builds are case-insensitive.
2952 # Without this we use nacl-as, which doesn't handle include directives, etc.
2953 env.Replace(ASCOM='${CCCOM}')
2955 FixWindowsAssembler(nacl_env)
2957 # Look in the local include and lib directories before the toolchain's.
2958 nacl_env['INCLUDE_DIR'] = '${TARGET_ROOT}/include'
2959 # Remove the default $LIB_DIR element so that we prepend it without duplication.
2960 # Using PrependUnique alone would let it stay last, where we want it first.
2961 nacl_env.FilterOut(LIBPATH=['${LIB_DIR}'])
2962 nacl_env.PrependUnique(
2963 CPPPATH = ['${INCLUDE_DIR}'],
2964 LIBPATH = ['${LIB_DIR}'],
2967 if nacl_env.Bit('bitcode'):
2968 # passing -O when linking requests LTO, which does additional global
2969 # optimizations at link time
2970 nacl_env.Append(LINKFLAGS=['-O3'])
2971 if not nacl_env.Bit('nacl_glibc'):
2972 nacl_env.Append(LINKFLAGS=['-static'])
2974 if nacl_env.Bit('translate_fast'):
2975 nacl_env.Append(LINKFLAGS=['-Xlinker', '-translate-fast'])
2976 nacl_env.Append(TRANSLATEFLAGS=['-translate-fast'])
2978 # With pnacl's clang base/ code uses the "override" keyword.
2979 nacl_env.Append(CXXFLAGS=['-Wno-c++11-extensions'])
2980 # Allow extraneous semicolons. (Until these are removed.)
2981 # http://code.google.com/p/nativeclient/issues/detail?id=2861
2982 nacl_env.Append(CCFLAGS=['-Wno-extra-semi'])
2983 # Allow unused private fields. (Until these are removed.)
2984 # http://code.google.com/p/nativeclient/issues/detail?id=2861
2985 nacl_env.Append(CCFLAGS=['-Wno-unused-private-field'])
2987 # We use a special environment for building the IRT image because it must
2988 # always use the newlib toolchain, regardless of --nacl_glibc. We clone
2989 # it from nacl_env here, before too much other cruft has been added.
2990 # We do some more magic below to instantiate it the way we need it.
2991 nacl_irt_env = nacl_env.Clone(
2992 BUILD_TYPE = 'nacl_irt',
2993 BUILD_TYPE_DESCRIPTION = 'NaCl IRT build',
2994 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT',
2997 # Provide access to the IRT build environment from the default environment
2998 # which is needed when compiling custom IRT for testing purposes.
2999 nacl_env['NACL_IRT_ENV'] = nacl_irt_env
3001 # Since we don't build src/untrusted/pthread/nacl.scons in
3002 # nacl_irt_env, we must tell the IRT how to find the pthread.h header.
3003 nacl_irt_env.Append(CPPPATH='${MAIN_DIR}/src/untrusted/pthread')
3005 # Map certain flag bits to suffices on the build output. This needs to
3006 # happen pretty early, because it affects any concretized directory names.
3007 target_variant_map = [
3008 ('bitcode', 'pnacl'),
3009 ('translate_fast', 'fast'),
3010 ('nacl_pic', 'pic'),
3011 ('use_sandboxed_translator', 'sbtc'),
3012 ('nacl_glibc', 'glibc'),
3013 ('pnacl_generate_pexe', 'pexe'),
3015 for variant_bit, variant_suffix in target_variant_map:
3016 if nacl_env.Bit(variant_bit):
3017 nacl_env['TARGET_VARIANT'] += '-' + variant_suffix
3019 if nacl_env.Bit('bitcode'):
3020 nacl_env['TARGET_VARIANT'] += '-clang'
3022 nacl_env.Replace(TESTRUNNER_LIBS=['testrunner'])
3023 # TODO(mseaborn): Drop this once chrome side has inlined this.
3024 nacl_env.Replace(PPAPI_LIBS=['ppapi'])
3026 # TODO(mseaborn): Make nacl-glibc-based static linking work with just
3027 # "-static", without specifying a linker script.
3028 # See http://code.google.com/p/nativeclient/issues/detail?id=1298
3029 def GetLinkerScriptBaseName(env):
3030 if env.Bit('build_x86_64'):
3031 return 'elf_x86_64_nacl'
3033 return 'elf_i386_nacl'
3035 if (nacl_env.Bit('nacl_glibc') and
3036 nacl_env.Bit('nacl_static_link')):
3037 nacl_env.Append(LINKFLAGS=['-static'])
3038 if nacl_env.Bit('target_x86'):
3039 # The "-lc" is necessary because libgcc_eh depends on libc but for
3040 # some reason nacl-gcc is not linking with "--start-group/--end-group".
3041 nacl_env.Append(LINKFLAGS=[
3042 '-T', 'ldscripts/%s.x.static' % GetLinkerScriptBaseName(nacl_env),
3045 if nacl_env.Bit('running_on_valgrind'):
3046 nacl_env.Append(CCFLAGS = ['-g', '-Wno-overlength-strings',
3047 '-fno-optimize-sibling-calls'],
3048 CPPDEFINES = [['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3049 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ]])
3050 # With GLibC, libvalgrind.so is preloaded at runtime.
3051 # With Newlib, it has to be linked in.
3052 if not nacl_env.Bit('nacl_glibc'):
3053 nacl_env.Append(LINKFLAGS = ['-Wl,-u,have_nacl_valgrind_interceptors'],
3054 LIBS = ['valgrind'])
3056 environment_list.append(nacl_env)
3058 if not nacl_env.Bit('nacl_glibc'):
3059 # These are all specific to nacl-newlib so we do not include them
3060 # when building against nacl-glibc. The functionality of
3061 # pthread/startup/stubs/nosys is provided by glibc. The valgrind
3062 # code currently assumes nc_threads.
3064 BUILD_SCONSCRIPTS = [
3065 #### ALPHABETICALLY SORTED ####
3066 'src/untrusted/pthread/nacl.scons',
3067 'src/untrusted/stubs/nacl.scons',
3068 'src/untrusted/nosys/nacl.scons',
3069 #### ALPHABETICALLY SORTED ####
3072 BUILD_SCONSCRIPTS = [
3073 #### ALPHABETICALLY SORTED ####
3074 'src/shared/gio/nacl.scons',
3075 'src/shared/imc/nacl.scons',
3076 'src/shared/ldr/nacl.scons',
3077 'src/shared/platform/nacl.scons',
3078 'src/shared/srpc/nacl.scons',
3079 'src/trusted/service_runtime/nacl.scons',
3080 'src/trusted/validator/nacl.scons',
3081 'src/trusted/weak_ref/nacl.scons',
3082 'src/untrusted/crash_dump/nacl.scons',
3083 'src/untrusted/minidump_generator/nacl.scons',
3084 'src/untrusted/nacl/nacl.scons',
3085 'src/untrusted/valgrind/nacl.scons',
3086 #### ALPHABETICALLY SORTED ####
3088 nacl_env.AddChromeFilesFromGroup('untrusted_scons_files')
3090 # These are tests that are worthwhile to run in IRT variant only.
3092 #### ALPHABETICALLY SORTED ####
3093 'tests/irt/nacl.scons',
3094 'tests/irt_compatibility/nacl.scons',
3095 'tests/random/nacl.scons',
3096 'tests/sbrk/nacl.scons',
3097 'tests/translator_size_limits/nacl.scons',
3100 # These are tests that are worthwhile to run in both IRT and non-IRT variants.
3101 # The nacl_irt_test mode runs them in the IRT variants.
3102 irt_variant_tests = [
3103 #### ALPHABETICALLY SORTED ####
3104 'tests/app_lib/nacl.scons',
3105 'tests/bigalloc/nacl.scons',
3106 'tests/callingconv/nacl.scons',
3107 'tests/callingconv_ppapi/nacl.scons',
3108 'tests/callingconv_case_by_case/nacl.scons',
3109 'tests/clock/nacl.scons',
3110 'tests/common/nacl.scons',
3111 'tests/compiler_thread_suspension/nacl.scons',
3112 'tests/computed_gotos/nacl.scons',
3113 'tests/data_below_data_start/nacl.scons',
3114 'tests/data_not_executable/nacl.scons',
3115 'tests/debug_stub/nacl.scons',
3116 'tests/dup/nacl.scons',
3117 'tests/dynamic_code_loading/nacl.scons',
3118 'tests/dynamic_linking/nacl.scons',
3119 'tests/egyptian_cotton/nacl.scons',
3120 'tests/environment_variables/nacl.scons',
3121 'tests/exception_test/nacl.scons',
3122 'tests/fib/nacl.scons',
3123 'tests/file/nacl.scons',
3124 'tests/fixedfeaturecpu/nacl.scons',
3125 'tests/futexes/nacl.scons',
3126 'tests/gc_instrumentation/nacl.scons',
3127 'tests/gdb/nacl.scons',
3128 'tests/glibc_file64_test/nacl.scons',
3129 'tests/glibc_static_test/nacl.scons',
3130 'tests/glibc_syscall_wrappers/nacl.scons',
3131 'tests/glibc_socket_wrappers/nacl.scons',
3132 'tests/hello_world/nacl.scons',
3133 'tests/imc_shm_mmap/nacl.scons',
3134 'tests/infoleak/nacl.scons',
3135 'tests/libc/nacl.scons',
3136 'tests/libc_free_hello_world/nacl.scons',
3137 'tests/list_mappings/nacl.scons',
3138 'tests/longjmp/nacl.scons',
3139 'tests/loop/nacl.scons',
3140 'tests/mandel/nacl.scons',
3141 'tests/manifest_file/nacl.scons',
3142 'tests/math/nacl.scons',
3143 'tests/memcheck_test/nacl.scons',
3144 'tests/mmap/nacl.scons',
3145 'tests/mmap_main_nexe/nacl.scons',
3146 'tests/mmap_prot_exec/nacl.scons',
3147 'tests/mmap_race_protect/nacl.scons',
3148 'tests/nacl_log/nacl.scons',
3149 'tests/nameservice/nacl.scons',
3150 'tests/nanosleep/nacl.scons',
3151 'tests/noop/nacl.scons',
3152 'tests/nrd_xfer/nacl.scons',
3153 'tests/nthread_nice/nacl.scons',
3154 'tests/null/nacl.scons',
3155 'tests/nullptr/nacl.scons',
3156 'tests/pagesize/nacl.scons',
3157 'tests/performance/nacl.scons',
3158 'tests/pnacl_abi/nacl.scons',
3159 'tests/pnacl_native_objects/nacl.scons',
3160 'tests/process_create/nacl.scons',
3161 'tests/redir/nacl.scons',
3162 'tests/rodata_not_writable/nacl.scons',
3163 'tests/sel_ldr/nacl.scons',
3164 'tests/sel_ldr_seccomp/nacl.scons',
3165 'tests/sel_main_chrome/nacl.scons',
3166 'tests/signal_handler/nacl.scons',
3167 'tests/simd/nacl.scons',
3168 'tests/sleep/nacl.scons',
3169 'tests/srpc/nacl.scons',
3170 'tests/srpc_hw/nacl.scons',
3171 'tests/srpc_message/nacl.scons',
3172 'tests/stack_alignment/nacl.scons',
3173 'tests/stubout_mode/nacl.scons',
3174 'tests/subprocess/nacl.scons',
3175 'tests/sysbasic/nacl.scons',
3176 'tests/syscall_return_regs/nacl.scons',
3177 'tests/syscall_return_sandboxing/nacl.scons',
3178 'tests/syscalls/nacl.scons',
3179 'tests/thread_capture/nacl.scons',
3180 'tests/threads/nacl.scons',
3181 'tests/time/nacl.scons',
3182 'tests/tls/nacl.scons',
3183 'tests/tls_perf/nacl.scons',
3184 'tests/tls_segment_x86_32/nacl.scons',
3185 'tests/toolchain/nacl.scons',
3186 'tests/toolchain/arm/nacl.scons',
3187 'tests/toolchain/mips/nacl.scons',
3188 'tests/unittests/shared/platform/nacl.scons',
3189 'tests/untrusted_check/nacl.scons',
3190 'tests/unwind_restores_regs/nacl.scons',
3191 #### ALPHABETICALLY SORTED ####
3192 # NOTE: The following tests are really IRT-only tests, but they
3193 # are in this category so that they can generate libraries (which
3194 # works in nacl_env but not in nacl_irt_test_env) while also
3195 # adding tests to nacl_irt_test_env.
3196 'tests/inbrowser_test_runner/nacl.scons',
3197 'tests/untrusted_crash_dump/nacl.scons',
3198 'tests/untrusted_minidump/nacl.scons',
3201 # These are tests that are NOT worthwhile to run in an IRT variant.
3202 # In some cases, that's because they are browser tests which always
3203 # use the IRT. In others, it's because they are special-case tests
3204 # that are incompatible with having an IRT loaded.
3205 nonvariant_tests = [
3206 #### ALPHABETICALLY SORTED ####
3207 'tests/barebones/nacl.scons',
3208 'tests/chrome_extension/nacl.scons',
3209 'tests/custom_desc/nacl.scons',
3210 'tests/faulted_thread_queue/nacl.scons',
3211 'tests/imc_sockets/nacl.scons',
3212 'tests/minnacl/nacl.scons',
3213 'tests/multiple_sandboxes/nacl.scons',
3214 # Potential issue with running them:
3215 # http://code.google.com/p/nativeclient/issues/detail?id=2092
3216 # See also the comment in "buildbot/buildbot_standard.py"
3217 'tests/pnacl_shared_lib_test/nacl.scons',
3218 'tests/pwrite/nacl.scons',
3219 'tests/signal_handler_single_step/nacl.scons',
3220 'tests/thread_suspension/nacl.scons',
3221 'tests/trusted_crash/crash_in_syscall/nacl.scons',
3222 'tests/trusted_crash/osx_crash_filter/nacl.scons',
3223 'tests/trusted_crash/osx_crash_forwarding/nacl.scons',
3224 'tests/unittests/shared/imc/nacl.scons',
3225 'tests/unittests/shared/srpc/nacl.scons',
3226 #### ALPHABETICALLY SORTED ####
3229 nacl_env.Append(BUILD_SCONSCRIPTS=nonvariant_tests)
3230 nacl_env.AddChromeFilesFromGroup('nonvariant_test_scons_files')
3231 nacl_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3232 nacl_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3234 # Defines TESTS_TO_RUN_INBROWSER.
3235 SConscript('tests/inbrowser_test_runner/selection.scons',
3236 exports=['nacl_env'])
3238 # Possibly install a toolchain by downloading it
3239 # TODO: explore using a less heavy weight mechanism
3240 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3243 SCons.Script.AddOption('--download',
3247 action='store_true',
3248 help='deprecated - allow tools to download')
3250 if nacl_env.GetOption('download'):
3251 print '@@@@ --download is deprecated, use gclient runhooks --force'
3252 nacl_sync_env = nacl_env.Clone()
3253 nacl_sync_env['ENV'] = os.environ
3254 nacl_sync_env.Execute('gclient runhooks --force')
3257 def NaClSharedLibrary(env, lib_name, *args, **kwargs):
3258 env_shared = env.Clone(COMPONENT_STATIC=False)
3259 soname = SCons.Util.adjustixes(lib_name, 'lib', '.so')
3260 env_shared.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s' % (soname)])
3261 return env_shared.ComponentLibrary(lib_name, *args, **kwargs)
3263 nacl_env.AddMethod(NaClSharedLibrary)
3265 def NaClSdkLibrary(env, lib_name, *args, **kwargs):
3266 n = [env.ComponentLibrary(lib_name, *args, **kwargs)]
3267 if not env.Bit('nacl_disable_shared'):
3268 n.append(env.NaClSharedLibrary(lib_name, *args, **kwargs))
3271 nacl_env.AddMethod(NaClSdkLibrary)
3274 # Special environment for untrusted test binaries that use raw syscalls
3275 def RawSyscallObjects(env, sources):
3276 raw_syscall_env = env.Clone()
3277 raw_syscall_env.Append(
3279 ['USE_RAW_SYSCALLS', '1'],
3280 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}' ],
3281 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}' ],
3282 ['NACL_TARGET_ARCH', '${TARGET_ARCHITECTURE}' ],
3283 ['NACL_TARGET_SUBARCH', '${TARGET_SUBARCH}' ],
3287 for source_file in sources:
3288 target_name = 'raw_' + os.path.basename(source_file).rstrip('.c')
3289 object = raw_syscall_env.ComponentObject(target_name,
3291 objects.append(object)
3294 nacl_env.AddMethod(RawSyscallObjects)
3297 # The IRT-building environment was cloned from nacl_env, but it should
3298 # ignore the --nacl_glibc, nacl_pic=1 and bitcode=1 switches.
3299 # We have to reinstantiate the naclsdk.py magic after clearing those flags,
3300 # so it regenerates the tool paths right.
3301 # TODO(mcgrathr,bradnelson): could get cleaner if naclsdk.py got folded back in.
3302 nacl_irt_env.ClearBits('nacl_glibc')
3303 nacl_irt_env.ClearBits('nacl_pic')
3304 # We build the IRT using the nnacl TC even when the pnacl TC is used otherwise.
3305 if nacl_irt_env.Bit('target_mips32') or nacl_irt_env.Bit('target_x86_64'):
3306 nacl_irt_env.SetBits('bitcode')
3308 nacl_irt_env.ClearBits('bitcode')
3309 nacl_irt_env.ClearBits('pnacl_generate_pexe')
3310 nacl_irt_env.ClearBits('use_sandboxed_translator')
3311 nacl_irt_env.Tool('naclsdk')
3312 # These are unfortunately clobbered by running Tool, which
3313 # we needed to do to get the destination directory reset.
3314 # We want all the same values from nacl_env.
3315 nacl_irt_env.Replace(EXTRA_CFLAGS=nacl_env['EXTRA_CFLAGS'],
3316 EXTRA_CXXFLAGS=nacl_env['EXTRA_CXXFLAGS'],
3317 CCFLAGS=nacl_env['CCFLAGS'],
3318 CFLAGS=nacl_env['CFLAGS'],
3319 CXXFLAGS=nacl_env['CXXFLAGS'])
3320 FixWindowsAssembler(nacl_irt_env)
3321 # Make it find the libraries it builds, rather than the SDK ones.
3322 nacl_irt_env.Replace(LIBPATH='${LIB_DIR}')
3324 if nacl_irt_env.Bit('bitcode'):
3325 if nacl_irt_env.Bit('target_x86_64'):
3326 nacl_irt_env.Append(CCFLAGS=['--target=x86_64-nacl'])
3327 nacl_irt_env.Append(LINKFLAGS=['--target=x86_64-nacl',
3328 '--pnacl-allow-translate',
3331 # The IRT is C only, don't link with the C++ linker so that it doesn't
3332 # start depending on the C++ standard library and (in the case of
3334 nacl_irt_env.Replace(LINK=(nacl_irt_env['LINK'].
3335 replace('pnacl-clang++', 'pnacl-clang')))
3337 if nacl_irt_env.Bit('bitcode'):
3338 nacl_irt_env.Append(LINKFLAGS=['--pnacl-allow-native'])
3340 # All IRT code must avoid direct use of the TLS ABI register, which
3341 # is reserved for user TLS. Instead, ensure all TLS accesses use a
3342 # call to __nacl_read_tp, which the IRT code overrides to segregate
3343 # IRT-private TLS from user TLS. This only applies to mips now, on
3344 # other platforms we modify the TLS register through tls_edit as a
3346 if nacl_irt_env.Bit('target_mips32'):
3347 nacl_irt_env.Append(LINKFLAGS=['-Wt,-mtls-use-call'])
3349 # TODO(mcgrathr): Clean up uses of these methods.
3350 def AddLibraryDummy(env, nodes):
3352 nacl_irt_env.AddMethod(AddLibraryDummy, 'AddLibraryToSdk')
3354 def AddObjectInternal(env, nodes):
3355 return env.Replicate('${LIB_DIR}', nodes)
3356 nacl_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3357 nacl_irt_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3359 def IrtNaClSdkLibrary(env, lib_name, *args, **kwargs):
3360 env.ComponentLibrary(lib_name, *args, **kwargs)
3361 nacl_irt_env.AddMethod(IrtNaClSdkLibrary, 'NaClSdkLibrary')
3363 nacl_irt_env.AddMethod(SDKInstallBin)
3365 # Populate the internal include directory when AddHeaderToSdk
3366 # is used inside nacl_env.
3367 def AddHeaderInternal(env, nodes, subdir='nacl'):
3368 dir = '${INCLUDE_DIR}'
3369 if subdir is not None:
3371 n = env.Replicate(dir, nodes)
3374 nacl_irt_env.AddMethod(AddHeaderInternal, 'AddHeaderToSdk')
3376 def PublishHeader(env, nodes, subdir):
3377 if ('install' in COMMAND_LINE_TARGETS or
3378 'install_headers' in COMMAND_LINE_TARGETS):
3379 dir = env.GetAbsDirArg('includedir', 'install_headers')
3380 if subdir is not None:
3382 n = env.Install(dir, nodes)
3383 env.Alias('install', env.Alias('install_headers', n))
3386 def PublishLibrary(env, nodes):
3387 env.Alias('build_lib', nodes)
3389 if ('install' in COMMAND_LINE_TARGETS or
3390 'install_lib' in COMMAND_LINE_TARGETS):
3391 dir = env.GetAbsDirArg('libdir', 'install_lib')
3392 n = env.Install(dir, nodes)
3393 env.Alias('install', env.Alias('install_lib', n))
3396 def NaClAddHeader(env, nodes, subdir='nacl'):
3397 n = AddHeaderInternal(env, nodes, subdir)
3398 PublishHeader(env, n, subdir)
3400 nacl_env.AddMethod(NaClAddHeader, 'AddHeaderToSdk')
3402 def NaClAddLibrary(env, nodes):
3403 nodes = env.Replicate('${LIB_DIR}', nodes)
3404 PublishLibrary(env, nodes)
3406 nacl_env.AddMethod(NaClAddLibrary, 'AddLibraryToSdk')
3408 def NaClAddObject(env, nodes):
3409 lib_nodes = env.Replicate('${LIB_DIR}', nodes)
3410 PublishLibrary(env, lib_nodes)
3412 nacl_env.AddMethod(NaClAddObject, 'AddObjectToSdk')
3414 # We want to do this for nacl_env when not under --nacl_glibc,
3415 # but for nacl_irt_env whether or not under --nacl_glibc, so
3416 # we do it separately for each after making nacl_irt_env and
3417 # clearing its Bit('nacl_glibc').
3418 def AddImplicitLibs(env):
3421 # Require the pnacl_irt_shim for pnacl x86-64 and arm.
3422 # Use -B to have the compiler look for the fresh libpnacl_irt_shim.a.
3423 if ( env.Bit('bitcode') and
3424 (env.Bit('target_x86_64') or env.Bit('target_arm'))
3425 and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT'):
3426 # Note: without this hack ibpnacl_irt_shim.a will be deleted
3427 # when "built_elsewhere=1"
3428 # Since we force the build in a previous step the dependency
3429 # is not really needed.
3430 # Note: the "precious" mechanism did not work in this case
3431 if not env.Bit('built_elsewhere'):
3432 if env.Bit('enable_chrome_side'):
3433 implicit_libs += ['libpnacl_irt_shim.a']
3435 if not env.Bit('nacl_glibc'):
3436 # These are automatically linked in by the compiler, either directly
3437 # or via the linker script that is -lc. In the non-glibc build, we
3438 # are the ones providing these files, so we need dependencies.
3439 # The ComponentProgram method (site_scons/site_tools/component_builders.py)
3440 # adds dependencies on env['IMPLICIT_LIBS'] if that's set.
3441 if env.Bit('bitcode'):
3442 implicit_libs += ['libnacl.a']
3444 implicit_libs += ['crt1.o',
3448 # TODO(mcgrathr): multilib nonsense defeats -B! figure out a better way.
3449 if GetTargetPlatform() == 'x86-32':
3450 implicit_libs.append(os.path.join('32', 'crt1.o'))
3452 if implicit_libs != []:
3453 env['IMPLICIT_LIBS'] = [env.File(os.path.join('${LIB_DIR}', file))
3454 for file in implicit_libs]
3455 # The -B<dir>/ flag is necessary to tell gcc to look for crt[1in].o there.
3456 env.Prepend(LINKFLAGS=['-B${LIB_DIR}/'])
3458 AddImplicitLibs(nacl_env)
3459 AddImplicitLibs(nacl_irt_env)
3461 nacl_irt_env.Append(
3462 BUILD_SCONSCRIPTS = [
3463 'src/shared/gio/nacl.scons',
3464 'src/shared/platform/nacl.scons',
3465 'src/shared/srpc/nacl.scons',
3466 'src/tools/tls_edit/build.scons',
3467 'src/untrusted/irt/nacl.scons',
3468 'src/untrusted/nacl/nacl.scons',
3469 'src/untrusted/stubs/nacl.scons',
3470 'tests/irt_private_pthread/nacl.scons',
3472 nacl_irt_env.AddChromeFilesFromGroup('untrusted_irt_scons_files')
3474 environment_list.append(nacl_irt_env)
3476 # Since browser_tests already use the IRT normally, those are fully covered
3477 # in nacl_env. But the non_browser_tests don't use the IRT in nacl_env.
3478 # We want additional variants of those tests with the IRT, so we make
3479 # another environment and repeat them with that adjustment.
3480 nacl_irt_test_env = nacl_env.Clone(
3481 BUILD_TYPE = 'nacl_irt_test',
3482 BUILD_TYPE_DESCRIPTION = 'NaCl tests build with IRT',
3483 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT_TESTS',
3485 INCLUDE_DIR = nacl_env.Dir('${INCLUDE_DIR}'),
3486 LIB_DIR = nacl_env.Dir('${LIB_DIR}'),
3487 BUILD_SCONSCRIPTS = [],
3489 nacl_irt_test_env.SetBits('tests_use_irt')
3490 if nacl_irt_test_env.Bit('enable_chrome_side'):
3491 nacl_irt_test_env.Replace(TESTRUNNER_LIBS=['testrunner_browser'])
3493 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3494 nacl_irt_test_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3495 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_only_tests)
3496 TestsUsePublicLibs(nacl_irt_test_env)
3497 TestsUsePublicListMappingsLib(nacl_irt_test_env)
3499 # If a tests/.../nacl.scons file builds a library, we will just use
3500 # the one already built in nacl_env instead.
3501 def IrtTestDummyLibrary(*args, **kwargs):
3503 nacl_irt_test_env.AddMethod(IrtTestDummyLibrary, 'ComponentLibrary')
3505 def IrtTestAddNodeToTestSuite(env, node, suite_name, node_name=None,
3506 is_broken=False, is_flaky=False,
3507 disable_irt_suffix=False):
3508 # The disable_irt_suffix argument is there for allowing tests
3509 # defined in nacl_irt_test_env to be part of chrome_browser_tests
3510 # (rather than part of chrome_browser_tests_irt).
3511 # TODO(mseaborn): But really, all of chrome_browser_tests should be
3512 # placed in nacl_irt_test_env rather than in nacl_env.
3513 if not disable_irt_suffix:
3514 if node_name is not None:
3516 suite_name = [name + '_irt' for name in suite_name]
3517 # NOTE: This needs to be called directly to as we're overriding the
3519 return AddNodeToTestSuite(env, node, suite_name, node_name,
3520 is_broken, is_flaky)
3521 nacl_irt_test_env.AddMethod(IrtTestAddNodeToTestSuite, 'AddNodeToTestSuite')
3523 environment_list.append(nacl_irt_test_env)
3526 windows_coverage_env = windows_debug_env.Clone(
3527 tools = ['code_coverage'],
3528 BUILD_TYPE = 'coverage-win',
3529 BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
3530 # TODO(bradnelson): switch nacl to common testing process so this won't be
3532 MANIFEST_FILE = None,
3533 COVERAGE_ANALYZER_DIR=r'..\third_party\coverage_analyzer\bin',
3534 COVERAGE_ANALYZER='$COVERAGE_ANALYZER_DIR\coverage_analyzer.exe',
3536 # TODO(bradnelson): Switch nacl to common testing process so this won't be
3537 # needed. Ignoring instrumentation failure as that's easier
3538 # than trying to gate out the ones with asm we can't handle.
3539 windows_coverage_env['LINKCOM'] = windows_coverage_env.Action([
3540 windows_coverage_env.get('LINKCOM', []),
3541 '-$COVERAGE_VSINSTR /COVERAGE ${TARGET}'])
3542 windows_coverage_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
3543 AddDualLibrary(windows_coverage_env)
3544 environment_list.append(windows_coverage_env)
3546 mac_coverage_env = mac_debug_env.Clone(
3547 tools = ['code_coverage'],
3548 BUILD_TYPE = 'coverage-mac',
3549 BUILD_TYPE_DESCRIPTION = 'MacOS code coverage build',
3550 # Strict doesnt't currently work for coverage because the path to gcov is
3551 # magically baked into the compiler.
3552 LIBS_STRICT = False,
3554 AddDualLibrary(mac_coverage_env)
3555 environment_list.append(mac_coverage_env)
3557 linux_coverage_env = linux_debug_env.Clone(
3558 tools = ['code_coverage'],
3559 BUILD_TYPE = 'coverage-linux',
3560 BUILD_TYPE_DESCRIPTION = 'Linux code coverage build',
3561 # Strict doesnt't currently work for coverage because the path to gcov is
3562 # magically baked into the compiler.
3563 LIBS_STRICT = False,
3566 linux_coverage_env.FilterOut(CCFLAGS=['-fPIE'])
3567 linux_coverage_env.Append(CCFLAGS=['-fPIC'])
3569 linux_coverage_env['OPTIONAL_COVERAGE_LIBS'] = '$COVERAGE_LIBS'
3570 AddDualLibrary(linux_coverage_env)
3571 environment_list.append(linux_coverage_env)
3574 # Environment Massaging
3575 RELEVANT_CONFIG = ['NACL_BUILD_FAMILY',
3579 'BUILD_TYPE_DESCRIPTION',
3582 MAYBE_RELEVANT_CONFIG = ['BUILD_OS',
3583 'BUILD_ARCHITECTURE',
3586 'TARGET_ARCHITECTURE',
3590 def DumpCompilerVersion(cc, env):
3592 env.Execute(env.Action('set'))
3593 env.Execute(env.Action('${CC} -v -c'))
3594 env.Execute(env.Action('${CC} -print-search-dirs'))
3595 env.Execute(env.Action('${CC} -print-libgcc-file-name'))
3596 elif cc.startswith('cl'):
3599 p = subprocess.Popen(env.subst('${CC} /V'),
3601 stdout=subprocess.PIPE,
3602 stderr=subprocess.PIPE)
3603 stdout, stderr = p.communicate()
3604 print stderr[0:stderr.find("\r")]
3605 except WindowsError:
3606 # If vcvars was not run before running SCons, we won't be able to find
3607 # the compiler at this point. SCons has built in functions for finding
3608 # the compiler, but they haven't run yet.
3609 print 'Can not find the compiler, assuming SCons will find it later.'
3611 print "UNKNOWN COMPILER"
3614 def SanityCheckEnvironments(all_envs):
3615 # simple completeness check
3616 for env in all_envs:
3617 for tag in RELEVANT_CONFIG:
3618 assert tag in env, repr(tag)
3619 assert env[tag], repr(env[tag])
3622 def LinkTrustedEnv(selected_envs):
3623 # Collect build families and ensure that we have only one env per family.
3625 for env in selected_envs:
3626 family = env['NACL_BUILD_FAMILY']
3627 if family not in family_map:
3628 family_map[family] = env
3630 msg = 'You are using incompatible environments simultaneously\n'
3631 msg += '%s vs %s\n' % (env['BUILD_TYPE'],
3632 family_map[family]['BUILD_TYPE'])
3633 msg += ('Please specfy the exact environments you require, e.g. '
3634 'MODE=dbg-host,nacl')
3635 raise Exception(msg)
3637 # Set TRUSTED_ENV so that tests of untrusted code can locate sel_ldr
3638 # etc. We set this on trusted envs too because some tests on
3639 # trusted envs run sel_ldr (e.g. using checked-in binaries).
3640 if 'TRUSTED' in family_map:
3641 for env in selected_envs:
3642 env['TRUSTED_ENV'] = family_map['TRUSTED']
3643 # Propagate some environment variables from the trusted environment,
3644 # in case some (e.g. Mac's DYLD_LIBRARY_PATH) are necessary for
3645 # running sel_ldr et al in untrusted environments' tests.
3646 for var in env['TRUSTED_ENV'].get('PROPAGATE_ENV', []):
3647 env['ENV'][var] = env['TRUSTED_ENV']['ENV'][var]
3648 if 'TRUSTED' not in family_map or 'UNTRUSTED' not in family_map:
3649 Banner('Warning: "--mode" did not specify both trusted and untrusted '
3650 'build environments. As a result, many tests will not be run.')
3653 build_platform = GetBuildPlatform()
3655 # Build Platform Base Function
3656 platform_func_map = {
3657 'win32' : MakeWindowsEnv,
3658 'cygwin': MakeWindowsEnv,
3659 'linux' : MakeLinuxEnv,
3660 'linux2': MakeLinuxEnv,
3661 'darwin': MakeMacEnv,
3663 if sys.platform not in platform_func_map:
3664 raise UserError('Unrecognized host platform: %s', sys.platform)
3665 make_env_func = platform_func_map[sys.platform]
3667 build_env = make_env_func(build_platform)
3668 build_env['IS_BUILD_ENV'] = True
3670 # Building tls_edit depends on gio, platform, and validator_ragel.
3671 build_env['BUILD_SCONSCRIPTS'] = [
3672 # KEEP THIS SORTED PLEASE
3673 'src/shared/gio/build.scons',
3674 'src/shared/platform/build.scons',
3675 'src/trusted/validator_ragel/build.scons',
3678 # The build environment is only used for intermediate steps and should
3679 # not be creating any targets. Aliases are used as means to add targets
3680 # to builds (IE, all_programs, all_libraries...etc.). Since we want to
3681 # share all of our build scripts but not define any aliases, we should
3682 # override the alias function and essentially stub it out.
3683 build_env.Alias = lambda env, target, source=[], actions=None, **kw : []
3687 def LinkBuildEnv(selected_envs):
3689 'opt': opt_build_env,
3690 'dbg': dbg_build_env,
3693 # We need to find the optimization level in order to know which
3694 # build environment we want to use
3696 for env in selected_envs:
3697 if env.get('OPTIMIZATION_LEVEL', None):
3698 opt_level = env['OPTIMIZATION_LEVEL']
3701 build_env = build_env_map.get(opt_level, opt_build_env)
3702 for env in selected_envs:
3703 env['BUILD_ENV'] = build_env
3705 # If the build environment is different from all the selected environments,
3706 # we will need to also append it to the selected environments so the targets
3708 build_env_root = build_env.subst('${TARGET_ROOT}')
3709 for env in selected_envs:
3710 if build_env_root == env.subst('${TARGET_ROOT}'):
3713 # Did not find a matching environment, append the build environment now.
3714 selected_envs.append(build_env)
3716 def DumpEnvironmentInfo(selected_envs):
3717 if VerboseConfigInfo(pre_base_env):
3718 Banner("The following environments have been configured")
3719 for env in selected_envs:
3720 for tag in RELEVANT_CONFIG:
3721 assert tag in env, repr(tag)
3722 print "%s: %s" % (tag, env.subst(env.get(tag)))
3723 for tag in MAYBE_RELEVANT_CONFIG:
3724 print "%s: %s" % (tag, env.subst(env.get(tag)))
3725 cc = env.subst('${CC}')
3727 asppcom = env.subst('${ASPPCOM}')
3728 print 'ASPPCOM:', asppcom
3729 DumpCompilerVersion(cc, env)
3731 rev_file = 'toolchain/linux_x86_pnacl/pnacl_newlib/REV'
3732 if os.path.exists(rev_file):
3733 for line in open(rev_file).read().split('\n'):
3734 if "Revision:" in line:
3735 print "PNACL : %s" % line
3737 def PnaclSetEmulatorForSandboxedTranslator(selected_envs):
3738 # Slip in emulator flags if necessary, for the sandboxed pnacl translator
3739 # on ARM, once emulator is actually known (vs in naclsdk.py, where it
3740 # is not yet known).
3741 for env in selected_envs:
3742 if (env.Bit('bitcode')
3743 and env.Bit('use_sandboxed_translator')
3744 and env.UsingEmulator()):
3745 # This must modify the LINK command itself, since LINKFLAGS may
3746 # be filtered (e.g., in barebones tests).
3747 env.Append(LINK=' --pnacl-use-emulator')
3748 env.Append(TRANSLATE=' --pnacl-use-emulator')
3751 # Blank out defaults.
3754 # Apply optional supplement if present in the directory tree.
3755 if os.path.exists(pre_base_env.subst('$MAIN_DIR/supplement/supplement.scons')):
3756 SConscript('supplement/supplement.scons', exports=['environment_list'])
3758 # print sytem info (optionally)
3759 if VerboseConfigInfo(pre_base_env):
3760 Banner('SCONS ARGS:' + str(sys.argv))
3761 os.system(pre_base_env.subst('${PYTHON} tools/sysinfo.py'))
3765 SanityCheckEnvironments(environment_list)
3766 selected_envs = FilterEnvironments(environment_list)
3768 # If we are building NaCl, build nacl_irt too. This works around it being
3769 # a separate mode due to the vagaries of scons when we'd really rather it
3770 # not be, while not requiring that every bot command line using --mode be
3771 # changed to list '...,nacl,nacl_irt' explicitly.
3772 if nacl_env in selected_envs:
3773 selected_envs.append(nacl_irt_env)
3775 # The nacl_irt_test_env requires nacl_env to build things correctly.
3776 if nacl_irt_test_env in selected_envs and nacl_env not in selected_envs:
3777 selected_envs.append(nacl_env)
3779 DumpEnvironmentInfo(selected_envs)
3780 LinkTrustedEnv(selected_envs)
3782 # When building NaCl, any intermediate build tool that is used during the
3783 # build process must be built using the current build environment, not the
3784 # target. Create a build environment for this purpose and link it into
3785 # the selected environments
3786 dbg_build_env, opt_build_env = GenerateOptimizationLevels(MakeBuildEnv())
3787 LinkBuildEnv(selected_envs)
3789 # This must happen after LinkTrustedEnv, since that is where TRUSTED_ENV
3790 # is finally set, and env.UsingEmulator() checks TRUSTED_ENV for the emulator.
3791 # This must also happen before BuildEnvironments.
3792 PnaclSetEmulatorForSandboxedTranslator(selected_envs)
3794 BuildEnvironments(selected_envs)
3796 # Change default to build everything, but not run tests.
3797 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
3800 # Sanity check whether we are ready to build nacl modules
3801 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3802 if nacl_env.Bit('naclsdk_validate') and (nacl_env in selected_envs or
3803 nacl_irt_env in selected_envs):
3804 nacl_env.ValidateSdk()
3806 if BROKEN_TEST_COUNT > 0:
3807 msg = "There are %d broken tests." % BROKEN_TEST_COUNT
3808 if GetOption('brief_comstr'):
3809 msg += " Add --verbose to the command line for more information."
3812 # separate warnings from actual build output
3813 Banner('B U I L D - O U T P U T:')