2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
14 sys.path.append("./common")
15 sys.path.append('../third_party')
17 from SCons.Errors import UserError
18 from SCons.Script import GetBuildFailures
23 SCons.Warnings.warningAsException()
25 sys.path.append("tools")
29 import pynacl.platform
31 # turning garbage collection off reduces startup time by 10%
38 def PrintFinalReport():
39 """This function is run just before scons exits and dumps various reports.
41 # Note, these global declarations are not strictly necessary
46 if pre_base_env.Bit('target_stats'):
49 print 'COMMAND EXECUTION REPORT'
51 for k in sorted(CMD_COUNTER.keys()):
52 print "%4d %s" % (CMD_COUNTER[k], k)
56 print 'ENVIRONMENT USAGE REPORT'
58 for k in sorted(ENV_COUNTER.keys()):
59 print "%4d %s" % (ENV_COUNTER[k], k)
62 for failure in GetBuildFailures():
63 for node in Flatten(failure.node):
65 # If this wasn't a test, "GetTestName" will return raw_name.
66 'test_name': GetTestName(node),
67 'raw_name': str(node.path),
68 'errstr': failure.errstr
71 json_path = ARGUMENTS.get('json_build_results_output_file')
73 with open(json_path, 'w') as f:
74 json.dump(failures, f, sort_keys=True, indent=2)
81 print 'ERROR REPORT: %d failures' % len(failures)
84 for failure in failures:
85 test_name = failure['test_name']
86 if test_name != failure['raw_name']:
87 test_name = '%s (%s)' % (test_name, failure['raw_name'])
88 print "%s failed: %s\n" % (test_name, failure['errstr'])
91 def VerboseConfigInfo(env):
92 "Should we print verbose config information useful for bug reports"
93 if '--help' in sys.argv: return False
94 if env.Bit('prebuilt') or env.Bit('built_elsewhere'): return False
95 return env.Bit('sysinfo')
100 # NOTE BitFromArgument(...) implicitly defines additional ACCEPTABLE_ARGUMENTS.
101 ACCEPTABLE_ARGUMENTS = set([
102 # TODO: add comments what these mean
103 # TODO: check which ones are obsolete
104 #### ASCII SORTED ####
105 # Use a destination directory other than the default "scons-out".
109 # Limit bandwidth of browser tester
111 # Location to download Chromium binaries to and/or read them from.
112 'chrome_binaries_dir',
113 # used for chrome_browser_tests: path to the browser
114 'chrome_browser_path',
115 # A comma-separated list of test names to disable by excluding the
116 # tests from a test suite. For example, 'small_tests
117 # disable_tests=run_hello_world_test' will run small_tests without
118 # including hello_world_test. Note that if a test listed here
119 # does not exist you will not get an error or a warning.
121 # used for chrome_browser_tests: path to a pre-built browser plugin.
122 'force_ppapi_plugin',
123 # force emulator use by tests
125 # force sel_ldr use by tests
127 # force nacl_helper_bootstrap used by tests
129 # force irt image used by tests
131 # generate_ninja=FILE enables a Ninja backend for SCons. This writes a
132 # .ninja build file to FILE describing all of SCons' build targets.
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 # When building with MSan, this can be set to values 0 (fastest, least
147 # useful reports) through 2 (slowest, most useful reports). Default is 1.
148 'msan_track_origins',
149 # colon-separated list of linker flags, e.g. "-lfoo:-Wl,-u,bar".
151 # prefix to add in-front of perf tracking trace labels.
153 # colon-separated list of pnacl bcld flags, e.g. "-lfoo:-Wl,-u,bar".
154 # Not using nacl_linkflags since that gets clobbered in some tests.
157 # Run tests under this tool (e.g. valgrind, tsan, strace, etc).
158 # If the tool has options, pass them after comma: 'tool,--opt1,--opt2'.
159 # NB: no way to use tools the names or the args of
160 # which contains a comma.
162 # More args for the tool.
163 'run_under_extra_args',
164 # Multiply timeout values by this number.
166 # test_wrapper specifies a wrapper program such as
167 # tools/run_test_via_ssh.py, which runs tests on a remote host
168 # using rsync and SSH. Example usage:
169 # ./scons run_hello_world_test platform=arm force_emulator= \
170 # test_wrapper="./tools/run_test_via_ssh.py --host=armbox --subdir=tmp"
172 # Replacement tsan command for overriding the DEPS-in tsan
173 # script. May have commas to separate separate shell args. There
174 # is no quoting, so this implies that this mechanism will fail if
175 # the args actually need to have commas. See
176 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
177 # the discussion of why this argument is needed.
179 # Run browser tests under this tool. See
180 # tools/browser_tester/browsertester/browserlauncher.py for tool names.
182 # Where to install header files for public consumption.
184 # Where to install libraries for public consumption.
186 # Where to install trusted-code binaries for public (SDK) consumption.
188 # Where a Breakpad build output directory is for optional Breakpad testing.
189 'breakpad_tools_dir',
190 # Allows overriding of the nacl newlib toolchain directory.
192 # Allows override of the nacl glibc toolchain directory.
194 # Allows override of the pnacl newlib toolchain directory.
196 # Allows overriding the version number in the toolchain's
197 # FEATURE_VERSION file. This is used for PNaCl ABI compatibility
199 'toolchain_feature_version',
203 # Overly general to provide compatibility with existing build bots, etc.
204 # In the future it might be worth restricting the values that are accepted.
205 _TRUE_STRINGS = set(['1', 'true', 'yes'])
206 _FALSE_STRINGS = set(['0', 'false', 'no'])
209 # Converts a string representing a Boolean value, of some sort, into an actual
210 # Boolean value. Python's built in type coercion does not work because
211 # bool('False') == True
212 def StringValueToBoolean(value):
213 # ExpandArguments may stick non-string values in ARGUMENTS. Be accommodating.
214 if isinstance(value, bool):
217 if not isinstance(value, basestring):
218 raise Exception("Expecting a string but got a %s" % repr(type(value)))
220 if value.lower() in _TRUE_STRINGS:
222 elif value.lower() in _FALSE_STRINGS:
225 raise Exception("Cannot convert '%s' to a Boolean value" % value)
228 def GetBinaryArgumentValue(arg_name, default):
229 if not isinstance(default, bool):
230 raise Exception("Default value for '%s' must be a Boolean" % arg_name)
231 if arg_name not in ARGUMENTS:
233 return StringValueToBoolean(ARGUMENTS[arg_name])
236 # name is the name of the bit
237 # arg_name is the name of the command-line argument, if it differs from the bit
238 def BitFromArgument(env, name, default, desc, arg_name=None):
239 # In most cases the bit name matches the argument name
243 DeclareBit(name, desc)
244 assert arg_name not in ACCEPTABLE_ARGUMENTS, repr(arg_name)
245 ACCEPTABLE_ARGUMENTS.add(arg_name)
247 if GetBinaryArgumentValue(arg_name, default):
253 # SetUpArgumentBits declares binary command-line arguments and converts them to
254 # bits. For example, one of the existing declarations would result in the
255 # argument "bitcode=1" causing env.Bit('bitcode') to evaluate to true.
256 # NOTE Command-line arguments are a SCons-ism that is separate from
257 # command-line options. Options are prefixed by "-" or "--" whereas arguments
258 # are not. The function SetBitFromOption can be used for options.
259 # NOTE This function must be called before the bits are used
260 # NOTE This function must be called after all modifications of ARGUMENTS have
261 # been performed. See: ExpandArguments
262 def SetUpArgumentBits(env):
263 BitFromArgument(env, 'bitcode', default=False,
264 desc='We are building bitcode')
266 BitFromArgument(env, 'pnacl_native_clang_driver', default=False,
267 desc='Use the (experimental) native PNaCl Clang driver')
269 BitFromArgument(env, 'nacl_clang', default=(not env.Bit('bitcode') and
270 not env.Bit('nacl_glibc')),
271 desc='Use the native nacl-clang newlib compiler instead of nacl-gcc')
273 BitFromArgument(env, 'translate_fast', default=False,
274 desc='When using pnacl TC (bitcode=1) use accelerated translation step')
276 BitFromArgument(env, 'use_sz', default=False,
277 desc='When using pnacl TC (bitcode=1) use Subzero for fast translation')
279 BitFromArgument(env, 'built_elsewhere', default=False,
280 desc='The programs have already been built by another system')
282 BitFromArgument(env, 'skip_trusted_tests', default=False,
283 desc='Only run untrusted tests - useful for translator testing'
284 ' (also skips tests of the IRT itself')
286 BitFromArgument(env, 'nacl_pic', default=False,
287 desc='generate position indepent code for (P)NaCl modules')
289 BitFromArgument(env, 'nacl_static_link', default=not env.Bit('nacl_glibc'),
290 desc='Whether to use static linking instead of dynamic linking '
291 'for building NaCl executables during tests. '
292 'For nacl-newlib, the default is 1 (static linking). '
293 'For nacl-glibc, the default is 0 (dynamic linking).')
295 BitFromArgument(env, 'nacl_disable_shared', default=not env.Bit('nacl_glibc'),
296 desc='Do not build shared versions of libraries. '
297 'For nacl-newlib, the default is 1 (static libraries only). '
298 'For nacl-glibc, the default is 0 (both static and shared libraries).')
300 # Defaults on when --verbose is specified.
301 # --verbose sets 'brief_comstr' to False, so this looks a little strange
302 BitFromArgument(env, 'target_stats', default=not GetOption('brief_comstr'),
303 desc='Collect and display information about which commands are executed '
304 'during the build process')
306 BitFromArgument(env, 'werror', default=True,
307 desc='Treat warnings as errors (-Werror)')
309 BitFromArgument(env, 'disable_nosys_linker_warnings', default=False,
310 desc='Disable warning mechanism in src/untrusted/nosys/warning.h')
312 BitFromArgument(env, 'naclsdk_validate', default=True,
313 desc='Verify the presence of the SDK')
315 # TODO(mseaborn): Remove this, since this is always False -- Valgrind is
316 # no longer supported. This will require removing some Chromium-side
318 BitFromArgument(env, 'running_on_valgrind', default=False,
319 desc='Compile and test using valgrind')
321 BitFromArgument(env, 'pp', default=False,
322 desc='Enable pretty printing')
324 # Defaults on when --verbose is specified
325 # --verbose sets 'brief_comstr' to False, so this looks a little strange
326 BitFromArgument(env, 'sysinfo', default=not GetOption('brief_comstr'),
327 desc='Print verbose system information')
329 BitFromArgument(env, 'disable_flaky_tests', default=False,
330 desc='Do not run potentially flaky tests - used on Chrome bots')
332 BitFromArgument(env, 'use_sandboxed_translator', default=False,
333 desc='use pnacl sandboxed translator for linking (not available for arm)')
335 BitFromArgument(env, 'pnacl_generate_pexe', default=env.Bit('bitcode'),
336 desc='use pnacl to generate pexes and translate in a separate step')
338 BitFromArgument(env, 'translate_in_build_step', default=True,
339 desc='Run translation during build phase (e.g. if do_not_run_tests=1)')
341 BitFromArgument(env, 'pnacl_unsandboxed', default=False,
342 desc='Translate pexe to an unsandboxed, host executable')
344 BitFromArgument(env, 'nonsfi_nacl', default=False,
345 desc='Use Non-SFI Mode instead of the original SFI Mode. This uses '
346 'nonsfi_loader instead of sel_ldr, and it tells the PNaCl toolchain '
347 'to translate pexes to Non-SFI nexes.')
349 BitFromArgument(env, 'use_newlib_nonsfi_loader', default=True,
350 desc='Test nonsfi_loader linked against NaCl newlib instead of the one '
351 'linked against host libc. This flag makes sense only with '
354 BitFromArgument(env, 'browser_headless', default=False,
355 desc='Where possible, set up a dummy display to run the browser on '
356 'when running browser tests. On Linux, this runs the browser through '
357 'xvfb-run. This Scons does not need to be run with an X11 display '
358 'and we do not open a browser window on the user\'s desktop. '
359 'Unfortunately there is no equivalent on Mac OS X.')
361 BitFromArgument(env, 'disable_crash_dialog', default=True,
362 desc='Disable Windows\' crash dialog box, which Windows pops up when a '
363 'process exits with an unhandled fault. Windows enables this by '
364 'default for processes launched from the command line or from the '
365 'GUI. Our default is to disable it, because the dialog turns crashes '
366 'into hangs on Buildbot, and our test suite includes various crash '
369 BitFromArgument(env, 'do_not_run_tests', default=False,
370 desc='Prevents tests from running. This lets SCons build the files needed '
371 'to run the specified test(s) without actually running them. This '
372 'argument is a counterpart to built_elsewhere.')
374 BitFromArgument(env, 'no_gdb_tests', default=False,
375 desc='Prevents GDB tests from running. If GDB is not available, you can '
376 'test everything else by specifying this flag.')
378 # TODO(shcherbina): add support for other golden-based tests, not only
379 # run_x86_*_validator_testdata_tests.
380 BitFromArgument(env, 'regenerate_golden', default=False,
381 desc='When running golden-based tests, instead of comparing results '
382 'save actual output as golden data.')
384 BitFromArgument(env, 'x86_64_zero_based_sandbox', default=False,
385 desc='Use the zero-address-based x86-64 sandbox model instead of '
386 'the r15-based model.')
388 BitFromArgument(env, 'android', default=False,
389 desc='Build for Android target')
391 BitFromArgument(env, 'skip_nonstable_bitcode', default=False,
392 desc='Skip tests involving non-stable bitcode')
394 #########################################################################
396 # This is for generating a testing library for use within private test
397 # enuminsts, where we want to compare and test different validators.
399 BitFromArgument(env, 'ncval_testing', default=False,
400 desc='EXPERIMENTAL: Compile validator code for testing within enuminsts')
402 # PNaCl sanity checks
403 if not env.Bit('bitcode'):
404 pnacl_only_flags = ('nonsfi_nacl',
405 'pnacl_generate_pexe',
407 'skip_nonstable_bitcode',
410 'use_sandboxed_translator')
412 for flag_name in pnacl_only_flags:
413 if env.Bit(flag_name):
414 raise UserError('The option %r only makes sense when using the '
415 'PNaCl toolchain (i.e. with bitcode=1)'
418 pnacl_incompatible_flags = ('nacl_clang',
420 for flag_name in pnacl_incompatible_flags:
421 if env.Bit(flag_name):
422 raise UserError('The option %r cannot be used when building with '
423 'PNaCl (i.e. with bitcode=1)' % flag_name)
425 def CheckArguments():
426 for key in ARGUMENTS:
427 if key not in ACCEPTABLE_ARGUMENTS:
428 raise UserError('bad argument: %s' % key)
431 def GetTargetPlatform():
432 return pynacl.platform.GetArch3264(ARGUMENTS.get('platform', 'x86-32'))
434 def GetBuildPlatform():
435 return pynacl.platform.GetArch3264()
438 environment_list = []
440 # Base environment for both nacl and non-nacl variants.
442 if ARGUMENTS.get('DESTINATION_ROOT') is not None:
443 kwargs['DESTINATION_ROOT'] = ARGUMENTS.get('DESTINATION_ROOT')
444 pre_base_env = Environment(
445 # Use the environment that scons was run in to run scons invoked commands.
446 # This allows in things like externally provided PATH, PYTHONPATH.
447 ENV = os.environ.copy(),
448 tools = ['component_setup'],
449 # SOURCE_ROOT is one leave above the native_client directory.
450 SOURCE_ROOT = Dir('#/..').abspath,
451 # Publish dlls as final products (to staging).
452 COMPONENT_LIBRARY_PUBLISH = True,
454 # Use workaround in special scons version.
456 LIBS_DO_SUBST = True,
458 # Select where to find coverage tools.
459 COVERAGE_MCOV = '../third_party/lcov/bin/mcov',
460 COVERAGE_GENHTML = '../third_party/lcov/bin/genhtml',
465 if 'generate_ninja' in ARGUMENTS:
466 import pynacl.scons_to_ninja
467 pynacl.scons_to_ninja.GenerateNinjaFile(
468 pre_base_env, dest_file=ARGUMENTS['generate_ninja'])
471 breakpad_tools_dir = ARGUMENTS.get('breakpad_tools_dir')
472 if breakpad_tools_dir is not None:
473 pre_base_env['BREAKPAD_TOOLS_DIR'] = pre_base_env.Dir(
474 os.path.abspath(breakpad_tools_dir))
478 DeclareBit('clang', 'Use clang to build trusted code')
479 pre_base_env.SetBitFromOption('clang', False)
482 'Use AddressSanitizer to build trusted code (implies --clang)')
483 pre_base_env.SetBitFromOption('asan', False)
484 if pre_base_env.Bit('asan'):
485 pre_base_env.SetBits('clang')
488 'Use MemorySanitizer to build trusted code (implies --clang)')
489 pre_base_env.SetBitFromOption('msan', False)
490 if pre_base_env.Bit('msan'):
491 pre_base_env.SetBits('clang')
494 DeclareBit('coverage_enabled', 'The build should be instrumented to generate'
495 'coverage information')
497 # If the environment variable BUILDBOT_BUILDERNAME is set, we can determine
498 # if we are running in a VM by the lack of a '-bare-' (aka bare metal) in the
499 # bot name. Otherwise if the builder name is not set, then assume real HW.
500 DeclareBit('running_on_vm', 'Returns true when environment is running in a VM')
501 builder = os.environ.get('BUILDBOT_BUILDERNAME')
502 if builder and builder.find('-bare-') == -1:
503 pre_base_env.SetBits('running_on_vm')
505 pre_base_env.ClearBits('running_on_vm')
507 DeclareBit('nacl_glibc', 'Use nacl-glibc for building untrusted code')
508 pre_base_env.SetBitFromOption('nacl_glibc', False)
510 # This function should be called ASAP after the environment is created, but
511 # after ExpandArguments.
512 SetUpArgumentBits(pre_base_env)
514 # Register PrintFinalReport only after SetUpArgumentBits since it references
515 # bits that get declared in SetUpArgumentBits
516 atexit.register(PrintFinalReport)
518 def DisableCrashDialog():
519 if sys.platform == 'win32':
522 # The double call is to preserve existing flags, as discussed at
523 # http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
524 new_flags = win32con.SEM_NOGPFAULTERRORBOX
525 existing_flags = win32api.SetErrorMode(new_flags)
526 win32api.SetErrorMode(existing_flags | new_flags)
528 if pre_base_env.Bit('disable_crash_dialog'):
531 # We want to pull CYGWIN setup in our environment or at least set flag
532 # nodosfilewarning. It does not do anything when CYGWIN is not involved
533 # so let's do it in all cases.
534 pre_base_env['ENV']['CYGWIN'] = os.environ.get('CYGWIN', 'nodosfilewarning')
536 # Note: QEMU_PREFIX_HOOK may influence test runs and sb translator invocations
537 pre_base_env['ENV']['QEMU_PREFIX_HOOK'] = os.environ.get('QEMU_PREFIX_HOOK', '')
539 # Allow the zero-based sandbox model to run insecurely.
540 # TODO(arbenson): remove this once binutils bug is fixed (see
541 # src/trusted/service_runtime/arch/x86_64/sel_addrspace_posix_x86_64.c)
542 if pre_base_env.Bit('x86_64_zero_based_sandbox'):
543 pre_base_env['ENV']['NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX'] = 1
545 if pre_base_env.Bit('werror'):
546 werror_flags = ['-Werror']
550 # Allow variadic macros
551 werror_flags = werror_flags + ['-Wno-variadic-macros']
553 if pre_base_env.Bit('clang'):
554 # Allow 'default' label in switch even when all enumeration cases
556 werror_flags += ['-Wno-covered-switch-default']
557 # Allow C++11 extensions (for "override")
558 werror_flags += ['-Wno-c++11-extensions']
561 # Method to make sure -pedantic, etc, are not stripped from the
562 # default env, since occasionally an engineer will be tempted down the
563 # dark -- but wide and well-trodden -- path of expediency and stray
564 # from the path of correctness.
566 def EnsureRequiredBuildWarnings(env):
567 if (env.Bit('linux') or env.Bit('mac')) and not env.Bit('android'):
568 required_env_flags = set(['-pedantic', '-Wall'] + werror_flags)
569 ccflags = set(env.get('CCFLAGS'))
571 if not required_env_flags.issubset(ccflags):
572 raise UserError('required build flags missing: '
573 + ' '.join(required_env_flags.difference(ccflags)))
575 # windows get a pass for now
578 pre_base_env.AddMethod(EnsureRequiredBuildWarnings)
580 # Expose MakeTempDir and MakeTempFile to scons scripts
581 def MakeEmptyFile(env, **kwargs):
582 fd, path = test_lib.MakeTempFile(env, **kwargs)
586 pre_base_env.AddMethod(test_lib.MakeTempDir)
587 pre_base_env.AddMethod(MakeEmptyFile)
589 # Method to add target suffix to name.
590 def NaClTargetArchSuffix(env, name):
591 return name + '_' + env['TARGET_FULLARCH'].replace('-', '_')
593 pre_base_env.AddMethod(NaClTargetArchSuffix)
596 # Generic Test Wrapper
598 # Add list of Flaky or Bad tests to skip per platform. A
599 # platform is defined as build type
600 # <BUILD_TYPE>-<SUBARCH>
605 # This is a list of tests that do not yet pass when using nacl-glibc.
606 # TODO(mseaborn): Enable more of these tests!
607 nacl_glibc_skiplist = set([
608 # Struct layouts differ.
610 # Syscall wrappers not implemented yet.
613 # Fails because clock() is not hooked up.
614 'run_timefuncs_test',
615 # Needs further investigation.
617 # This test fails with nacl-glibc: glibc reports an internal
618 # sanity check failure in free().
619 # TODO(robertm): This needs further investigation.
620 'run_ppapi_event_test',
621 'run_ppapi_geturl_valid_test',
622 'run_ppapi_geturl_invalid_test',
623 # http://code.google.com/p/chromium/issues/detail?id=108131
624 # we would need to list all of the glibc components as
625 # web accessible resources in the extensions's manifest.json,
626 # not just the nexe and nmf file.
627 'run_ppapi_extension_mime_handler_browser_test',
629 nacl_glibc_skiplist.update(['%s_irt' % test for test in nacl_glibc_skiplist])
631 # Whitelist of tests to run for Non-SFI Mode. Note that typos here will
632 # not be caught automatically!
633 # TODO(mseaborn): Eventually we should run all of small_tests instead of
635 nonsfi_test_whitelist = set([
636 'run_arm_float_abi_test',
637 'run_clock_get_test',
639 'run_directory_test',
641 'run_example_irt_caller_test',
642 'run_exception_test',
644 'run_file_descriptor_test',
648 'run_hello_world_test',
650 'run_irt_futex_test',
651 'run_malloc_realloc_calloc_free_test',
653 'run_nanosleep_test',
654 'run_nonsfi_syscall_test',
660 'run_sigaction_test',
661 'run_signal_sigbus_test',
664 'run_stack_alignment_asm_test',
665 'run_stack_alignment_test',
668 'run_user_async_signal_test',
672 # If a test is not in one of these suites, it will probally not be run on a
673 # regular basis. These are the suites that will be run by the try bot or that
674 # a large number of users may run by hand.
675 MAJOR_TEST_SUITES = set([
679 # Tests using the pepper plugin, only run with chrome
680 # TODO(ncbray): migrate pepper_browser_tests to chrome_browser_tests
681 'pepper_browser_tests',
682 # Lightweight browser tests
683 'chrome_browser_tests',
685 'memcheck_bot_tests',
687 # Special testing environment for testing comparing x86 validators.
689 # Environment for validator difference testing
690 'validator_diff_tests',
691 # Subset of tests enabled for Non-SFI Mode.
695 # These are the test suites we know exist, but aren't run on a regular basis.
696 # These test suites are essentially shortcuts that run a specific subset of the
698 ACCEPTABLE_TEST_SUITES = set([
700 'dynamic_load_tests',
701 'eh_tests', # Tests for C++ exception handling
702 'exception_tests', # Tests for hardware exception handling
708 'sel_ldr_sled_tests',
711 'validator_modeling',
713 # Special testing of the decoder for the ARM validator.
717 # Under --mode=nacl_irt_test we build variants of numerous tests normally
718 # built under --mode=nacl. The test names and suite names for these
719 # variants are set (in IrtTestAddNodeToTestSuite, below) by appending _irt
720 # to the names used for the --mode=nacl version of the same tests.
721 MAJOR_TEST_SUITES |= set([name + '_irt'
722 for name in MAJOR_TEST_SUITES])
723 ACCEPTABLE_TEST_SUITES |= set([name + '_irt'
724 for name in ACCEPTABLE_TEST_SUITES])
726 # The major test suites are also acceptable names. Suite names are checked
727 # against this set in order to catch typos.
728 ACCEPTABLE_TEST_SUITES.update(MAJOR_TEST_SUITES)
731 def ValidateTestSuiteNames(suite_name, node_name):
732 if node_name is None:
733 node_name = '<unknown>'
735 # Prevent a silent failiure - strings are iterable!
736 if not isinstance(suite_name, (list, tuple)):
737 raise Exception("Test suites for %s should be specified as a list, "
738 "not as a %s: %s" % (node_name, type(suite_name).__name__,
742 raise Exception("No test suites are specified for %s. Set the 'broken' "
743 "parameter on AddNodeToTestSuite in the cases where there's a known "
744 "issue and you don't want the test to run" % (node_name,))
746 # Make sure each test is in at least one test suite we know will run
747 major_suites = set(suite_name).intersection(MAJOR_TEST_SUITES)
749 raise Exception("None of the test suites %s for %s are run on a "
750 "regular basis" % (repr(suite_name), node_name))
752 # Make sure a wierd test suite hasn't been inadvertantly specified
754 if s not in ACCEPTABLE_TEST_SUITES:
755 raise Exception("\"%s\" is not a known test suite. Either this is "
756 "a typo for %s, or it should be added to ACCEPTABLE_TEST_SUITES in "
757 "SConstruct" % (s, node_name))
759 BROKEN_TEST_COUNT = 0
762 def GetPlatformString(env):
763 build = env['BUILD_TYPE']
765 # If we are testing 'NACL' we really need the trusted info
766 if build=='nacl' and 'TRUSTED_ENV' in env:
767 trusted_env = env['TRUSTED_ENV']
768 build = trusted_env['BUILD_TYPE']
769 subarch = trusted_env['BUILD_SUBARCH']
771 subarch = env['BUILD_SUBARCH']
773 # Build the test platform string
774 return build + '-' + subarch
776 pre_base_env.AddMethod(GetPlatformString)
779 tests_to_disable_qemu = set([
780 # These tests do not work under QEMU but do work on ARM hardware.
782 # You should use the is_broken argument in preference to adding
783 # tests to this list.
785 # See: http://code.google.com/p/nativeclient/issues/detail?id=2437
786 # Note, for now these tests disable both the irt and non-irt variants
787 'run_egyptian_cotton_test',
788 'run_many_threads_sequential_test',
789 # subprocess needs to also have qemu prefix, which isn't supported
790 'run_subprocess_test',
791 'run_thread_suspension_test',
792 'run_dynamic_modify_test',
795 tests_to_disable = set()
796 if ARGUMENTS.get('disable_tests', '') != '':
797 tests_to_disable.update(ARGUMENTS['disable_tests'].split(','))
800 def ShouldSkipTest(env, node_name):
801 if (env.Bit('skip_trusted_tests')
802 and (env['NACL_BUILD_FAMILY'] == 'TRUSTED'
803 or env['NACL_BUILD_FAMILY'] == 'UNTRUSTED_IRT')):
806 if env.Bit('do_not_run_tests'):
807 # This hack is used for pnacl testing where we might build tests
808 # without running them on one bot and then transfer and run them on another.
809 # The skip logic only takes the first bot into account e.g. qemu
810 # restrictions, while it really should be skipping based on the second
811 # bot. By simply disabling the skipping completely we work around this.
814 # There are no known-to-fail tests any more, but this code is left
815 # in so that if/when we port to a new architecture or add a test
816 # that is known to fail on some platform(s), we can continue to have
817 # a central location to disable tests from running. NB: tests that
818 # don't *build* on some platforms need to be omitted in another way.
820 if node_name in tests_to_disable:
823 if env.UsingEmulator():
824 if node_name in tests_to_disable_qemu:
826 # For now also disable the irt variant
827 if node_name.endswith('_irt') and node_name[:-4] in tests_to_disable_qemu:
830 # Retrieve list of tests to skip on this platform
831 skiplist = bad_build_lists.get(env.GetPlatformString(), [])
832 if node_name in skiplist:
835 if env.Bit('nacl_glibc') and node_name in nacl_glibc_skiplist:
840 pre_base_env.AddMethod(ShouldSkipTest)
843 def AddImplicitTestSuites(suite_list, node_name):
844 if node_name in nonsfi_test_whitelist:
845 suite_list = suite_list + ['nonsfi_tests']
849 def AddNodeToTestSuite(env, node, suite_name, node_name, is_broken=False,
851 global BROKEN_TEST_COUNT
853 # CommandTest can return an empty list when it silently discards a test
857 assert node_name is not None
858 test_name_regex = r'run_.*_(unit)?test.*$'
859 assert re.match(test_name_regex, node_name), (
860 'test %r does not match "run_..._test" naming convention '
861 '(precise regex is %s)' % (node_name, test_name_regex))
863 suite_name = AddImplicitTestSuites(suite_name, node_name)
864 ValidateTestSuiteNames(suite_name, node_name)
868 if is_broken or is_flaky and env.Bit('disable_flaky_tests'):
869 # Only print if --verbose is specified
870 if not GetOption('brief_comstr'):
871 print '*** BROKEN ', node_name
872 BROKEN_TEST_COUNT += 1
873 env.Alias('broken_tests', node)
874 elif env.ShouldSkipTest(node_name):
875 print '*** SKIPPING ', env.GetPlatformString(), ':', node_name
876 env.Alias('broken_tests', node)
878 env.Alias('all_tests', node)
884 env.ComponentTestOutput(node_name, node)
885 test_name = node_name
887 # This is rather shady, but the tests need a name without dots so they match
889 # TODO(ncbray) node_name should not be optional.
890 test_name = os.path.basename(str(node[0].path))
891 if test_name.endswith('.out'):
892 test_name = test_name[:-4]
893 test_name = test_name.replace('.', '_')
894 SetTestName(node, test_name)
896 pre_base_env.AddMethod(AddNodeToTestSuite)
899 def TestBindsFixedTcpPort(env, node):
900 # This tells Scons that tests that bind a fixed TCP port should not
901 # run concurrently, because they would interfere with each other.
902 # These tests are typically tests for NaCl's GDB debug stub. The
903 # dummy filename used below is an arbitrary token that just has to
904 # match across the tests.
905 SideEffect(env.File('${SCONSTRUCT_DIR}/test_binds_fixed_tcp_port'), node)
907 pre_base_env.AddMethod(TestBindsFixedTcpPort)
910 # Convenient testing aliases
911 # NOTE: work around for scons non-determinism in the following two lines
912 Alias('sel_ldr_sled_tests', [])
914 Alias('small_tests', [])
915 Alias('medium_tests', [])
916 Alias('large_tests', [])
918 Alias('small_tests_irt', [])
919 Alias('medium_tests_irt', [])
920 Alias('large_tests_irt', [])
922 Alias('pepper_browser_tests', [])
923 Alias('chrome_browser_tests', [])
925 Alias('unit_tests', 'small_tests')
926 Alias('smoke_tests', ['small_tests', 'medium_tests'])
928 if pre_base_env.Bit('nacl_glibc'):
929 Alias('memcheck_bot_tests', ['small_tests'])
930 Alias('tsan_bot_tests', ['small_tests'])
932 Alias('memcheck_bot_tests', ['small_tests', 'medium_tests', 'large_tests'])
933 Alias('tsan_bot_tests', [])
941 pre_base_env.AddMethod(Banner)
945 # Define the platforms, and use them to define the path for the
946 # scons-out directory (aka TARGET_ROOT)
948 # Various variables in the scons environment are related to this, e.g.
950 # BUILD_ARCH: (arm, mips, x86)
951 # BUILD_SUBARCH: (32, 64)
954 DeclareBit('build_x86_32', 'Building binaries for the x86-32 architecture',
955 exclusive_groups='build_arch')
956 DeclareBit('build_x86_64', 'Building binaries for the x86-64 architecture',
957 exclusive_groups='build_arch')
958 DeclareBit('build_mips32', 'Building binaries for the MIPS architecture',
959 exclusive_groups='build_arch')
960 DeclareBit('build_arm_arm', 'Building binaries for the ARM architecture',
961 exclusive_groups='build_arch')
963 # Shorthand for either the 32 or 64 bit version of x86.
964 DeclareBit('build_x86', 'Building binaries for the x86 architecture')
966 DeclareBit('build_arm', 'Building binaries for the arm architecture')
969 def MakeArchSpecificEnv(platform=None):
970 env = pre_base_env.Clone()
972 platform = GetTargetPlatform()
974 arch = pynacl.platform.GetArch(platform)
975 if pynacl.platform.IsArch64Bit(platform):
980 env.Replace(BUILD_FULLARCH=platform)
981 env.Replace(BUILD_ARCHITECTURE=arch)
982 env.Replace(BUILD_SUBARCH=subarch)
983 env.Replace(TARGET_FULLARCH=platform)
984 env.Replace(TARGET_ARCHITECTURE=arch)
985 env.Replace(TARGET_SUBARCH=subarch)
987 env.SetBits('build_%s' % platform.replace('-', '_'))
989 if env.Bit('build_x86_32') or env.Bit('build_x86_64'):
990 env.SetBits('build_x86')
991 if env.Bit('build_arm_arm'):
992 env.SetBits('build_arm')
994 env.Replace(BUILD_ISA_NAME=platform)
996 # Determine where the object files go
997 env.Replace(BUILD_TARGET_NAME=platform)
998 # This may be changed later; see target_variant_map, below.
999 env.Replace(TARGET_VARIANT='')
1000 env.Replace(TARGET_ROOT=
1001 '${DESTINATION_ROOT}/${BUILD_TYPE}-${BUILD_TARGET_NAME}${TARGET_VARIANT}')
1006 pre_base_env.AddMethod(lambda self: ARGUMENTS.get('running_on_valgrind'),
1007 'IsRunningUnderValgrind')
1009 DeclareBit('with_leakcheck', 'Running under Valgrind leak checker')
1011 def RunningUnderLeakCheck():
1012 run_under = ARGUMENTS.get('run_under')
1014 extra_args = ARGUMENTS.get('run_under_extra_args')
1016 run_under += extra_args
1017 if run_under.find('leak-check=full') > 0:
1021 if RunningUnderLeakCheck():
1022 pre_base_env.SetBits('with_leakcheck')
1025 def StripSuffix(string, suffix):
1026 assert string.endswith(suffix)
1027 return string[:-len(suffix)]
1030 # TODO(mseaborn): Change code to use ComponentLibrary() directly.
1031 # DualLibrary() is left over from when we built libraries twice, with and
1032 # without "-fPIC", for building plugins as DSOs.
1033 def DualLibrary(env, lib_name, *args, **kwargs):
1034 return env.ComponentLibrary(lib_name, *args, **kwargs)
1036 def DualObject(env, *args, **kwargs):
1037 return env.ComponentObject(*args, **kwargs)
1040 def AddDualLibrary(env):
1041 env.AddMethod(DualLibrary)
1042 env.AddMethod(DualObject)
1045 # In prebuild mode we ignore the dependencies so that stuff does
1046 # NOT get build again
1047 # Optionally ignore the build process.
1048 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
1049 pre_base_env.SetBitFromOption('prebuilt', False)
1052 # HELPERS FOR TEST INVOLVING TRUSTED AND UNTRUSTED ENV
1053 def GetEmulator(env):
1054 emulator = ARGUMENTS.get('force_emulator')
1055 if emulator is None and 'TRUSTED_ENV' in env:
1056 emulator = env['TRUSTED_ENV'].get('EMULATOR')
1059 pre_base_env.AddMethod(GetEmulator)
1061 def UsingEmulator(env):
1062 return bool(env.GetEmulator())
1064 pre_base_env.AddMethod(UsingEmulator)
1067 def GetValidator(env, validator):
1068 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1069 if 'TRUSTED_ENV' not in env:
1072 # TODO(shyamsundarr): rename ncval_new to ncval.
1073 if validator is None:
1074 if env.Bit('build_arm'):
1075 validator = 'arm-ncval-core'
1076 elif env.Bit('build_mips32'):
1077 validator = 'mips-ncval-core'
1079 validator = 'ncval_new'
1081 trusted_env = env['TRUSTED_ENV']
1082 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}%s${PROGSUFFIX}' %
1085 pre_base_env.AddMethod(GetValidator)
1088 # Perform os.path.abspath rooted at the directory SConstruct resides in.
1089 def SConstructAbsPath(env, path):
1090 return os.path.normpath(os.path.join(env['MAIN_DIR'], path))
1092 pre_base_env.AddMethod(SConstructAbsPath)
1095 def GetPlatformBuildTargetDir(env):
1096 # Currently we do not support any cross OS compiles, eventually the OS name
1097 # will probably be passed in through arguments.
1098 os_name = pynacl.platform.GetOS()
1100 # Currently 32/64 share the same tool build target directory. When we have
1101 # separate toolchains for each the architectures will probably have to use
1102 # the Arch3264() variant.
1103 build_arch = pynacl.platform.GetArch(GetBuildPlatform())
1105 return '%s_%s' % (os_name, build_arch)
1107 pre_base_env.AddMethod(GetPlatformBuildTargetDir)
1110 def GetToolchainDir(env, platform_build_dir=None, toolchain_name=None,
1111 target_arch=None, is_pnacl=None, lib_name=None):
1112 if platform_build_dir is None:
1113 platform_build_dir = env.GetPlatformBuildTargetDir()
1115 if toolchain_name is None:
1116 # Fill in default arguments based on environment.
1117 if is_pnacl is None:
1118 # For the purposes of finding the toolchain dir, nacl_clang is PNaCl.
1119 is_pnacl = env.Bit('bitcode') or env.Bit('nacl_clang')
1120 if lib_name is None:
1121 if is_pnacl or not env.Bit('nacl_glibc'):
1126 if target_arch is None:
1127 target_arch = pynacl.platform.GetArch(GetTargetPlatform())
1130 target_env = 'pnacl'
1132 target_env = 'nacl_%s' % target_arch
1134 # See if we have a custom toolchain directory set.
1136 toolchain_arg = 'pnacl_%s_dir' % lib_name
1138 assert lib_name == 'glibc'
1139 toolchain_arg = 'nacl_%s_dir' % lib_name
1141 custom_toolchain_dir = ARGUMENTS.get(toolchain_arg, None)
1142 if custom_toolchain_dir:
1143 return env.SConstructAbsPath(custom_toolchain_dir)
1145 # Get the standard toolchain name since no directory custom was found.
1147 target_env = 'pnacl'
1149 target_env = 'nacl_%s' % target_arch
1150 toolchain_name = '%s_%s_raw' % (target_env, lib_name)
1152 # Get the absolute path for the platform build directory and toolchain.
1153 toolchain_sub_dir = os.path.join('toolchain',
1156 return env.SConstructAbsPath(toolchain_sub_dir)
1158 pre_base_env.AddMethod(GetToolchainDir)
1162 sel_ldr = ARGUMENTS.get('force_sel_ldr')
1164 return env.File(env.SConstructAbsPath(sel_ldr))
1166 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1167 if 'TRUSTED_ENV' not in env:
1170 trusted_env = env['TRUSTED_ENV']
1171 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}sel_ldr${PROGSUFFIX}')
1173 pre_base_env.AddMethod(GetSelLdr)
1176 def GetSelLdrSeccomp(env):
1177 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1178 if 'TRUSTED_ENV' not in env:
1181 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1184 trusted_env = env['TRUSTED_ENV']
1185 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}'
1186 'sel_ldr_seccomp${PROGSUFFIX}')
1188 pre_base_env.AddMethod(GetSelLdrSeccomp)
1191 def SupportsSeccompBpfSandbox(env):
1192 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1195 # The gcov runtime does some extra calls (such as 'access') that
1196 # are not permitted by the policy.
1197 if env.Bit('coverage_enabled'):
1200 # This is a lame detection if seccomp bpf filters are supported by the kernel.
1201 # We suppose that any Linux kernel v3.2+ supports it, but it is only true
1202 # for Ubuntu kernels. Seccomp BPF filters reached the mainline at 3.5,
1203 # so this check will be wrong on some relatively old non-Ubuntu Linux distros.
1204 kernel_version = map(int, platform.release().split('.', 2)[:2])
1205 return kernel_version >= [3, 2]
1207 pre_base_env.AddMethod(SupportsSeccompBpfSandbox)
1210 def GetBootstrap(env):
1212 # Bootstrap doens't currently work with MSan. However, MSan is only
1213 # available on x86_64 where we don't need bootstrap anyway.
1215 bootstrap = ARGUMENTS.get('force_bootstrap')
1217 bootstrap = env.File(env.SConstructAbsPath(bootstrap))
1219 if 'TRUSTED_ENV' in env:
1220 trusted_env = env['TRUSTED_ENV']
1221 if trusted_env.Bit('linux'):
1222 bootstrap = trusted_env.File('${STAGING_DIR}/nacl_helper_bootstrap')
1224 template_digits = 'X' * 16
1226 ['--r_debug=0x' + template_digits,
1227 '--reserved_at_zero=0x' + template_digits])
1230 pre_base_env.AddMethod(GetBootstrap)
1232 def AddBootstrap(env, executable, args):
1233 bootstrap, bootstrap_args = env.GetBootstrap()
1234 if bootstrap is None:
1235 return [executable] + args
1237 return [bootstrap, executable] + bootstrap_args + args
1239 pre_base_env.AddMethod(AddBootstrap)
1242 def GetNonSfiLoader(env):
1243 if env.Bit('use_newlib_nonsfi_loader'):
1244 return nacl_env.GetTranslatedNexe(nacl_env.File(
1245 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}'))
1247 if 'TRUSTED_ENV' not in env:
1249 return env['TRUSTED_ENV'].File(
1250 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}')
1252 pre_base_env.AddMethod(GetNonSfiLoader)
1255 def GetIrtNexe(env, chrome_irt=False):
1256 image = ARGUMENTS.get('force_irt')
1258 return env.SConstructAbsPath(image)
1261 return nacl_irt_env.File('${STAGING_DIR}/irt.nexe')
1263 return nacl_irt_env.File('${STAGING_DIR}/irt_core.nexe')
1265 pre_base_env.AddMethod(GetIrtNexe)
1268 # Note that we build elf_loader in the nacl_irt_env, not because it is
1269 # actually built like the IRT per se, but just because we need it always to
1270 # be built against newlib.
1271 def GetElfLoaderNexe(env):
1272 elf_loader_env = nacl_env
1273 if env.Bit('nacl_glibc'):
1274 elf_loader_env = nacl_irt_env
1275 return elf_loader_env.File('${STAGING_DIR}/elf_loader.nexe')
1277 pre_base_env.AddMethod(GetElfLoaderNexe)
1280 def ApplyTLSEdit(env, nexe_name, raw_nexe):
1281 # If the environment was built elsewhere, we do not need to apply tls_edit
1282 # since it only needs to be done during building.
1283 if env.Bit('built_elsewhere'):
1284 return env.File(nexe_name)
1286 tls_edit_exe = env['BUILD_ENV'].File('${STAGING_DIR}/tls_edit${PROGSUFFIX}')
1289 [tls_edit_exe, raw_nexe],
1290 '${SOURCES[0]} --verbose ${SOURCES[1:]} ${TARGET}')
1292 pre_base_env.AddMethod(ApplyTLSEdit)
1294 def CommandValidatorTestNacl(env, name, image,
1295 validator_flags=None,
1299 validator = env.GetValidator(validator)
1300 if validator is None:
1301 print 'WARNING: no validator found. Skipping test %s' % name
1304 if validator_flags is None:
1305 validator_flags = []
1307 if env.Bit('pnacl_generate_pexe'):
1310 command = [validator] + validator_flags + [image]
1311 return env.CommandTest(name, command, size, **extra)
1313 pre_base_env.AddMethod(CommandValidatorTestNacl)
1316 def ExtractPublishedFiles(env, target_name):
1317 run_files = ['$STAGING_DIR/' + os.path.basename(published_file.path)
1318 for published_file in env.GetPublished(target_name, 'run')]
1319 nexe = '$STAGING_DIR/%s${PROGSUFFIX}' % target_name
1320 return [env.File(file) for file in run_files + [nexe]]
1322 pre_base_env.AddMethod(ExtractPublishedFiles)
1325 # Only include the chrome side of the build if present.
1326 if os.path.exists(pre_base_env.File(
1327 '#/../ppapi/native_client/chrome_main.scons').abspath):
1328 SConscript('#/../ppapi/native_client/chrome_main.scons',
1329 exports=['pre_base_env'])
1330 enable_chrome = True
1332 def AddChromeFilesFromGroup(env, file_group):
1334 pre_base_env.AddMethod(AddChromeFilesFromGroup)
1335 enable_chrome = False
1336 DeclareBit('enable_chrome_side',
1337 'Is the chrome side present.')
1338 pre_base_env.SetBitFromOption('enable_chrome_side', enable_chrome)
1340 def ProgramNameForNmf(env, basename):
1341 """ Create an architecture-specific filename that can be used in an NMF URL.
1343 if env.Bit('pnacl_generate_pexe'):
1346 return '%s_%s' % (basename, env.get('TARGET_FULLARCH'))
1348 pre_base_env.AddMethod(ProgramNameForNmf)
1351 def MakeNaClLogOption(env, target):
1352 """ Make up a filename related to the [target], for use with NACLLOG.
1353 The file should end up in the build directory (scons-out/...).
1355 # NOTE: to log to the source directory use file.srcnode().abspath instead.
1356 # See http://www.scons.org/wiki/File%28%29
1357 return env.File(target + '.nacllog').abspath
1359 pre_base_env.AddMethod(MakeNaClLogOption)
1361 def MakeVerboseExtraOptions(env, target, log_verbosity, extra):
1362 """ Generates **extra options that will give access to service runtime logs,
1363 at a given log_verbosity. Slips the options into the given extra dict. """
1364 log_file = env.MakeNaClLogOption(target)
1365 extra['log_file'] = log_file
1366 extra_env = ['NACLLOG=%s' % log_file,
1367 'NACLVERBOSITY=%d' % log_verbosity]
1368 extra['osenv'] = extra.get('osenv', []) + extra_env
1370 pre_base_env.AddMethod(MakeVerboseExtraOptions)
1372 def ShouldUseVerboseOptions(env, extra):
1373 """ Heuristic for setting up Verbose NACLLOG options. """
1374 return ('process_output_single' in extra or
1375 'log_golden' in extra)
1377 pre_base_env.AddMethod(ShouldUseVerboseOptions)
1380 DeclareBit('tests_use_irt', 'Non-browser tests also load the IRT image', False)
1382 # Bit to be set by individual test/nacl.scons files that need to opt out.
1383 DeclareBit('nonstable_bitcode', 'Tests use non-stable bitcode features', False)
1386 def GetFinalizedPexe(env, pexe):
1387 """ Prep and finalize the ABI for a given pexe if needed.
1389 if not env.Bit('pnacl_generate_pexe') or env.Bit('nonstable_bitcode'):
1392 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1393 # file instead. There are currently some canned nexe tests in build.scons.
1394 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1397 # Otherwise, finalize during the build step, since there is no finalize tool
1398 # that can run on triggered bots such as the ARM HW bots.
1399 pexe_name = pexe.abspath
1400 final_name = StripSuffix(pexe_name, '.nonfinal.pexe') + '.final.pexe'
1401 # Make sure the pexe doesn't get removed by the fake builders when
1404 node = env.Command(target=final_name, source=[pexe_name],
1405 action=[Action('${PNACLFINALIZECOM}',
1406 '${PNACLFINALIZECOMSTR}')])
1407 env.Alias('all_programs', node)
1408 assert len(node) == 1, node
1411 pre_base_env.AddMethod(GetFinalizedPexe)
1414 # Translate the given pexe.
1415 def GetTranslatedNexe(env, pexe):
1416 # First finalize the pexe.
1417 pexe = GetFinalizedPexe(env, pexe)
1419 # Then check if we need to translate.
1420 # Check if we started with a pexe, so there is actually a translation step.
1421 if not env.Bit('pnacl_generate_pexe'):
1424 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1425 # file instead. There are currently some canned nexe tests in build.scons.
1426 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1429 # Often there is a build step (do_not_run_tests=1) and a test step
1430 # (which is run with -j1). Normally we want to translate in the build step
1431 # so we can translate in parallel. However when we do sandboxed translation
1432 # on arm hw, we do the build step on x86 and translation on arm, so we have
1433 # to force the translation to be done in the test step. Hence,
1434 # we check the bit 'translate_in_build_step' / check if we are
1436 if not env.Bit('translate_in_build_step') and env.Bit('do_not_run_tests'):
1439 pexe_name = pexe.abspath
1440 # Tidy up the suffix (remove the .final.pexe or .nonfinal.pexe),
1441 # depending on whether or not the pexe was finalized.
1442 suffix_to_strip = '.final.pexe'
1443 if not pexe_name.endswith(suffix_to_strip):
1444 suffix_to_strip = '.nonfinal.pexe'
1445 nexe_name = StripSuffix(pexe_name, suffix_to_strip) + '.nexe'
1446 # Make sure the pexe doesn't get removed by the fake builders when
1449 command = '${TRANSLATECOM}'
1450 if env.Bit('nonstable_bitcode'):
1451 command += ' --allow-llvm-bitcode-input'
1452 node = env.Command(target=nexe_name, source=[pexe_name],
1453 action=[Action(command, '${TRANSLATECOMSTR}')])
1454 env.Alias('all_programs', node)
1455 assert len(node) == 1, node
1458 pre_base_env.AddMethod(GetTranslatedNexe)
1461 def CommandTestFileDumpCheck(env,
1466 """Create a test that disassembles a binary (|target|) and checks for
1467 patterns in the |check_file|. Disassembly is done using |objdump_flags|.
1470 # Do not try to run OBJDUMP if 'built_elsewhere', since that *might* mean
1471 # that a toolchain is not even present. E.g., the arm hw buildbots do
1472 # not have the pnacl toolchain. We should be able to look for the host
1473 # ARM objdump though... a TODO(jvoung) for when there is time.
1474 if env.Bit('built_elsewhere'):
1476 target = env.GetTranslatedNexe(target)
1477 return env.CommandTestFileCheck(name,
1478 ['${OBJDUMP}', objdump_flags, target],
1481 pre_base_env.AddMethod(CommandTestFileDumpCheck)
1483 def CommandTestFileCheck(env, name, cmd, check_file):
1484 """Create a test that runs a |cmd| (array of strings),
1485 which is expected to print to stdout. The results
1486 of stdout will then be piped to the file_check.py tool which
1487 will search for the regexes specified in |check_file|. """
1489 return env.CommandTest(
1492 env.File('${SCONSTRUCT_DIR}/tools/llvm_file_check_wrapper.py'),
1495 direct_emulation=False)
1497 pre_base_env.AddMethod(CommandTestFileCheck)
1499 def CommandSelLdrTestNacl(env, name, nexe,
1505 # True for *.nexe statically linked with glibc
1507 skip_bootstrap=False,
1508 wrapper_program_prefix=None,
1509 # e.g., [ 'python', 'time_check.py', '--' ]
1511 # Disable all sel_ldr tests for windows under coverage.
1512 # Currently several .S files block sel_ldr from being instrumented.
1513 # See http://code.google.com/p/nativeclient/issues/detail?id=831
1514 if ('TRUSTED_ENV' in env and
1515 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1516 env['TRUSTED_ENV'].Bit('windows')):
1519 # The nexe might be a pexe that needs finalization, and translation.
1520 nexe = env.GetTranslatedNexe(nexe)
1523 if args is not None:
1526 if env.Bit('pnacl_unsandboxed') or (env.Bit('nonsfi_nacl') and
1527 not env.Bit('tests_use_irt')):
1528 # Run unsandboxed executable directly, without sel_ldr.
1529 return env.CommandTest(name, command, size, **extra)
1532 if env.Bit('nonsfi_nacl'):
1533 loader = env.GetNonSfiLoader()
1535 loader = env.GetSelLdr()
1537 print 'WARNING: no sel_ldr found. Skipping test %s' % name
1540 # Avoid problems with [] as default arguments
1541 if sel_ldr_flags is None:
1544 # Avoid modifying original list
1545 sel_ldr_flags = list(sel_ldr_flags)
1547 # Disable the validator if running a GLibC test under Valgrind.
1548 # http://code.google.com/p/nativeclient/issues/detail?id=1799
1549 if env.IsRunningUnderValgrind() and env.Bit('nacl_glibc'):
1550 sel_ldr_flags += ['-cc']
1551 # https://code.google.com/p/nativeclient/issues/detail?id=3158
1552 # We don't currently have valgrind.so for LD_PRELOAD to use. That .so
1553 # is not used for newlib.
1554 # TODO(sehr): add valgrind.so built for NaCl.
1557 # Skip platform qualification checks on configurations with known issues.
1558 if env.GetEmulator() or env.IsRunningUnderValgrind():
1559 sel_ldr_flags += ['-Q']
1561 # Skip validation if we are using the x86-64 zero-based sandbox.
1562 # TODO(arbenson): remove this once the validator supports the x86-64
1563 # zero-based sandbox model.
1564 if env.Bit('x86_64_zero_based_sandbox'):
1565 sel_ldr_flags += ['-c']
1567 # The glibc modifications only make sense for nacl_env tests.
1568 # But this function gets used by some base_env (i.e. src/trusted/...)
1569 # tests too. Don't add the --nacl_glibc changes to the command
1570 # line for those cases.
1571 if env.Bit('nacl_glibc') and env['NACL_BUILD_FAMILY'] != 'TRUSTED':
1572 if not glibc_static and not env.Bit('nacl_static_link'):
1573 # Enable file access so shared libraries can be loaded.
1574 sel_ldr_flags.append('-a')
1575 # Locally-built shared libraries come from ${LIB_DIR} while
1576 # toolchain-provided ones come from ${NACL_SDK_LIB}.
1577 library_path = '${LIB_DIR}:${NACL_SDK_LIB}'
1578 if env.Bit('build_x86'):
1579 # In the old glibc, we run via runnable-ld.so (the dynamic linker).
1580 command = ['${NACL_SDK_LIB}/runnable-ld.so',
1581 '--library-path', library_path] + command
1583 # In the new glibc, we run via elf_loader and direct it where to
1584 # find the dynamic linker in the toolchain.
1585 command = [env.GetElfLoaderNexe(),
1587 os.path.dirname(env.subst('${NACL_SDK_LIB}'))] + command
1588 sel_ldr_flags.extend(['-E', 'LD_LIBRARY_PATH=' + library_path])
1590 # Turn off sandbox for mac so coverage files can be written out.
1591 if ('TRUSTED_ENV' in env and
1592 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1593 env.Bit('host_mac') and
1594 '-a' not in sel_ldr_flags):
1595 sel_ldr_flags += ['-a']
1597 if env.Bit('tests_use_irt'):
1598 sel_ldr_flags += ['-B', nacl_env.GetIrtNexe()]
1601 loader_cmd = [loader]
1603 loader_cmd = env.AddBootstrap(loader, [])
1605 if env.Bit('nonsfi_nacl'):
1606 # nonsfi_loader does not accept the same flags as sel_ldr yet, so
1607 # we ignore sel_ldr_flags here.
1608 command = [loader] + command
1610 command = loader_cmd + sel_ldr_flags + ['--'] + command
1612 if env.Bit('host_linux'):
1613 extra['using_nacl_signal_handler'] = True
1615 if env.ShouldUseVerboseOptions(extra):
1616 env.MakeVerboseExtraOptions(name, log_verbosity, extra)
1618 node = env.CommandTest(name, command, size, posix_path=True,
1619 wrapper_program_prefix=wrapper_program_prefix, **extra)
1620 if env.Bit('tests_use_irt'):
1621 env.Alias('irt_tests', node)
1624 pre_base_env.AddMethod(CommandSelLdrTestNacl)
1627 TEST_EXTRA_ARGS = ['stdin', 'log_file',
1628 'stdout_golden', 'stderr_golden', 'log_golden',
1629 'filter_regex', 'filter_inverse', 'filter_group_only',
1630 'osenv', 'arch', 'subarch', 'exit_status',
1631 'num_runs', 'process_output_single',
1632 'process_output_combined', 'using_nacl_signal_handler',
1633 'declares_exit_status', 'time_warning', 'time_error']
1635 TEST_TIME_THRESHOLD = {
1642 # Valgrind handles SIGSEGV in a way our testing tools do not expect.
1643 UNSUPPORTED_VALGRIND_EXIT_STATUS = ['trusted_sigabrt',
1644 'untrusted_sigill' ,
1645 'untrusted_segfault',
1646 'untrusted_sigsegv_or_equivalent',
1648 'trusted_sigsegv_or_equivalent']
1651 def GetPerfEnvDescription(env):
1652 """Return a string describing architecture, library, etc. options.
1654 This function attempts to gather a string that might inform why a performance
1655 change has occurred.
1657 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1658 # Trusted tests do not depend on the untrusted toolchain, untrusted libc,
1659 # whether or not the IRT is used, etc.
1660 description_list = ['trusted',
1661 env['TARGET_PLATFORM'].lower(),
1662 env['TARGET_FULLARCH']]
1663 return ARGUMENTS.get('perf_prefix', '') + '_'.join(description_list)
1664 description_list = [env['TARGET_FULLARCH']]
1665 # Using a list to keep the order consistent.
1666 bit_to_description = [ ('tests_use_irt', ('with_irt', '')),
1667 ('bitcode', ('pnacl', 'nnacl')),
1668 ('translate_fast', ('fast', '')),
1669 ('use_sz', ('sz', '')),
1670 ('nacl_glibc', ('glibc', 'newlib')),
1671 ('nacl_static_link', ('static', 'dynamic')),
1673 for (bit, (descr_yes, descr_no)) in bit_to_description:
1675 additional = descr_yes
1677 additional = descr_no
1679 description_list.append(additional)
1680 return ARGUMENTS.get('perf_prefix', '') + '_'.join(description_list)
1682 pre_base_env.AddMethod(GetPerfEnvDescription)
1687 def GetTestName(target):
1688 key = str(target.path)
1689 return TEST_NAME_MAP.get(key, key)
1691 pre_base_env['GetTestName'] = GetTestName
1694 def SetTestName(node, name):
1695 for target in Flatten(node):
1696 TEST_NAME_MAP[str(target.path)] = name
1699 def ApplyTestWrapperCommand(command_args, extra_deps):
1700 new_args = ARGUMENTS['test_wrapper'].split()
1701 for input_file in extra_deps:
1702 new_args.extend(['-F', input_file])
1703 for arg in command_args:
1704 if isinstance(arg, str):
1705 new_args.extend(['-a', arg])
1707 new_args.extend(['-f', arg])
1711 def CommandTest(env, name, command, size='small', direct_emulation=True,
1712 extra_deps=[], posix_path=False, capture_output=True,
1713 capture_stderr=True, wrapper_program_prefix=None,
1714 scale_timeout=None, **extra):
1715 if not name.endswith('.out') or name.startswith('$'):
1716 raise Exception('ERROR: bad test filename for test output %r' % name)
1718 if env.IsRunningUnderValgrind():
1720 elif env.Bit('asan'):
1721 skip = 'AddressSanitizer'
1724 # Valgrind tends to break crash tests by changing the exit status.
1725 # So far, tests using declares_exit_status are crash tests. If this
1726 # changes, we will have to find a way to make declares_exit_status
1727 # work with Valgrind.
1728 if (skip is not None and
1729 (extra.get('exit_status') in UNSUPPORTED_VALGRIND_EXIT_STATUS or
1730 bool(int(extra.get('declares_exit_status', 0))))):
1731 print 'Skipping death test "%s" under %s' % (name, skip)
1735 extra.setdefault('osenv', [])
1736 # Ensure that 'osenv' is a list.
1737 if isinstance(extra['osenv'], str):
1738 extra['osenv'] = [extra['osenv']]
1739 # ASan normally intercepts SIGSEGV and SIGFPE and disables our signal
1740 # handlers, which interferes with various NaCl tests, including the
1741 # platform qualification test built into sel_ldr. We fix this by telling
1742 # ASan not to mess with SIGSEGV and SIGFPE.
1743 asan_options = ['handle_segv=0', 'handle_sigfpe=0']
1744 # ASan aborts on errors rather than exits. This changes the expected exit
1745 # codes for some tests.
1746 asan_options.append('abort_on_error=0')
1748 if env.Bit('host_mac') and int(platform.mac_ver()[0].split('.')[1]) < 7:
1749 # MacOS 10.6 has a bug in the libsandbox system library where it
1750 # makes a memcmp call that reads off the end of a malloc'd block.
1751 # The bug appears to be harmless, but trips an ASan report. So
1752 # tell ASan to suppress memcmp checks.
1753 asan_options.append('strict_memcmp=0')
1754 # TODO(mcgrathr): Remove this when we clean up all the crufty old
1755 # code to be leak-free.
1756 # https://code.google.com/p/nativeclient/issues/detail?id=3874
1757 asan_options.append('detect_leaks=0')
1758 # Note that the ASan runtime doesn't use : specifically as a separator.
1759 # It actually just looks for "foo=" anywhere in the string with strstr,
1760 # so any separator will do. The most obvious choices, ' ', ',', and ';'
1761 # all cause command_tester.py to split things up and get confused.
1762 extra['osenv'].append('ASAN_OPTIONS=' + ':'.join(asan_options))
1764 name = '${TARGET_ROOT}/test_results/' + name
1765 # NOTE: using the long version of 'name' helps distinguish opt vs dbg
1766 max_time = TEST_TIME_THRESHOLD[size]
1767 if 'scale_timeout' in ARGUMENTS:
1768 max_time = max_time * int(ARGUMENTS['scale_timeout'])
1770 max_time = max_time * scale_timeout
1772 if env.Bit('nacl_glibc'):
1773 suite = 'nacl_glibc'
1775 suite = 'nacl_newlib'
1776 if env.Bit('bitcode'):
1779 script_flags = ['--name', '%s.${GetTestName(TARGET)}' % suite,
1780 '--time_warning', str(max_time),
1781 '--time_error', str(10 * max_time),
1784 run_under = ARGUMENTS.get('run_under')
1786 run_under_extra_args = ARGUMENTS.get('run_under_extra_args')
1787 if run_under_extra_args:
1788 run_under = run_under + ',' + run_under_extra_args
1789 script_flags.append('--run_under')
1790 script_flags.append(run_under)
1792 emulator = env.GetEmulator()
1793 if emulator and direct_emulation:
1794 command = [emulator] + command
1796 # test wrapper should go outside of emulators like qemu, since the
1797 # test wrapper code is not emulated.
1798 if wrapper_program_prefix is not None:
1799 command = wrapper_program_prefix + command
1801 script_flags.append('--perf_env_description')
1802 script_flags.append(env.GetPerfEnvDescription())
1804 # Add architecture info.
1805 extra['arch'] = env['BUILD_ARCHITECTURE']
1806 extra['subarch'] = env['BUILD_SUBARCH']
1808 for flag_name, flag_value in extra.iteritems():
1809 assert flag_name in TEST_EXTRA_ARGS, repr(flag_name)
1810 if isinstance(flag_value, list):
1811 # Options to command_tester.py which are actually lists must not be
1812 # separated by whitespace. This stringifies the lists with a separator
1813 # char to satisfy command_tester.
1814 flag_value = command_tester.StringifyList(flag_value)
1815 # do not add --flag + |flag_name| |flag_value| if
1816 # |flag_value| is false (empty).
1818 script_flags.append('--' + flag_name)
1819 # Make sure flag values are strings (or SCons objects) when building
1820 # up the command. Right now, this only means convert ints to strings.
1821 if isinstance(flag_value, int):
1822 flag_value = str(flag_value)
1823 script_flags.append(flag_value)
1826 if not capture_output:
1827 script_flags.extend(['--capture_output', '0'])
1828 if not capture_stderr:
1829 script_flags.extend(['--capture_stderr', '0'])
1831 # Set command_tester.py's output filename. We skip this when using
1832 # test_wrapper because the run_test_via_ssh.py wrapper does not have
1833 # the ability to copy result files back from the remote host.
1834 if 'test_wrapper' not in ARGUMENTS:
1835 script_flags.extend(['--output_stamp', name])
1837 test_script = env.File('${SCONSTRUCT_DIR}/tools/command_tester.py')
1838 extra_deps = extra_deps + [env.File('${SCONSTRUCT_DIR}/tools/test_lib.py')]
1839 command = ['${PYTHON}', test_script] + script_flags + command
1840 if 'test_wrapper' in ARGUMENTS:
1841 command = ApplyTestWrapperCommand(command, extra_deps)
1842 return env.AutoDepsCommand(name, command,
1843 extra_deps=extra_deps, posix_path=posix_path,
1844 disabled=env.Bit('do_not_run_tests'))
1846 pre_base_env.AddMethod(CommandTest)
1849 def FileSizeTest(env, name, envFile, max_size=None):
1850 """FileSizeTest() returns a scons node like the other XYZTest generators.
1851 It logs the file size of envFile in a perf-buildbot-recognizable format.
1852 Optionally, it can cause a test failure if the file is larger than max_size.
1854 def doSizeCheck(target, source, env):
1855 filepath = source[0].abspath
1856 actual_size = os.stat(filepath).st_size
1857 command_tester.LogPerfResult(name,
1858 env.GetPerfEnvDescription(),
1859 '%.3f' % (actual_size / 1024.0),
1861 # Also get zipped size.
1862 nexe_file = open(filepath, 'rb')
1863 zipped_size = len(zlib.compress(nexe_file.read()))
1865 command_tester.LogPerfResult(name,
1866 'ZIPPED_' + env.GetPerfEnvDescription(),
1867 '%.3f' % (zipped_size / 1024.0),
1869 # Finally, do the size check.
1870 if max_size is not None and actual_size > max_size:
1871 # NOTE: this exception only triggers a failure for this particular test,
1872 # just like any other test failure.
1873 raise Exception("File %s larger than expected: expected up to %i, got %i"
1874 % (filepath, max_size, actual_size))
1875 # If 'built_elsewhere', the file should should have already been built.
1876 # Do not try to built it and/or its pieces.
1877 if env.Bit('built_elsewhere'):
1878 env.Ignore(name, envFile)
1879 return env.Command(name, envFile, doSizeCheck)
1881 pre_base_env.AddMethod(FileSizeTest)
1883 def StripExecutable(env, name, exe):
1884 """StripExecutable returns a node representing the stripped version of |exe|.
1885 The stripped version will be given the basename |name|.
1886 NOTE: for now this only works with the untrusted toolchain.
1887 STRIP does not appear to be a first-class citizen in SCons and
1888 STRIP has only been set to point at the untrusted toolchain.
1893 action=[Action('${STRIPCOM} ${SOURCES} -o ${TARGET}', '${STRIPCOMSTR}')])
1895 pre_base_env.AddMethod(StripExecutable)
1898 # TODO(ncbray): pretty up the log output when running this builder.
1899 def DisabledCommand(target, source, env):
1902 pre_base_env['BUILDERS']['DisabledCommand'] = Builder(action=DisabledCommand)
1905 def AutoDepsCommand(env, name, command, extra_deps=[], posix_path=False,
1907 """AutoDepsCommand() takes a command as an array of arguments. Each
1908 argument may either be:
1911 * a Scons file object, e.g. one created with env.File() or as the
1912 result of another build target.
1914 In the second case, the file is automatically declared as a
1915 dependency of this command.
1917 command = list(command)
1919 for index, arg in enumerate(command):
1920 if not isinstance(arg, str):
1921 if len(Flatten(arg)) != 1:
1922 # Do not allow this, because it would cause "deps" to get out
1923 # of sync with the indexes in "command".
1924 # See http://code.google.com/p/nativeclient/issues/detail?id=1086
1925 raise AssertionError('Argument to AutoDepsCommand() actually contains '
1926 'multiple (or zero) arguments: %r' % arg)
1928 command[index] = '${SOURCES[%d].posix}' % len(deps)
1930 command[index] = '${SOURCES[%d].abspath}' % len(deps)
1933 # If built_elsewhere, build commands are replaced by no-ops, so make sure
1934 # the targets don't get removed first
1935 if env.Bit('built_elsewhere'):
1937 env.Depends(name, extra_deps)
1940 return env.DisabledCommand(name, deps)
1942 return env.Command(name, deps, ' '.join(command))
1945 pre_base_env.AddMethod(AutoDepsCommand)
1948 def GetPrintableCommandName(cmd):
1949 """Look at the first few elements of cmd to derive a suitable command name."""
1950 cmd_tokens = cmd.split()
1951 if "python" in cmd_tokens[0] and len(cmd_tokens) >= 2:
1952 cmd_name = cmd_tokens[1]
1954 cmd_name = cmd_tokens[0].split('(')[0]
1956 # undo some pretty printing damage done by hammer
1957 cmd_name = cmd_name.replace('________','')
1958 # use file name part of a path
1959 return cmd_name.split('/')[-1]
1962 def GetPrintableEnvironmentName(env):
1963 # use file name part of a obj root path as env name
1964 return env.subst('${TARGET_ROOT}').split('/')[-1]
1966 pre_base_env.AddMethod(GetPrintableEnvironmentName)
1969 def CustomCommandPrinter(cmd, targets, source, env):
1970 # Abuse the print hook to count the commands that are executed
1971 if env.Bit('target_stats'):
1972 cmd_name = GetPrintableCommandName(cmd)
1973 env_name = env.GetPrintableEnvironmentName()
1974 CMD_COUNTER[cmd_name] = CMD_COUNTER.get(cmd_name, 0) + 1
1975 ENV_COUNTER[env_name] = ENV_COUNTER.get(env_name, 0) + 1
1978 # Our pretty printer
1980 cmd_name = GetPrintableCommandName(cmd)
1981 env_name = env.GetPrintableEnvironmentName()
1982 sys.stdout.write('[%s] [%s] %s\n' % (cmd_name, env_name,
1983 targets[0].get_path()))
1985 # The SCons default (copied from print_cmd_line in Action.py)
1986 sys.stdout.write(cmd + u'\n')
1988 if 'generate_ninja' not in ARGUMENTS:
1989 pre_base_env.Append(PRINT_CMD_LINE_FUNC=CustomCommandPrinter)
1992 def GetAbsDirArg(env, argument, target):
1993 """Fetch the named command-line argument and turn it into an absolute
1994 directory name. If the argument is missing, raise a UserError saying
1995 that the given target requires that argument be given."""
1996 dir = ARGUMENTS.get(argument)
1998 raise UserError('%s must be set when invoking %s' % (argument, target))
1999 return os.path.join(env.Dir('$MAIN_DIR').abspath, dir)
2001 pre_base_env.AddMethod(GetAbsDirArg)
2004 def MakeGTestEnv(env):
2005 # Create an environment to run unit tests using Gtest.
2006 gtest_env = env.Clone()
2008 if gtest_env['NACL_BUILD_FAMILY'] != 'TRUSTED' or not gtest_env.Bit('mac'):
2009 # This became necessary for the arm cross TC v4.6 but probable applies
2010 # to all new gcc TCs. MacOS does not have this switch.
2011 gtest_env.Append(LINKFLAGS=['-pthread'])
2013 # Define compile-time flag that communicates that we are compiling in the test
2014 # environment (rather than for the TCB).
2015 if gtest_env['NACL_BUILD_FAMILY'] == 'TRUSTED':
2016 gtest_env.Append(CCFLAGS=['-DNACL_TRUSTED_BUT_NOT_TCB'])
2018 # This is necessary for unittest_main.c which includes gtest/gtest.h
2019 # The problem is that gtest.h includes other files expecting the
2020 # include path to be set.
2021 gtest_env.Prepend(CPPPATH=['${SOURCE_ROOT}/testing/gtest/include'])
2023 # gtest does not compile with our stringent settings.
2024 if gtest_env.Bit('linux') or gtest_env.Bit('mac'):
2025 # "-pedantic" is because of: gtest-typed-test.h:236:46: error:
2026 # anonymous variadic macros were introduced in C99
2027 # Also, gtest does not compile successfully with "-Wundef".
2028 gtest_env.FilterOut(CCFLAGS=['-pedantic', '-Wundef'])
2029 gtest_env.FilterOut(CXXFLAGS=['-fno-rtti', '-Weffc++'])
2031 # gtest is incompatible with static linking due to obscure libstdc++
2032 # linking interactions.
2033 # See http://code.google.com/p/nativeclient/issues/detail?id=1987
2034 gtest_env.FilterOut(LINKFLAGS=['-static'])
2036 gtest_env.Prepend(LIBS=['gtest'])
2039 pre_base_env.AddMethod(MakeGTestEnv)
2041 def MakeUntrustedNativeEnv(env):
2042 native_env = nacl_env.Clone()
2043 if native_env.Bit('bitcode') and not native_env.Bit('build_mips32'):
2044 native_env = native_env.PNaClGetNNaClEnv()
2047 pre_base_env.AddMethod(MakeUntrustedNativeEnv)
2049 def MakeBaseTrustedEnv(platform=None):
2050 base_env = MakeArchSpecificEnv(platform)
2052 IS_BUILD_ENV = False,
2059 EXTRA_CXXFLAGS = [],
2061 CFLAGS = ['${EXTRA_CFLAGS}'],
2062 CXXFLAGS = ['${EXTRA_CXXFLAGS}'],
2064 if base_env.Bit('ncval_testing'):
2065 base_env.Append(CPPDEFINES = ['NCVAL_TESTING'])
2067 base_env.Append(BUILD_SCONSCRIPTS = [
2068 # KEEP THIS SORTED PLEASE
2069 'build/package_version/build.scons',
2070 'pynacl/build.scons',
2071 'src/nonsfi/irt/build.scons',
2072 'src/nonsfi/loader/build.scons',
2073 'src/shared/gio/build.scons',
2074 'src/shared/imc/build.scons',
2075 'src/shared/platform/build.scons',
2076 'src/third_party/gtest/build.scons',
2077 'src/trusted/cpu_features/build.scons',
2078 'src/trusted/debug_stub/build.scons',
2079 'src/trusted/desc/build.scons',
2080 'src/trusted/fault_injection/build.scons',
2081 'src/trusted/interval_multiset/build.scons',
2082 'src/trusted/nacl_base/build.scons',
2083 'src/trusted/perf_counter/build.scons',
2084 'src/trusted/platform_qualify/build.scons',
2085 'src/trusted/seccomp_bpf/build.scons',
2086 'src/trusted/service_runtime/build.scons',
2087 'src/trusted/validator/build.scons',
2088 'src/trusted/validator/driver/build.scons',
2089 'src/trusted/validator_arm/build.scons',
2090 'src/trusted/validator_ragel/build.scons',
2091 'src/trusted/validator_x86/build.scons',
2092 'tests/common/build.scons',
2093 'tests/lock_manager/build.scons',
2094 'tests/performance/build.scons',
2095 'tests/python_version/build.scons',
2096 'tests/sel_ldr_seccomp/build.scons',
2097 'tests/tools/build.scons',
2098 'tests/unittests/shared/imc/build.scons',
2099 'tests/unittests/shared/platform/build.scons',
2100 'tests/unittests/trusted/asan/build.scons',
2101 'tests/unittests/trusted/bits/build.scons',
2102 'tests/unittests/trusted/platform_qualify/build.scons',
2103 'tests/unittests/trusted/service_runtime/build.scons',
2104 'toolchain_build/build.scons',
2107 base_env.AddMethod(SDKInstallBin)
2109 # The ARM and MIPS validators can be built for any target that doesn't use
2111 if not base_env.Bit('build_x86_64'):
2113 BUILD_SCONSCRIPTS = [
2114 'src/trusted/validator_mips/build.scons',
2117 base_env.AddChromeFilesFromGroup('trusted_scons_files')
2120 NACL_BUILD_FAMILY = 'TRUSTED',
2123 # Add optional scons files if present in the directory tree.
2124 if os.path.exists(pre_base_env.subst('${MAIN_DIR}/supplement/build.scons')):
2125 base_env.Append(BUILD_SCONSCRIPTS=['${MAIN_DIR}/supplement/build.scons'])
2130 # Select tests to run under coverage build.
2131 pre_base_env['COVERAGE_TARGETS'] = [
2132 'small_tests', 'medium_tests', 'large_tests',
2133 'chrome_browser_tests']
2136 pre_base_env.Help("""\
2137 ======================================================================
2139 ======================================================================
2144 * cleaning: scons -c
2146 * smoke test: scons --mode=nacl,opt-linux -k pp=1 smoke_tests
2148 * sel_ldr: scons --mode=opt-linux sel_ldr
2150 Targets to build trusted code destined for the SDK:
2151 * build trusted-code tools: scons build_bin
2152 * install trusted-code tools: scons install_bin bindir=...
2153 * These default to opt build, or add --mode=dbg-host for debug build.
2155 Targets to build untrusted code destined for the SDK:
2156 * build just libraries: scons build_lib
2157 * install just headers: scons install_headers includedir=...
2158 * install just libraries: scons install_lib libdir=...
2159 * install headers and libraries:scons install includedir=... libdir=...
2161 * dump system info: scons --mode=nacl,opt-linux dummy
2166 --prebuilt Do not build things, just do install steps
2168 --verbose Full command line logging before command execution
2170 pp=1 Use command line pretty printing (more concise output)
2172 sysinfo=1 Verbose system info printing
2174 naclsdk_validate=0 Suppress presence check of sdk
2178 Automagically generated help:
2179 -----------------------------
2183 def SetUpClang(env):
2184 env['CLANG_DIR'] = '${SOURCE_ROOT}/third_party/llvm-build/Release+Asserts/bin'
2185 env['CLANG_OPTS'] = []
2187 if not (env.Bit('host_linux') or env.Bit('host_mac')):
2188 raise UserError("ERROR: ASan is only available for Linux and Mac")
2189 env.Append(CLANG_OPTS=['-fsanitize=address',
2190 '-gline-tables-only',
2191 '-fno-omit-frame-pointer',
2192 '-DADDRESS_SANITIZER'])
2193 if env.Bit('host_mac'):
2194 # The built executables will try to find this library at runtime
2195 # in the directory containing the executable itself. In the
2196 # Chromium build, the library just gets copied into that
2197 # directory. Here, there isn't a single directory from which
2198 # all the test binaries are run (sel_ldr is run from staging/
2199 # but other trusted test binaries are run from their respective
2200 # obj/.../ directories). So instead just point the dynamic linker
2201 # at the right directory using an environment variable.
2202 # Be sure to check and update clang_lib_version whenever updating
2203 # tools/clang revs in DEPS.
2204 clang_lib_version = '4.0.0'
2205 clang_lib_dir = str(env.Dir('${CLANG_DIR}/../lib/clang/%s/lib/darwin' %
2206 clang_lib_version).abspath)
2207 env['ENV']['DYLD_LIBRARY_PATH'] = clang_lib_dir
2208 if 'PROPAGATE_ENV' not in env:
2209 env['PROPAGATE_ENV'] = []
2210 env['PROPAGATE_ENV'].append('DYLD_LIBRARY_PATH')
2213 if not env.Bit('host_linux') or not env.Bit('build_x86_64'):
2214 raise UserError('ERROR: MSan is only available for x86-64 Linux')
2215 track_origins = ARGUMENTS.get('msan_track_origins', '1')
2216 env.Append(CLANG_OPTS=['-fsanitize=memory',
2217 '-fsanitize-memory-track-origins=%s' % track_origins,
2218 '-gline-tables-only',
2219 '-fno-omit-frame-pointer',
2220 '-DMEMORY_SANITIZER'])
2222 env['CC'] = '${CLANG_DIR}/clang ${CLANG_OPTS}'
2223 env['CXX'] = '${CLANG_DIR}/clang++ ${CLANG_OPTS}'
2224 # Make sure we find Clang-supplied libraries like -lprofile_rt
2225 # in the Clang build we use, rather than from the system.
2226 # The system-installed versions go with the system-installed Clang
2227 # and might not be compatible with the Clang we're running.
2228 env.Append(LIBPATH=['${CLANG_DIR}/../lib'])
2230 def GenerateOptimizationLevels(env):
2231 if env.Bit('clang'):
2234 # Generate debug variant.
2235 debug_env = env.Clone(tools = ['target_debug'])
2236 debug_env['OPTIMIZATION_LEVEL'] = 'dbg'
2237 debug_env['BUILD_TYPE'] = debug_env.subst('$BUILD_TYPE')
2238 debug_env['BUILD_DESCRIPTION'] = debug_env.subst('$BUILD_DESCRIPTION')
2239 AddDualLibrary(debug_env)
2240 # Add to the list of fully described environments.
2241 environment_list.append(debug_env)
2243 # Generate opt variant.
2244 opt_env = env.Clone(tools = ['target_optimized'])
2245 opt_env['OPTIMIZATION_LEVEL'] = 'opt'
2246 opt_env['BUILD_TYPE'] = opt_env.subst('$BUILD_TYPE')
2247 opt_env['BUILD_DESCRIPTION'] = opt_env.subst('$BUILD_DESCRIPTION')
2248 AddDualLibrary(opt_env)
2249 # Add to the list of fully described environments.
2250 environment_list.append(opt_env)
2252 return (debug_env, opt_env)
2255 def SDKInstallBin(env, name, node, target=None):
2256 """Add the given node to the build_bin and install_bin targets.
2257 It will be installed under the given name with the build target appended.
2258 The optional target argument overrides the setting of what that target is."""
2259 env.Alias('build_bin', node)
2260 if 'install_bin' in COMMAND_LINE_TARGETS:
2261 dir = env.GetAbsDirArg('bindir', 'install_bin')
2263 target = env['TARGET_FULLARCH'].replace('-', '_')
2264 file_name, file_ext = os.path.splitext(name)
2265 output_name = file_name + '_' + target + file_ext
2266 install_node = env.InstallAs(os.path.join(dir, output_name), node)
2267 env.Alias('install_bin', install_node)
2270 def MakeWindowsEnv(platform=None):
2271 base_env = MakeBaseTrustedEnv(platform)
2272 windows_env = base_env.Clone(
2273 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-win',
2274 BUILD_TYPE_DESCRIPTION = 'Windows ${OPTIMIZATION_LEVEL} build',
2275 tools = ['target_platform_windows'],
2276 # Windows /SAFESEH linking requires either an .sxdata section be
2277 # present or that @feat.00 be defined as a local, absolute symbol
2278 # with an odd value.
2279 ASCOM = ('$ASPPCOM /E /D__ASSEMBLER__ | '
2280 '$WINASM -defsym @feat.00=1 -o $TARGET'),
2281 PDB = '${TARGET.base}.pdb',
2282 # Strict doesn't currently work for Windows since some of the system
2283 # libraries like wsock32 are magical.
2284 LIBS_STRICT = False,
2285 TARGET_ARCH='x86_64' if base_env.Bit('build_x86_64') else 'x86',
2290 ['_WIN32_WINNT', '0x0501'],
2291 ['__STDC_LIMIT_MACROS', '1'],
2293 # WIN32 is used by ppapi
2295 # WIN32_LEAN_AND_MEAN tells windows.h to omit obsolete and rarely
2296 # used #include files. This allows use of Winsock 2.0 which otherwise
2297 # would conflict with Winsock 1.x included by windows.h.
2298 ['WIN32_LEAN_AND_MEAN', ''],
2300 LIBS = ['ws2_32', 'advapi32'],
2301 # TODO(bsy) remove 4355 once cross-repo
2302 # NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
2303 CCFLAGS = ['/EHsc', '/WX', '/wd4355', '/wd4800']
2306 # This linker option allows us to ensure our builds are compatible with
2307 # Chromium, which uses it.
2308 if windows_env.Bit('build_x86_32'):
2309 windows_env.Append(LINKFLAGS = "/safeseh")
2311 # We use the GNU assembler (gas) on Windows so that we can use the
2312 # same .S assembly files on all platforms. Microsoft's assembler uses
2313 # a completely different syntax for x86 code.
2314 if windows_env.Bit('build_x86_64'):
2315 # This assembler only works for x86-64 code.
2316 windows_env['WINASM'] = \
2317 windows_env.File('$SOURCE_ROOT/third_party/mingw-w64/mingw/bin/'
2318 'x86_64-w64-mingw32-as.exe').abspath
2320 # This assembler only works for x86-32 code.
2321 windows_env['WINASM'] = \
2322 windows_env.File('$SOURCE_ROOT/third_party/gnu_binutils/files/'
2327 windows_optimized_env) = GenerateOptimizationLevels(MakeWindowsEnv())
2329 def MakeUnixLikeEnv(platform=None):
2330 unix_like_env = MakeBaseTrustedEnv(platform)
2331 # -Wdeclaration-after-statement is desirable because MS studio does
2332 # not allow declarations after statements in a block, and since much
2333 # of our code is portable and primarily initially tested on Linux,
2334 # it'd be nice to get the build error earlier rather than later
2335 # (building and testing on Linux is faster).
2336 # TODO(nfullagar): should we consider switching to -std=c99 ?
2337 unix_like_env.Prepend(
2340 '-Wdeclaration-after-statement',
2341 # Require defining functions as "foo(void)" rather than
2342 # "foo()" because, in C (but not C++), the latter defines a
2343 # function with unspecified arguments rather than no
2345 '-Wstrict-prototypes',
2356 '-fdiagnostics-show-option',
2357 '-fvisibility=hidden',
2358 '-fstack-protector',
2360 # NOTE: pthread is only neeeded for libppNaClPlugin.so and on arm
2362 CPPDEFINES = [['__STDC_LIMIT_MACROS', '1'],
2363 ['__STDC_FORMAT_MACROS', '1'],
2366 # Android's stlport uses __STRICT_ANSI__ to exclude "long long".
2367 # This breaks basically all C++ code that uses stlport.
2368 if not unix_like_env.Bit('android'):
2369 unix_like_env.Prepend(CXXFLAGS=['-std=c++98'])
2371 if not unix_like_env.Bit('clang'):
2372 unix_like_env.Append(CCFLAGS=['--param', 'ssp-buffer-size=4'])
2374 if unix_like_env.Bit('werror'):
2375 unix_like_env.Append(LINKFLAGS=['-Werror'])
2377 return unix_like_env
2380 def MakeMacEnv(platform=None):
2381 mac_env = MakeUnixLikeEnv(platform).Clone(
2382 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-mac',
2383 BUILD_TYPE_DESCRIPTION = 'MacOS ${OPTIMIZATION_LEVEL} build',
2384 tools = ['target_platform_mac'],
2385 # TODO(bradnelson): this should really be able to live in unix_like_env
2386 # but can't due to what the target_platform_x module is
2389 PLUGIN_SUFFIX = '.bundle',
2391 # On Mac, only the newer clang toolchains can parse some of the trusted
2392 # code's assembly syntax, so turn clang on by default.
2393 mac_env.SetBits('clang')
2395 # For no good reason, this all gets instantiated on every platform,
2396 # and then only actually used on Mac. But the find_sdk.py script
2397 # will barf if run on a non-Mac.
2398 if pynacl.platform.IsMac():
2399 # mac_sdk_min must be kept in synch with mac_sdk_min in
2400 # chromium/src/build/config/mac/mac_sdk.gni.
2401 mac_sdk_min = '10.10'
2402 # Find the Mac SDK to use as sysroot.
2403 # This invocation matches the model in //build/config/mac/mac_sdk.gni.
2404 mac_sdk_sysroot, mac_sdk_version = subprocess.check_output([
2406 os.path.join(os.path.pardir, 'build', 'mac', 'find_sdk.py'),
2411 mac_sdk_sysroot = 'ThisIsNotAMac'
2413 # This should be kept in synch with mac_deployment_target
2414 # in build/common.gypi, which in turn should be kept in synch
2415 # with chromium/src/build/common.gypi.
2416 mac_deployment_target = '10.6'
2418 sdk_flags = ['-isysroot', mac_sdk_sysroot,
2419 '-mmacosx-version-min=' + mac_deployment_target]
2420 mac_env.Append(CCFLAGS=sdk_flags, ASFLAGS=sdk_flags, LINKFLAGS=sdk_flags)
2422 subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
2424 # '-Wno-gnu' is required for the statement expression defining dirfd
2425 # for OSX -- otherwise, a warning is generated.
2426 CCFLAGS=[subarch_flag, '-fPIC', '-Wno-gnu'],
2427 ASFLAGS=[subarch_flag],
2428 LINKFLAGS=[subarch_flag, '-fPIC'],
2429 CPPDEFINES = [# defining _DARWIN_C_SOURCE breaks 10.4
2430 #['_DARWIN_C_SOURCE', '1'],
2431 #['__STDC_LIMIT_MACROS', '1']
2437 (mac_debug_env, mac_optimized_env) = GenerateOptimizationLevels(MakeMacEnv())
2440 def which(cmd, paths=os.environ.get('PATH', '').split(os.pathsep)):
2442 if os.access(os.path.join(p, cmd), os.X_OK):
2447 def SetUpLinuxEnvArm(env):
2448 if env.Bit('clang'):
2449 raise UserError('Clang build not supported with ARM '
2450 '(use --no-clang to disable)')
2451 jail = env.GetToolchainDir(toolchain_name='arm_trusted')
2452 if not platform.machine().startswith('arm'):
2453 # Allow emulation on non-ARM hosts.
2454 env.Replace(EMULATOR=jail + '/run_under_qemu_arm')
2455 if env.Bit('built_elsewhere'):
2456 def FakeInstall(dest, source, env):
2457 print 'Not installing', dest
2458 # Replace build commands with no-ops
2459 env.Replace(CC='true', CXX='true', LD='true',
2460 AR='true', RANLIB='true', INSTALL=FakeInstall)
2462 env.Replace(CC='arm-linux-gnueabihf-gcc',
2463 CXX='arm-linux-gnueabihf-g++',
2464 LD='arm-linux-gnueabihf-ld',
2466 # The -rpath-link argument is needed on Ubuntu/Precise to
2467 # avoid linker warnings about missing ld.linux.so.3.
2468 # TODO(sbc): remove this once we stop supporting Precise
2469 # as a build environment.
2470 LINKFLAGS=['-Wl,-rpath-link=' + jail +
2471 '/lib/arm-linux-gnueabihf']
2473 # Note we let the compiler choose whether it's -marm or -mthumb by
2474 # default. The hope is this will have the best chance of testing
2475 # the prevailing compilation mode used for Chromium et al.
2476 env.Prepend(CCFLAGS=['-march=armv7-a'])
2478 # get_plugin_dirname.cc has a dependency on dladdr
2479 env.Append(LIBS=['dl'])
2481 def SetUpAndroidEnv(env):
2482 env.FilterOut(CPPDEFINES=[['_LARGEFILE64_SOURCE', '1']])
2483 android_ndk_root = os.path.join('${SOURCE_ROOT}', 'third_party',
2485 android_ndk_experimental_root = os.path.join('${SOURCE_ROOT}',
2486 'third_party', 'android_tools',
2488 android_sdk_root = os.path.join('${SOURCE_ROOT}', 'third_party',
2489 'android_sdk', 'public')
2490 android_sdk_version = 21
2491 android_stlport_root = os.path.join(android_ndk_root, 'sources', 'cxx-stl',
2494 pynacl.platform.OS_WIN : 'win',
2495 pynacl.platform.OS_MAC: 'darwin',
2496 pynacl.platform.OS_LINUX : 'linux'
2498 host_os = ndk_host_os_map[pynacl.platform.GetOS()]
2499 android_sdk = os.path.join(android_sdk_root, 'platforms',
2500 'android-%s' % android_sdk_version)
2502 if env.Bit('build_arm'):
2503 android_ndk_target_prefix = 'arm-linux-androideabi'
2504 android_ndk_version = '4.8'
2505 android_app_abi = 'armeabi-v7a'
2506 android_ndk_sysroot = os.path.join(android_ndk_root, 'platforms',
2507 'android-14', 'arch-arm')
2508 android_ndk_lib_dir = os.path.join('usr', 'lib')
2509 android_toolchain = os.path.join(android_ndk_root, 'toolchains',
2510 'arm-linux-androideabi-4.8', 'prebuilt',
2511 '%s-x86_64' % host_os, 'bin')
2512 arch_cflags += ['-march=armv7-a', '-mfloat-abi=softfp']
2513 elif env.Bit('build_x86_32'):
2514 android_ndk_target_prefix = 'i686-linux-android'
2515 android_ndk_version = '4.8'
2516 android_app_abi = 'x86'
2517 android_ndk_sysroot = os.path.join(android_ndk_root, 'platforms',
2518 'android-14', 'arch-x86')
2519 android_ndk_lib_dir = os.path.join('usr', 'lib')
2520 android_toolchain = os.path.join(android_ndk_root, 'toolchains',
2521 'x86-4.8', 'prebuilt',
2522 '%s-x86_64' % host_os, 'bin')
2523 arch_cflags += ['-m32', '-msse2']
2524 # TODO(sehr): add other android architecture platform settings here.
2525 android_ndk_include = os.path.join(android_ndk_sysroot, 'usr', 'include')
2526 android_ndk_lib = os.path.join(android_ndk_sysroot, android_ndk_lib_dir)
2527 android_sdk_jar = os.path.join(android_sdk, 'android.jar')
2528 android_stlport_include = os.path.join(android_stlport_root, 'stlport')
2529 android_stlport_libs_dir = os.path.join(android_stlport_root, 'libs',
2531 android_ndk_libgcc_path = os.path.join(android_toolchain, '..', 'lib', 'gcc',
2532 android_ndk_target_prefix,
2533 android_ndk_version)
2534 env.Replace(CC=os.path.join(android_toolchain,
2535 '%s-gcc' % android_ndk_target_prefix),
2536 CXX=os.path.join(android_toolchain,
2537 '%s-g++' % android_ndk_target_prefix),
2538 LD=os.path.join(android_toolchain,
2539 '%s-g++' % android_ndk_target_prefix),
2540 AR=os.path.join(android_toolchain,
2541 '%s-ar' % android_ndk_target_prefix),
2542 RANLIB=os.path.join(android_toolchain,
2543 '%s-ranlib' % android_ndk_target_prefix),
2544 READELF=os.path.join(android_toolchain,
2545 '%s-readelf' % android_ndk_target_prefix),
2546 STRIP=os.path.join(android_toolchain,
2547 '%s-strip' % android_ndk_target_prefix),
2548 EMULATOR=os.path.join(android_sdk_root, 'tools', 'emulator'),
2549 LIBPATH=['${LIB_DIR}',
2551 android_ndk_libgcc_path,
2552 os.path.join(android_stlport_root, 'libs',
2555 LIBS=['stlport_shared',
2562 # SHLINKFLAGS should not inherit options from LINKFLAGS.
2563 env.FilterOut(SHLINKFLAGS=['$LINKFLAGS'])
2564 env.Append(CCFLAGS=['--sysroot=' + android_ndk_sysroot,
2565 '-isystem=' + os.path.join(android_ndk_sysroot, 'usr',
2567 '-I%s' % android_stlport_include,
2568 '-ffunction-sections',
2570 '-fstack-protector',
2572 '-finline-limit=64',
2573 '-Wa,--noexecstack',
2576 # Due to bogus warnings on uintptr_t formats.
2579 CXXFLAGS=['-I%s' % android_stlport_include,
2580 '-I%s' % android_ndk_include,
2583 LINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2585 '-Wl,--no-undefined',
2586 # Don't export symbols from statically linked libraries.
2587 '-Wl,--exclude-libs=ALL',
2588 # crtbegin_dynamic.o should be the last item in ldflags.
2589 os.path.join(android_ndk_lib, 'crtbegin_dynamic.o'),
2591 LINKCOM=' $ANDROID_EXTRA_LIBS',
2592 ANDROID_EXTRA_LIBS=os.path.join(android_ndk_lib,
2593 'crtend_android.o'),
2594 SHLINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2596 # crtbegin_so.o should be the last item in ldflags.
2597 os.path.join(android_ndk_lib, 'crtbegin_so.o'),
2599 SHLINKCOM=' $ANDROID_EXTRA_SHLIBS',
2600 ANDROID_EXTRA_SHLIBS=os.path.join(android_ndk_lib,
2605 def SetUpLinuxEnvMips(env):
2606 jail = env.GetToolchainDir(toolchain_name='mips_trusted')
2607 if not platform.machine().startswith('mips'):
2608 # Allow emulation on non-MIPS hosts.
2609 env.Replace(EMULATOR=jail + '/run_under_qemu_mips32')
2610 if env.Bit('built_elsewhere'):
2611 def FakeInstall(dest, source, env):
2612 print 'Not installing', dest
2613 # Replace build commands with no-ops
2614 env.Replace(CC='true', CXX='true', LD='true',
2615 AR='true', RANLIB='true', INSTALL=FakeInstall)
2617 tc_dir = os.path.join(jail, 'bin')
2618 if not which(os.path.join(tc_dir, 'mipsel-linux-gnu-gcc')):
2620 "MIPS trusted toolchain not found - try running:\n"
2621 " build/package_version/package_version.py --packages"
2622 " linux_x86/mips_trusted sync -x\n"
2623 "Or build it yourself with:\n"
2624 " tools/trusted_cross_toolchains/trusted-toolchain-creator"
2625 ".mipsel.debian.sh nacl_sdk")
2626 env.Replace(CC=os.path.join(tc_dir, 'mipsel-linux-gnu-gcc'),
2627 CXX=os.path.join(tc_dir, 'mipsel-linux-gnu-g++'),
2628 LD=os.path.join(tc_dir, 'mipsel-linux-gnu-ld'),
2630 LIBPATH=['${LIB_DIR}',
2631 jail + '/sysroot/usr/lib']
2634 env.Append(LIBS=['rt', 'dl', 'pthread'],
2635 CCFLAGS=['-march=mips32r2'])
2637 # Makes a generic Linux development environment.
2638 # Linux development environments are used in two different ways.
2639 # 1) To produce trusted tools (e.g., sel_ldr), called TRUSTED_ENV
2640 # 2) To produce build tools (e.g., tls_edit), called BUILD_ENV
2641 def MakeGenericLinuxEnv(platform=None):
2642 linux_env = MakeUnixLikeEnv(platform).Clone(
2643 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-linux',
2644 BUILD_TYPE_DESCRIPTION = 'Linux ${OPTIMIZATION_LEVEL} build',
2645 tools = ['target_platform_linux'],
2646 # TODO(bradnelson): this should really be able to live in unix_like_env
2647 # but can't due to what the target_platform_x module is
2652 # Prepend so we can disable warnings via Append
2654 CPPDEFINES = [['_POSIX_C_SOURCE', '199506'],
2655 ['_XOPEN_SOURCE', '600'],
2656 ['_GNU_SOURCE', '1'],
2657 ['_LARGEFILE64_SOURCE', '1'],
2662 if linux_env.Bit('build_x86_32'):
2665 LINKFLAGS = ['-m32'],
2667 elif linux_env.Bit('build_x86_64'):
2670 LINKFLAGS = ['-m64'],
2672 elif linux_env.Bit('build_arm'):
2673 SetUpLinuxEnvArm(linux_env)
2674 elif linux_env.Bit('build_mips32'):
2675 SetUpLinuxEnvMips(linux_env)
2677 Banner('Strange platform: %s' % GetTargetPlatform())
2679 # These are desireable options for every Linux platform:
2680 # _FORTIFY_SOURCE: general paranoia "hardening" option for library functions
2681 # -fPIE/-pie: create a position-independent executable
2682 # relro/now: "hardening" options for linking
2683 # noexecstack: ensure that the executable does not get a PT_GNU_STACK
2684 # header that causes the kernel to set the READ_IMPLIES_EXEC
2685 # personality flag, which disables NX page protection.
2686 linux_env.Prepend(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2687 # By default SHLINKFLAGS uses $LINKFLAGS, but we do not want -pie
2688 # in $SHLINKFLAGS, only in $LINKFLAGS. So move LINKFLAGS over to
2689 # COMMON_LINKFLAGS, and add the "hardening" options there. Then
2690 # make both LINKFLAGS and SHLINKFLAGS refer to that, and add -pie
2691 # only to LINKFLAGS.
2692 linux_env.Replace(COMMON_LINKFLAGS=linux_env['LINKFLAGS'],
2693 LINKFLAGS=['$COMMON_LINKFLAGS'])
2694 linux_env.FilterOut(SHLINKFLAGS=['$LINKFLAGS'])
2695 linux_env.Prepend(SHLINKFLAGS=['$COMMON_LINKFLAGS'])
2696 linux_env.Prepend(COMMON_LINKFLAGS=['-Wl,-z,relro',
2698 '-Wl,-z,noexecstack'])
2699 linux_env.Prepend(LINKFLAGS=['-pie'])
2700 # The ARM toolchain has a linker that doesn't handle the code its
2701 # compiler generates under -fPIE.
2702 if linux_env.Bit('build_arm') or linux_env.Bit('build_mips32'):
2703 linux_env.Prepend(CCFLAGS=['-fPIC'])
2704 # TODO(mcgrathr): Temporarily punt _FORTIFY_SOURCE for ARM because
2705 # it causes a libc dependency newer than the old bots have installed.
2706 linux_env.FilterOut(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2708 linux_env.Prepend(CCFLAGS=['-fPIE'])
2710 # We always want to use the same flags for .S as for .c because
2711 # code-generation flags affect the predefines we might test there.
2712 linux_env.Replace(ASFLAGS=['${CCFLAGS}'])
2716 # Specializes a generic Linux development environment to be a trusted
2718 def MakeTrustedLinuxEnv(platform=None):
2719 linux_env = MakeGenericLinuxEnv(platform)
2720 if linux_env.Bit('android'):
2721 SetUpAndroidEnv(linux_env)
2724 (linux_debug_env, linux_optimized_env) = \
2725 GenerateOptimizationLevels(MakeTrustedLinuxEnv())
2728 def BiasedBitcodeFlags(env):
2729 """ Return clang flags to use biased bitcode and generate native-ABI-compliant
2730 code. Does not imply pre-translation.
2732 if env.Bit('build_x86_32'):
2733 return ['--target=i686-unknown-nacl']
2734 if env.Bit('build_x86_64'):
2735 return ['--target=x86_64-unknown-nacl']
2736 if env.Bit('build_arm'):
2737 return ['--target=armv7-unknown-nacl-gnueabihf', '-mfloat-abi=hard']
2738 if env.Bit('build_mips32'):
2740 raise UserError('No known target bits set')
2742 pre_base_env.AddMethod(BiasedBitcodeFlags)
2744 # Do this before the site_scons/site_tools/naclsdk.py stuff to pass it along.
2745 pre_base_env.Append(
2746 PNACL_BCLDFLAGS = ARGUMENTS.get('pnacl_bcldflags', '').split(':'))
2749 # The nacl_env is used to build native_client modules
2750 # using a special tool chain which produces platform
2751 # independent binaries
2752 # NOTE: this loads stuff from: site_scons/site_tools/naclsdk.py
2753 nacl_env = MakeArchSpecificEnv()
2754 # See comment below about libc++ and libpthread in NONIRT_LIBS.
2755 using_nacl_libcxx = nacl_env.Bit('bitcode') or nacl_env.Bit('nacl_clang')
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}'] + (['-Werror'] if nacl_env.Bit('werror')
2807 # These are settings for in-tree, non-browser tests to use.
2808 # They use libraries that circumvent the IRT-based implementations
2809 # in the public libraries.
2810 # Note that pthread_private is part of NONIRT_LIBS for clang because
2811 # libc++ depends on libpthread. However we can't just add
2812 # libpthread_private to the link line because those libs get added before
2813 # the standard libs, so the references that come from libc++ itself will
2814 # still get satisfied from libpthread instead of libpthread_private (and
2815 # that code will crash because it requires the IRT). So put libc++ on the
2816 # user link line before libpthread_private to ensure that its references
2817 # to libpthread also get satisfied by libpthread_private.
2818 # TODO(dschuff): Also remove the hack in pnacl-ld and use this for pnacl.
2819 NONIRT_LIBS = (['nacl_sys_private'] +
2820 (['c++','pthread_private'] if using_nacl_libcxx else [])),
2821 PTHREAD_LIBS = ['pthread_private'],
2822 DYNCODE_LIBS = ['nacl_dyncode_private'],
2823 EXCEPTION_LIBS = ['nacl_exception_private'],
2824 LIST_MAPPINGS_LIBS = ['nacl_list_mappings_private'],
2825 RANDOM_LIBS = ['nacl_random_private'],
2828 def UsesAbiNote(env):
2829 """Return True if using a new-style GCC with .note.NaCl.ABI.* notes.
2830 This means there will always be an RODATA segment, even if just for the note."""
2831 return env.Bit('build_arm') and not env.Bit('bitcode')
2833 nacl_env.AddMethod(UsesAbiNote)
2835 def UnderWindowsCoverage(env):
2836 """Return True if using running on coverage under windows."""
2837 if 'TRUSTED_ENV' not in env:
2839 return env['TRUSTED_ENV'].Bit('coverage_enabled') and env.Bit('host_windows')
2841 nacl_env.AddMethod(UnderWindowsCoverage)
2843 def SetNonStableBitcodeIfAllowed(env, allow_sb_translator=False):
2844 """ This modifies the environment to allow features that aren't part
2845 of PNaCl's stable ABI. If tests using these features should be
2846 skipped entirely, this returns False. Otherwise, on success, it
2849 if env.Bit('bitcode') and env.Bit('skip_nonstable_bitcode'):
2851 # The PNaCl sandboxed translator (for the most part) only accepts stable
2852 # bitcode, so in most cases we skip building non-stable tests.
2853 # However, there are some limited cases like debug information which
2854 # we support but do not guarantee stability. Tests targeting such cases
2855 # can opt-in to testing w/ allow_sb_translator=True.
2856 if env.Bit('use_sandboxed_translator') and not allow_sb_translator:
2858 # Change environment to skip finalization step.
2859 env.SetBits('nonstable_bitcode')
2862 nacl_env.AddMethod(SetNonStableBitcodeIfAllowed)
2865 def AllowInlineAssembly(env):
2866 """ This modifies the environment to allow inline assembly in
2867 untrusted code. If the environment cannot be modified to allow
2868 inline assembly, it returns False. Otherwise, on success, it
2871 if env.Bit('bitcode'):
2872 # For each architecture, we only attempt to make our inline
2873 # assembly code work with one untrusted-code toolchain. For x86,
2874 # we target GCC, but not PNaCl/Clang, because the latter's
2875 # assembly support has various quirks that we don't want to have
2876 # to debug. For ARM, we target PNaCl/Clang, because that is the
2877 # only current ARM toolchain. One day, we will have an ARM GCC
2878 # toolchain, and we will no longer need to use inline assembly
2879 # with PNaCl/Clang at all.
2881 # For Non-SFI NaCl we use inline assembly in PNaCl/Clang.
2882 if not (env.Bit('build_arm') or env.Bit('build_mips32')
2883 or env.Bit('nonsfi_nacl')):
2885 # Inline assembly does not work in pexes.
2886 if env.Bit('pnacl_generate_pexe'):
2888 env.AddBiasForPNaCl()
2889 env.PNaClForceNative()
2891 if env.Bit('build_x86_32'):
2892 env.AppendUnique(CCFLAGS=['--target=i686-unknown-nacl'])
2893 elif env.Bit('build_x86_64'):
2894 env.AppendUnique(CCFLAGS=['--target=x86_64-unknown-nacl'])
2895 elif env.Bit('build_arm'):
2896 env.AppendUnique(CCFLAGS=['--target=armv7a-unknown-nacl-gnueabihf',
2897 '-mfloat-abi=hard'])
2898 # Enable the use of inline assembly.
2899 env.Append(CCFLAGS=['-fgnu-inline-asm'])
2902 nacl_env.AddMethod(AllowInlineAssembly)
2905 # TODO(mseaborn): Enable this unconditionally once the C code on the
2906 # Chromium side compiles successfully with this warning.
2907 if not enable_chrome:
2908 nacl_env.Append(CFLAGS=['-Wstrict-prototypes'])
2910 # This is the address at which a user executable is expected to place its
2911 # data segment in order to be compatible with the integrated runtime (IRT)
2912 # library. This address should not be changed lightly.
2913 irt_compatible_rodata_addr = 0x10000000
2914 # This is the address at which the IRT's own code will be located.
2915 # It must be below irt_compatible_rodata and leave enough space for
2916 # the code segment of the IRT. It should be as close as possible to
2917 # irt_compatible_rodata so as to leave the maximum contiguous area
2918 # available for the dynamic code loading area that falls below it.
2919 # This can be adjusted as necessary for the actual size of the IRT code.
2920 irt_code_addr = irt_compatible_rodata_addr - (6 << 20) # max 6M IRT code
2921 # This is the address at which the IRT's own data will be located. The
2922 # 32-bit sandboxes limit the address space to 1GB; the initial thread's
2923 # stack sits at the top of the address space and extends down for
2924 # NACL_DEFAULT_STACK_MAX (src/trusted/service_runtime/sel_ldr.h) below.
2925 # So this must be below there, and leave enough space for the IRT's own
2926 # data segment. It should be as high as possible so as to leave the
2927 # maximum contiguous area available for the user's data and break below.
2928 # This can be adjusted as necessary for the actual size of the IRT data
2929 # (that is RODATA, rounded up to 64k, plus writable data).
2930 # 1G (address space) - 16M (NACL_DEFAULT_STACK_MAX) - 1MB (IRT rodata+data)
2931 irt_data_addr = (1 << 30) - (16 << 20) - (1 << 20)
2934 IRT_DATA_REGION_START = '%#.8x' % irt_compatible_rodata_addr,
2935 # Load addresses of the IRT's code and data segments.
2936 IRT_BLOB_CODE_START = '%#.8x' % irt_code_addr,
2937 IRT_BLOB_DATA_START = '%#.8x' % irt_data_addr,
2940 def TestsUsePublicListMappingsLib(env):
2941 """Use the public list_mappings library for in-tree tests."""
2942 env.Replace(LIST_MAPPINGS_LIBS=['nacl_list_mappings'])
2944 def TestsUsePublicLibs(env):
2945 """Change the environment so it uses public libraries for in-tree tests."""
2946 env.Replace(NONIRT_LIBS=['pthread'] if env.Bit('bitcode') else [],
2947 PTHREAD_LIBS=['pthread'],
2948 DYNCODE_LIBS=['nacl_dyncode', 'nacl'],
2949 EXCEPTION_LIBS=['nacl_exception', 'nacl'],
2950 RANDOM_LIBS=['nacl'])
2952 # glibc is incompatible with libpthread_private and libnacl_sys_private.
2953 if nacl_env.Bit('nacl_glibc'):
2954 nacl_env.Replace(NONIRT_LIBS=[],
2955 PTHREAD_LIBS=['pthread'])
2957 # These add on to those set in pre_base_env, above.
2960 # This ensures that UINT32_MAX gets defined.
2961 ['__STDC_LIMIT_MACROS', '1'],
2962 # This ensures that PRId64 etc. get defined.
2963 ['__STDC_FORMAT_MACROS', '1'],
2964 # _GNU_SOURCE ensures that strtof() gets declared.
2966 ['_POSIX_C_SOURCE', '199506'],
2967 ['_XOPEN_SOURCE', '600'],
2969 ['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
2970 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ],
2972 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}'],
2973 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}'],
2977 def FixWindowsAssembler(env):
2978 if env.Bit('host_windows'):
2979 # ASCOM is the rule used by .s files and ASPPCOM is the rule used by .S
2980 # files; the latter uses the C preprocessor. This is needed because Windows
2981 # builds are case-insensitive, so they all appear as .s files.
2982 env.Replace(ASCOM='${ASPPCOM}')
2984 FixWindowsAssembler(nacl_env)
2986 # Look in the local include and lib directories before the toolchain's.
2987 nacl_env['INCLUDE_DIR'] = '${TARGET_ROOT}/include'
2988 # Remove the default $LIB_DIR element so that we prepend it without duplication.
2989 # Using PrependUnique alone would let it stay last, where we want it first.
2990 nacl_env.FilterOut(LIBPATH=['${LIB_DIR}'])
2991 nacl_env.PrependUnique(
2992 CPPPATH = ['${INCLUDE_DIR}'],
2993 LIBPATH = ['${LIB_DIR}'],
2996 if nacl_env.Bit('bitcode'):
2997 # passing -O when linking requests LTO, which does additional global
2998 # optimizations at link time
2999 nacl_env.Append(LINKFLAGS=['-O3'])
3000 if not nacl_env.Bit('nacl_glibc'):
3001 nacl_env.Append(LINKFLAGS=['-static'])
3003 if nacl_env.Bit('translate_fast'):
3004 nacl_env.Append(LINKFLAGS=['-Xlinker', '-translate-fast'])
3005 nacl_env.Append(TRANSLATEFLAGS=['-translate-fast'])
3006 if nacl_env.Bit('use_sz'):
3007 nacl_env.Append(TRANSLATEFLAGS=['--use-sz'])
3009 # With pnacl's clang base/ code uses the "override" keyword.
3010 nacl_env.Append(CXXFLAGS=['-Wno-c++11-extensions'])
3011 # Allow extraneous semicolons. (Until these are removed.)
3012 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3013 nacl_env.Append(CCFLAGS=['-Wno-extra-semi'])
3014 # Allow unused private fields. (Until these are removed.)
3015 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3016 nacl_env.Append(CCFLAGS=['-Wno-unused-private-field'])
3017 # native_client/src/nonsfi/linux/linux_syscall_structs.h uses designated
3018 # initializers, which causes a warning when included from c++98 code.
3019 nacl_env.Append(CXXFLAGS=['-Wno-c99-extensions'])
3021 if nacl_env.Bit('nacl_clang'):
3022 # third_party/valgrind/nacl_valgrind.h uses asm instead of __asm__
3023 # https://code.google.com/p/nativeclient/issues/detail?id=3974
3024 # TODO(dschuff): change it to __asm__ and remove this suppression.
3025 nacl_env.Append(CCFLAGS=['-Wno-language-extension-token'])
3027 # We use a special environment for building the IRT image because it must
3028 # always use the newlib toolchain, regardless of --nacl_glibc. We clone
3029 # it from nacl_env here, before too much other cruft has been added.
3030 # We do some more magic below to instantiate it the way we need it.
3031 nacl_irt_env = nacl_env.Clone(
3032 BUILD_TYPE = 'nacl_irt',
3033 BUILD_TYPE_DESCRIPTION = 'NaCl IRT build',
3034 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT',
3037 # Provide access to the IRT build environment from the default environment
3038 # which is needed when compiling custom IRT for testing purposes.
3039 nacl_env['NACL_IRT_ENV'] = nacl_irt_env
3041 # Since we don't build src/untrusted/pthread/nacl.scons in
3042 # nacl_irt_env, we must tell the IRT how to find the pthread.h header.
3043 nacl_irt_env.Append(CPPPATH='${MAIN_DIR}/src/untrusted/pthread')
3045 # Map certain flag bits to suffices on the build output. This needs to
3046 # happen pretty early, because it affects any concretized directory names.
3047 target_variant_map = [
3048 ('bitcode', 'pnacl'),
3049 ('translate_fast', 'fast'),
3050 ('use_sz', 'subzero'),
3051 ('nacl_pic', 'pic'),
3052 ('use_sandboxed_translator', 'sbtc'),
3053 ('nacl_glibc', 'glibc'),
3054 ('pnacl_generate_pexe', 'pexe'),
3055 ('nonsfi_nacl', 'nonsfi'),
3057 for variant_bit, variant_suffix in target_variant_map:
3058 if nacl_env.Bit(variant_bit):
3059 nacl_env['TARGET_VARIANT'] += '-' + variant_suffix
3061 if nacl_env.Bit('bitcode'):
3062 nacl_env['TARGET_VARIANT'] += '-clang'
3064 nacl_env.Replace(TESTRUNNER_LIBS=['testrunner'])
3066 # TODO(mseaborn): Make nacl-glibc-based static linking work with just
3067 # "-static", without specifying a linker script.
3068 # See http://code.google.com/p/nativeclient/issues/detail?id=1298
3069 def GetLinkerScriptBaseName(env):
3070 if env.Bit('build_x86_64'):
3071 return 'elf_x86_64_nacl'
3073 return 'elf_i386_nacl'
3075 if (nacl_env.Bit('nacl_glibc') and
3076 nacl_env.Bit('nacl_static_link')):
3077 nacl_env.Append(LINKFLAGS=['-static'])
3078 if nacl_env.Bit('build_x86'):
3079 # The "-lc" is necessary because libgcc_eh depends on libc but for
3080 # some reason nacl-gcc is not linking with "--start-group/--end-group".
3081 nacl_env.Append(LINKFLAGS=[
3082 '-T', 'ldscripts/%s.x.static' % GetLinkerScriptBaseName(nacl_env),
3085 if nacl_env.Bit('running_on_valgrind'):
3086 nacl_env.Append(CCFLAGS = ['-g', '-Wno-overlength-strings',
3087 '-fno-optimize-sibling-calls'],
3088 CPPDEFINES = [['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3089 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ]])
3090 # With GLibC, libvalgrind.so is preloaded at runtime.
3091 # With Newlib, it has to be linked in.
3092 if not nacl_env.Bit('nacl_glibc'):
3093 nacl_env.Append(LINKFLAGS = ['-Wl,-u,have_nacl_valgrind_interceptors'],
3094 LIBS = ['valgrind'])
3096 environment_list.append(nacl_env)
3098 if not nacl_env.Bit('nacl_glibc'):
3099 # These are all specific to nacl-newlib so we do not include them
3100 # when building against nacl-glibc. The functionality of
3101 # pthread/startup/stubs/nosys is provided by glibc. The valgrind
3102 # code currently assumes nc_threads.
3104 BUILD_SCONSCRIPTS = [
3105 #### ALPHABETICALLY SORTED ####
3106 'src/untrusted/elf_loader/nacl.scons',
3107 'src/untrusted/pthread/nacl.scons',
3108 'src/untrusted/stubs/nacl.scons',
3109 'src/untrusted/nosys/nacl.scons',
3110 #### ALPHABETICALLY SORTED ####
3113 BUILD_SCONSCRIPTS = [
3114 #### ALPHABETICALLY SORTED ####
3115 'src/nonsfi/irt/build.scons',
3116 'src/nonsfi/linux/nacl.scons',
3117 'src/nonsfi/loader/build.scons',
3118 'src/shared/gio/nacl.scons',
3119 'src/shared/imc/nacl.scons',
3120 'src/shared/platform/nacl.scons',
3121 'src/trusted/service_runtime/nacl.scons',
3122 'src/trusted/validator/nacl.scons',
3123 'src/untrusted/irt/nacl_headers.scons',
3124 'src/untrusted/minidump_generator/nacl.scons',
3125 'src/untrusted/nacl/nacl.scons',
3126 'src/untrusted/pll_loader/nacl.scons',
3127 'src/untrusted/pnacl_dynloader/nacl.scons',
3128 'src/untrusted/valgrind/nacl.scons',
3129 #### ALPHABETICALLY SORTED ####
3131 nacl_env.AddChromeFilesFromGroup('untrusted_scons_files')
3133 # These are tests that are worthwhile to run in IRT variant only.
3135 #### ALPHABETICALLY SORTED ####
3136 'tests/elf_loader/nacl.scons',
3137 'tests/irt/nacl.scons',
3138 'tests/irt_compatibility/nacl.scons',
3139 'tests/irt_entry_alignment/nacl.scons',
3140 'tests/irt_ext/nacl.scons',
3141 'tests/irt_stack_alignment/nacl.scons',
3142 'tests/sbrk/nacl.scons',
3143 'tests/translator_size_limits/nacl.scons',
3146 # These are tests that are worthwhile to run in both IRT and non-IRT variants.
3147 # The nacl_irt_test mode runs them in the IRT variants.
3148 irt_variant_tests = [
3149 #### ALPHABETICALLY SORTED ####
3150 'tests/app_lib/nacl.scons',
3151 'tests/benchmark/nacl.scons',
3152 'tests/bigalloc/nacl.scons',
3153 'tests/callingconv/nacl.scons',
3154 'tests/callingconv_ppapi/nacl.scons',
3155 'tests/callingconv_case_by_case/nacl.scons',
3156 'tests/clock/nacl.scons',
3157 'tests/common/nacl.scons',
3158 'tests/compiler_thread_suspension/nacl.scons',
3159 'tests/computed_gotos/nacl.scons',
3160 'tests/data_below_data_start/nacl.scons',
3161 'tests/data_not_executable/nacl.scons',
3162 'tests/debug_stub/nacl.scons',
3163 'tests/dup/nacl.scons',
3164 'tests/dynamic_code_loading/nacl.scons',
3165 'tests/dynamic_linking/nacl.scons',
3166 'tests/egyptian_cotton/nacl.scons',
3167 'tests/environment_variables/nacl.scons',
3168 'tests/exception_test/nacl.scons',
3169 'tests/fdopen_test/nacl.scons',
3170 'tests/file/nacl.scons',
3171 'tests/futexes/nacl.scons',
3172 'tests/gc_instrumentation/nacl.scons',
3173 'tests/gdb/nacl.scons',
3174 'tests/glibc_file64_test/nacl.scons',
3175 'tests/glibc_static_test/nacl.scons',
3176 'tests/glibc_syscall_wrappers/nacl.scons',
3177 'tests/glibc_socket_wrappers/nacl.scons',
3178 'tests/hello_world/nacl.scons',
3179 'tests/imc_shm_mmap/nacl.scons',
3180 'tests/includability/nacl.scons',
3181 'tests/infoleak/nacl.scons',
3182 'tests/libc/nacl.scons',
3183 'tests/libc_free_hello_world/nacl.scons',
3184 'tests/limited_file_access/nacl.scons',
3185 'tests/list_mappings/nacl.scons',
3186 'tests/longjmp/nacl.scons',
3187 'tests/loop/nacl.scons',
3188 'tests/math/nacl.scons',
3189 'tests/memcheck_test/nacl.scons',
3190 'tests/mmap/nacl.scons',
3191 'tests/mmap_main_nexe/nacl.scons',
3192 'tests/mmap_prot_exec/nacl.scons',
3193 'tests/mmap_race_protect/nacl.scons',
3194 'tests/nacl_log/nacl.scons',
3195 'tests/nanosleep/nacl.scons',
3196 'tests/nonsfi/nacl.scons',
3197 'tests/noop/nacl.scons',
3198 'tests/nrd_xfer/nacl.scons',
3199 'tests/nthread_nice/nacl.scons',
3200 'tests/null/nacl.scons',
3201 'tests/nullptr/nacl.scons',
3202 'tests/pagesize/nacl.scons',
3203 'tests/performance/nacl.scons',
3204 'tests/pnacl_abi/nacl.scons',
3205 'tests/pnacl_dynamic_loading/nacl.scons',
3206 'tests/pnacl_native_objects/nacl.scons',
3207 'tests/random/nacl.scons',
3208 'tests/redir/nacl.scons',
3209 'tests/rodata_not_writable/nacl.scons',
3210 'tests/run_py/nacl.scons',
3211 'tests/sel_ldr/nacl.scons',
3212 'tests/sel_ldr_seccomp/nacl.scons',
3213 'tests/sel_main_chrome/nacl.scons',
3214 'tests/signal_handler/nacl.scons',
3215 'tests/simd/nacl.scons',
3216 'tests/sleep/nacl.scons',
3217 'tests/stack_alignment/nacl.scons',
3218 'tests/stubout_mode/nacl.scons',
3219 'tests/sysbasic/nacl.scons',
3220 'tests/syscall_return_regs/nacl.scons',
3221 'tests/syscall_return_sandboxing/nacl.scons',
3222 'tests/syscalls/nacl.scons',
3223 'tests/thread_capture/nacl.scons',
3224 'tests/threads/nacl.scons',
3225 'tests/time/nacl.scons',
3226 'tests/tls/nacl.scons',
3227 'tests/tls_segment_x86_32/nacl.scons',
3228 'tests/toolchain/nacl.scons',
3229 'tests/toolchain/arm/nacl.scons',
3230 'tests/toolchain/mips/nacl.scons',
3231 'tests/unittests/shared/platform/nacl.scons',
3232 'tests/untrusted_check/nacl.scons',
3233 'tests/unwind_restores_regs/nacl.scons',
3234 'tests/validator/nacl.scons',
3235 #### ALPHABETICALLY SORTED ####
3236 # NOTE: The following tests are really IRT-only tests, but they
3237 # are in this category so that they can generate libraries (which
3238 # works in nacl_env but not in nacl_irt_test_env) while also
3239 # adding tests to nacl_irt_test_env.
3240 'tests/inbrowser_test_runner/nacl.scons',
3241 'tests/untrusted_minidump/nacl.scons',
3244 # These are tests that are NOT worthwhile to run in an IRT variant.
3245 # In some cases, that's because they are browser tests which always
3246 # use the IRT. In others, it's because they are special-case tests
3247 # that are incompatible with having an IRT loaded.
3248 nonvariant_tests = [
3249 #### ALPHABETICALLY SORTED ####
3250 'tests/barebones/nacl.scons',
3251 'tests/chrome_extension/nacl.scons',
3252 'tests/custom_desc/nacl.scons',
3253 'tests/faulted_thread_queue/nacl.scons',
3254 'tests/gold_plugin/nacl.scons',
3255 'tests/imc_sockets/nacl.scons',
3256 'tests/minnacl/nacl.scons',
3257 'tests/multiple_sandboxes/nacl.scons',
3258 # Potential issue with running them:
3259 # http://code.google.com/p/nativeclient/issues/detail?id=2092
3260 # See also the comment in "buildbot/buildbot_standard.py"
3261 'tests/pnacl_shared_lib_test/nacl.scons',
3262 'tests/pwrite/nacl.scons',
3263 'tests/signal_handler_single_step/nacl.scons',
3264 'tests/thread_suspension/nacl.scons',
3265 'tests/trusted_crash/crash_in_syscall/nacl.scons',
3266 'tests/trusted_crash/osx_crash_filter/nacl.scons',
3267 'tests/trusted_crash/osx_crash_forwarding/nacl.scons',
3268 'tests/unittests/shared/imc/nacl.scons',
3269 #### ALPHABETICALLY SORTED ####
3272 nacl_env.Append(BUILD_SCONSCRIPTS=nonvariant_tests)
3273 nacl_env.AddChromeFilesFromGroup('nonvariant_test_scons_files')
3274 nacl_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3275 nacl_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3277 # Defines TESTS_TO_RUN_INBROWSER.
3278 SConscript('tests/inbrowser_test_runner/selection.scons',
3279 exports=['nacl_env'])
3281 # Possibly install a toolchain by downloading it
3282 # TODO: explore using a less heavy weight mechanism
3283 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3286 SCons.Script.AddOption('--download',
3290 action='store_true',
3291 help='deprecated - allow tools to download')
3293 if nacl_env.GetOption('download'):
3294 print '@@@@ --download is deprecated, use gclient runhooks --force'
3295 nacl_sync_env = nacl_env.Clone()
3296 nacl_sync_env['ENV'] = os.environ
3297 nacl_sync_env.Execute('gclient runhooks --force')
3300 def NaClSharedLibrary(env, lib_name, *args, **kwargs):
3301 env_shared = env.Clone(COMPONENT_STATIC=False)
3302 soname = SCons.Util.adjustixes(lib_name, 'lib', '.so')
3303 env_shared.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s' % (soname)])
3304 return env_shared.ComponentLibrary(lib_name, *args, **kwargs)
3306 nacl_env.AddMethod(NaClSharedLibrary)
3308 def NaClSdkLibrary(env, lib_name, *args, **kwargs):
3309 n = [env.ComponentLibrary(lib_name, *args, **kwargs)]
3310 if not env.Bit('nacl_disable_shared'):
3311 n.append(env.NaClSharedLibrary(lib_name, *args, **kwargs))
3314 nacl_env.AddMethod(NaClSdkLibrary)
3317 # Special environment for untrusted test binaries that use raw syscalls
3318 def RawSyscallObjects(env, sources):
3319 raw_syscall_env = env.Clone()
3320 raw_syscall_env.Append(
3322 ['USE_RAW_SYSCALLS', '1'],
3326 for source_file in sources:
3327 target_name = 'raw_' + os.path.basename(source_file).rstrip('.c')
3328 object = raw_syscall_env.ComponentObject(target_name,
3330 objects.append(object)
3333 nacl_env.AddMethod(RawSyscallObjects)
3336 # The IRT-building environment was cloned from nacl_env, but it should
3337 # ignore the --nacl_glibc, nacl_pic=1 and bitcode=1 switches.
3338 # We have to reinstantiate the naclsdk.py magic after clearing those flags,
3339 # so it regenerates the tool paths right.
3340 # TODO(mcgrathr,bradnelson): could get cleaner if naclsdk.py got folded back in.
3341 nacl_irt_env.ClearBits('nacl_glibc')
3342 nacl_irt_env.ClearBits('nacl_pic')
3343 nacl_irt_env.ClearBits('pnacl_generate_pexe')
3344 nacl_irt_env.ClearBits('use_sandboxed_translator')
3345 nacl_irt_env.ClearBits('bitcode')
3346 # The choice of toolchain used to build the IRT does not depend on the toolchain
3347 # used to build user/test code. nacl-clang is used everywhere for the IRT.
3348 nacl_irt_env.SetBits('nacl_clang')
3350 nacl_irt_env.Tool('naclsdk')
3351 # These are unfortunately clobbered by running Tool, which
3352 # we needed to do to get the destination directory reset.
3353 # We want all the same values from nacl_env.
3354 nacl_irt_env.Replace(EXTRA_CFLAGS=nacl_env['EXTRA_CFLAGS'],
3355 EXTRA_CXXFLAGS=nacl_env['EXTRA_CXXFLAGS'],
3356 CCFLAGS=nacl_env['CCFLAGS'],
3357 CFLAGS=nacl_env['CFLAGS'],
3358 CXXFLAGS=nacl_env['CXXFLAGS'])
3359 FixWindowsAssembler(nacl_irt_env)
3360 # Make it find the libraries it builds, rather than the SDK ones.
3361 nacl_irt_env.Replace(LIBPATH='${LIB_DIR}')
3363 # The IRT must be built using LLVM's assembler on x86-64 to preserve sandbox
3364 # base address hiding. It's also used on x86-32 for consistency.
3365 if nacl_irt_env.Bit('build_x86_64') or nacl_irt_env.Bit('build_x86_32'):
3366 nacl_irt_env.Append(CCFLAGS=['-integrated-as'])
3367 if nacl_irt_env.Bit('build_x86_32'):
3368 # The x86-32 IRT needs to be callable with an under-aligned stack.
3369 # See https://code.google.com/p/nativeclient/issues/detail?id=3935
3370 nacl_irt_env.Append(CCFLAGS=['-mstackrealign', '-mno-sse'])
3372 # The IRT is C only, don't link with the C++ linker so that it doesn't
3373 # start depending on the C++ standard library and (in the case of
3375 nacl_irt_env.Replace(LINK=(nacl_irt_env['LINK'].
3376 replace('nacl-clang++', 'nacl-clang')))
3378 # TODO(mcgrathr): Clean up uses of these methods.
3379 def AddLibraryDummy(env, nodes):
3381 nacl_irt_env.AddMethod(AddLibraryDummy, 'AddLibraryToSdk')
3383 def AddObjectInternal(env, nodes):
3384 return env.Replicate('${LIB_DIR}', nodes)
3385 nacl_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3386 nacl_irt_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3388 def IrtNaClSdkLibrary(env, lib_name, *args, **kwargs):
3389 env.ComponentLibrary(lib_name, *args, **kwargs)
3390 nacl_irt_env.AddMethod(IrtNaClSdkLibrary, 'NaClSdkLibrary')
3392 nacl_irt_env.AddMethod(SDKInstallBin)
3394 # Populate the internal include directory when AddHeaderToSdk
3395 # is used inside nacl_env.
3396 def AddHeaderInternal(env, nodes, subdir='nacl'):
3397 dir = '${INCLUDE_DIR}'
3398 if subdir is not None:
3400 n = env.Replicate(dir, nodes)
3403 nacl_irt_env.AddMethod(AddHeaderInternal, 'AddHeaderToSdk')
3405 def PublishHeader(env, nodes, subdir):
3406 if ('install' in COMMAND_LINE_TARGETS or
3407 'install_headers' in COMMAND_LINE_TARGETS):
3408 dir = env.GetAbsDirArg('includedir', 'install_headers')
3409 if subdir is not None:
3411 n = env.Install(dir, nodes)
3412 env.Alias('install', env.Alias('install_headers', n))
3415 def PublishLibrary(env, nodes):
3416 env.Alias('build_lib', nodes)
3418 if ('install' in COMMAND_LINE_TARGETS or
3419 'install_lib' in COMMAND_LINE_TARGETS):
3420 dir = env.GetAbsDirArg('libdir', 'install_lib')
3421 n = env.Install(dir, nodes)
3422 env.Alias('install', env.Alias('install_lib', n))
3425 def NaClAddHeader(env, nodes, subdir='nacl'):
3426 n = AddHeaderInternal(env, nodes, subdir)
3427 PublishHeader(env, n, subdir)
3429 nacl_env.AddMethod(NaClAddHeader, 'AddHeaderToSdk')
3431 def NaClAddLibrary(env, nodes):
3432 nodes = env.Replicate('${LIB_DIR}', nodes)
3433 PublishLibrary(env, nodes)
3435 nacl_env.AddMethod(NaClAddLibrary, 'AddLibraryToSdk')
3437 def NaClAddObject(env, nodes):
3438 lib_nodes = env.Replicate('${LIB_DIR}', nodes)
3439 PublishLibrary(env, lib_nodes)
3441 nacl_env.AddMethod(NaClAddObject, 'AddObjectToSdk')
3443 # We want to do this for nacl_env when not under --nacl_glibc,
3444 # but for nacl_irt_env whether or not under --nacl_glibc, so
3445 # we do it separately for each after making nacl_irt_env and
3446 # clearing its Bit('nacl_glibc').
3447 def AddImplicitLibs(env):
3450 # Require the pnacl_irt_shim for pnacl x86-64 and arm.
3451 # Use -B to have the compiler look for the fresh libpnacl_irt_shim.a.
3452 if ( env.Bit('bitcode') and
3453 (env.Bit('build_x86_64') or env.Bit('build_arm'))
3454 and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT'):
3455 # Note: without this hack ibpnacl_irt_shim.a will be deleted
3456 # when "built_elsewhere=1"
3457 # Since we force the build in a previous step the dependency
3458 # is not really needed.
3459 # Note: the "precious" mechanism did not work in this case
3460 if not env.Bit('built_elsewhere'):
3461 if env.Bit('enable_chrome_side'):
3462 implicit_libs += ['libpnacl_irt_shim.a']
3464 if not env.Bit('nacl_glibc'):
3465 # These are automatically linked in by the compiler, either directly
3466 # or via the linker script that is -lc. In the non-glibc build, we
3467 # are the ones providing these files, so we need dependencies.
3468 # The ComponentProgram method (site_scons/site_tools/component_builders.py)
3469 # adds dependencies on env['IMPLICIT_LIBS'] if that's set.
3470 if env.Bit('bitcode'):
3471 implicit_libs += ['libnacl.a']
3473 implicit_libs += ['crt1.o',
3477 # TODO(mcgrathr): multilib nonsense defeats -B! figure out a better way.
3478 if GetTargetPlatform() == 'x86-32':
3479 implicit_libs.append(os.path.join('32', 'crt1.o'))
3480 # libc++ depends on libpthread, and because PPAPI applications always need
3481 # threads anyway, nacl-clang just includes -lpthread unconditionally.
3482 if using_nacl_libcxx and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT':
3483 implicit_libs += ['libpthread.a']
3485 if implicit_libs != []:
3486 env['IMPLICIT_LIBS'] = [env.File(os.path.join('${LIB_DIR}', file))
3487 for file in implicit_libs]
3488 # The -B<dir>/ flag is necessary to tell gcc to look for crt[1in].o there.
3489 env.Prepend(LINKFLAGS=['-B${LIB_DIR}/'])
3491 AddImplicitLibs(nacl_env)
3492 AddImplicitLibs(nacl_irt_env)
3494 nacl_irt_env.Append(
3495 BUILD_SCONSCRIPTS = [
3496 'src/shared/gio/nacl.scons',
3497 'src/shared/platform/nacl.scons',
3498 'src/tools/tls_edit/build.scons',
3499 'src/untrusted/elf_loader/nacl.scons',
3500 'src/untrusted/irt/nacl.scons',
3501 'src/untrusted/nacl/nacl.scons',
3502 'src/untrusted/stubs/nacl.scons',
3503 'tests/irt_private_pthread/nacl.scons',
3505 nacl_irt_env.AddChromeFilesFromGroup('untrusted_irt_scons_files')
3507 environment_list.append(nacl_irt_env)
3509 # Since browser_tests already use the IRT normally, those are fully covered
3510 # in nacl_env. But the non_browser_tests don't use the IRT in nacl_env.
3511 # We want additional variants of those tests with the IRT, so we make
3512 # another environment and repeat them with that adjustment.
3513 nacl_irt_test_env = nacl_env.Clone(
3514 BUILD_TYPE = 'nacl_irt_test',
3515 BUILD_TYPE_DESCRIPTION = 'NaCl tests build with IRT',
3516 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT_TESTS',
3517 NACL_ENV = nacl_env,
3519 INCLUDE_DIR = nacl_env.Dir('${INCLUDE_DIR}'),
3520 LIB_DIR = nacl_env.Dir('${LIB_DIR}'),
3521 BUILD_SCONSCRIPTS = [],
3523 nacl_irt_test_env.SetBits('tests_use_irt')
3524 if nacl_irt_test_env.Bit('enable_chrome_side'):
3525 nacl_irt_test_env.Replace(TESTRUNNER_LIBS=['testrunner_browser'])
3527 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3528 nacl_irt_test_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3529 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_only_tests)
3530 TestsUsePublicLibs(nacl_irt_test_env)
3531 TestsUsePublicListMappingsLib(nacl_irt_test_env)
3533 # We add the following settings after creating nacl_irt_test_env because we
3534 # don't want them to be inherited by nacl_irt_test_env.
3535 if nacl_env.Bit('nonsfi_nacl'):
3536 if nacl_env.Bit('pnacl_generate_pexe'):
3537 # Not-IRT-using non-SFI code uses Linux syscalls directly. Since this
3538 # involves using inline assembly, this requires turning off the PNaCl ABI
3540 nacl_env.SetBits('nonstable_bitcode')
3541 nacl_env.Append(LINKFLAGS=['--pnacl-disable-abi-check'])
3542 # Tell the PNaCl translator to link a Linux executable.
3543 nacl_env.Append(TRANSLATEFLAGS=['--noirt'])
3545 nacl_env.Append(LINKFLAGS=['--pnacl-allow-native', '-Wt,--noirt'])
3547 # If a tests/.../nacl.scons file builds a library, we will just use
3548 # the one already built in nacl_env instead.
3549 def IrtTestDummyLibrary(*args, **kwargs):
3551 nacl_irt_test_env.AddMethod(IrtTestDummyLibrary, 'ComponentLibrary')
3553 def IrtTestAddNodeToTestSuite(env, node, suite_name, node_name=None,
3554 is_broken=False, is_flaky=False,
3555 disable_irt_suffix=False):
3556 # The disable_irt_suffix argument is there for allowing tests
3557 # defined in nacl_irt_test_env to be part of chrome_browser_tests
3558 # (rather than part of chrome_browser_tests_irt).
3559 # TODO(mseaborn): But really, all of chrome_browser_tests should be
3560 # placed in nacl_irt_test_env rather than in nacl_env.
3561 suite_name = AddImplicitTestSuites(suite_name, node_name)
3562 if not disable_irt_suffix:
3563 if node_name is not None:
3565 suite_name = [name + '_irt' for name in suite_name]
3566 # NOTE: This needs to be called directly to as we're overriding the
3568 return AddNodeToTestSuite(env, node, suite_name, node_name,
3569 is_broken, is_flaky)
3570 nacl_irt_test_env.AddMethod(IrtTestAddNodeToTestSuite, 'AddNodeToTestSuite')
3572 environment_list.append(nacl_irt_test_env)
3575 windows_coverage_env = windows_debug_env.Clone(
3576 tools = ['code_coverage'],
3577 BUILD_TYPE = 'coverage-win',
3578 BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
3579 # TODO(bradnelson): switch nacl to common testing process so this won't be
3581 MANIFEST_FILE = None,
3582 COVERAGE_ANALYZER_DIR=r'..\third_party\coverage_analyzer\bin',
3583 COVERAGE_ANALYZER='$COVERAGE_ANALYZER_DIR\coverage_analyzer.exe',
3585 # TODO(bradnelson): Switch nacl to common testing process so this won't be
3586 # needed. Ignoring instrumentation failure as that's easier
3587 # than trying to gate out the ones with asm we can't handle.
3588 windows_coverage_env['LINKCOM'] = windows_coverage_env.Action([
3589 windows_coverage_env.get('LINKCOM', []),
3590 '-$COVERAGE_VSINSTR /COVERAGE ${TARGET}'])
3591 windows_coverage_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
3592 AddDualLibrary(windows_coverage_env)
3593 environment_list.append(windows_coverage_env)
3595 mac_coverage_env = mac_debug_env.Clone(
3596 tools = ['code_coverage'],
3597 BUILD_TYPE = 'coverage-mac',
3598 BUILD_TYPE_DESCRIPTION = 'MacOS code coverage build',
3599 # Strict doesnt't currently work for coverage because the path to gcov is
3600 # magically baked into the compiler.
3601 LIBS_STRICT = False,
3603 AddDualLibrary(mac_coverage_env)
3604 environment_list.append(mac_coverage_env)
3606 linux_coverage_env = linux_debug_env.Clone(
3607 tools = ['code_coverage'],
3608 BUILD_TYPE = 'coverage-linux',
3609 BUILD_TYPE_DESCRIPTION = 'Linux code coverage build',
3610 # Strict doesnt't currently work for coverage because the path to gcov is
3611 # magically baked into the compiler.
3612 LIBS_STRICT = False,
3615 linux_coverage_env.FilterOut(CCFLAGS=['-fPIE'])
3616 linux_coverage_env.Append(CCFLAGS=['-fPIC'])
3618 linux_coverage_env['OPTIONAL_COVERAGE_LIBS'] = '$COVERAGE_LIBS'
3619 AddDualLibrary(linux_coverage_env)
3620 environment_list.append(linux_coverage_env)
3623 # Environment Massaging
3624 RELEVANT_CONFIG = ['NACL_BUILD_FAMILY',
3628 'BUILD_TYPE_DESCRIPTION',
3631 MAYBE_RELEVANT_CONFIG = ['BUILD_OS',
3632 'BUILD_ARCHITECTURE',
3635 'TARGET_ARCHITECTURE',
3639 def DumpCompilerVersion(cc, env):
3641 env.Execute(env.Action('set'))
3642 env.Execute(env.Action('${CC} -v -c'))
3643 env.Execute(env.Action('${CC} -print-search-dirs'))
3644 env.Execute(env.Action('${CC} -print-libgcc-file-name'))
3645 elif cc.startswith('cl'):
3648 p = subprocess.Popen(env.subst('${CC} /V'),
3650 stdout=subprocess.PIPE,
3651 stderr=subprocess.PIPE)
3652 stdout, stderr = p.communicate()
3653 print stderr[0:stderr.find("\r")]
3654 except WindowsError:
3655 # If vcvars was not run before running SCons, we won't be able to find
3656 # the compiler at this point. SCons has built in functions for finding
3657 # the compiler, but they haven't run yet.
3658 print 'Can not find the compiler, assuming SCons will find it later.'
3660 print "UNKNOWN COMPILER"
3663 def SanityCheckEnvironments(all_envs):
3664 # simple completeness check
3665 for env in all_envs:
3666 for tag in RELEVANT_CONFIG:
3667 assert tag in env, repr(tag)
3668 assert env[tag], repr(env[tag])
3671 def LinkTrustedEnv(selected_envs):
3672 # Collect build families and ensure that we have only one env per family.
3674 for env in selected_envs:
3675 family = env['NACL_BUILD_FAMILY']
3676 if family not in family_map:
3677 family_map[family] = env
3679 msg = 'You are using incompatible environments simultaneously\n'
3680 msg += '%s vs %s\n' % (env['BUILD_TYPE'],
3681 family_map[family]['BUILD_TYPE'])
3682 msg += ('Please specfy the exact environments you require, e.g. '
3683 'MODE=dbg-host,nacl')
3684 raise Exception(msg)
3686 # Set TRUSTED_ENV so that tests of untrusted code can locate sel_ldr
3687 # etc. We set this on trusted envs too because some tests on
3688 # trusted envs run sel_ldr (e.g. using checked-in binaries).
3689 if 'TRUSTED' in family_map:
3690 for env in selected_envs:
3691 env['TRUSTED_ENV'] = family_map['TRUSTED']
3692 # Propagate some environment variables from the trusted environment,
3693 # in case some (e.g. Mac's DYLD_LIBRARY_PATH) are necessary for
3694 # running sel_ldr et al in untrusted environments' tests.
3695 for var in env['TRUSTED_ENV'].get('PROPAGATE_ENV', []):
3696 env['ENV'][var] = env['TRUSTED_ENV']['ENV'][var]
3697 if 'TRUSTED' not in family_map or 'UNTRUSTED' not in family_map:
3698 Banner('Warning: "--mode" did not specify both trusted and untrusted '
3699 'build environments. As a result, many tests will not be run.')
3702 build_platform = GetBuildPlatform()
3704 # Build Platform Base Function
3705 platform_func_map = {
3706 'win32' : MakeWindowsEnv,
3707 'cygwin': MakeWindowsEnv,
3708 'linux' : MakeGenericLinuxEnv,
3709 'linux2': MakeGenericLinuxEnv,
3710 'darwin': MakeMacEnv,
3712 if sys.platform not in platform_func_map:
3713 raise UserError('Unrecognized host platform: %s', sys.platform)
3714 make_env_func = platform_func_map[sys.platform]
3716 build_env = make_env_func(build_platform)
3717 build_env['IS_BUILD_ENV'] = True
3719 # Building tls_edit depends on gio, platform, and validator_ragel.
3720 build_env['BUILD_SCONSCRIPTS'] = [
3721 # KEEP THIS SORTED PLEASE
3722 'src/shared/gio/build.scons',
3723 'src/shared/platform/build.scons',
3724 'src/trusted/validator_ragel/build.scons',
3727 # The build environment is only used for intermediate steps and should
3728 # not be creating any targets. Aliases are used as means to add targets
3729 # to builds (IE, all_programs, all_libraries...etc.). Since we want to
3730 # share all of our build scripts but not define any aliases, we should
3731 # override the alias function and essentially stub it out.
3732 build_env.Alias = lambda env, target, source=[], actions=None, **kw : []
3736 def LinkBuildEnv(selected_envs):
3738 'opt': opt_build_env,
3739 'dbg': dbg_build_env,
3742 # We need to find the optimization level in order to know which
3743 # build environment we want to use
3745 for env in selected_envs:
3746 if env.get('OPTIMIZATION_LEVEL', None):
3747 opt_level = env['OPTIMIZATION_LEVEL']
3750 build_env = build_env_map.get(opt_level, opt_build_env)
3751 for env in selected_envs:
3752 env['BUILD_ENV'] = build_env
3754 # If the build environment is different from all the selected environments,
3755 # we will need to also append it to the selected environments so the targets
3757 build_env_root = build_env.subst('${TARGET_ROOT}')
3758 for env in selected_envs:
3759 if build_env_root == env.subst('${TARGET_ROOT}'):
3762 # Did not find a matching environment, append the build environment now.
3763 selected_envs.append(build_env)
3765 def DumpEnvironmentInfo(selected_envs):
3766 if VerboseConfigInfo(pre_base_env):
3767 Banner("The following environments have been configured")
3768 for env in selected_envs:
3769 for tag in RELEVANT_CONFIG:
3770 assert tag in env, repr(tag)
3771 print "%s: %s" % (tag, env.subst(env.get(tag)))
3772 for tag in MAYBE_RELEVANT_CONFIG:
3773 print "%s: %s" % (tag, env.subst(env.get(tag)))
3774 cc = env.subst('${CC}')
3776 asppcom = env.subst('${ASPPCOM}')
3777 print 'ASPPCOM:', asppcom
3778 DumpCompilerVersion(cc, env)
3780 rev_file = 'toolchain/linux_x86/pnacl_newlib_raw/REV'
3781 if os.path.exists(rev_file):
3782 for line in open(rev_file).read().split('\n'):
3783 if "Revision:" in line:
3784 print "PNACL : %s" % line
3786 def PnaclSetEmulatorForSandboxedTranslator(selected_envs):
3787 # Slip in emulator flags if necessary, for the sandboxed pnacl translator
3788 # on ARM, once emulator is actually known (vs in naclsdk.py, where it
3789 # is not yet known).
3790 for env in selected_envs:
3791 if (env['NACL_BUILD_FAMILY'] != 'TRUSTED'
3792 and env.Bit('bitcode')
3793 and env.Bit('use_sandboxed_translator')
3794 and env.UsingEmulator()):
3795 # This must modify the LINK command itself, since LINKFLAGS may
3796 # be filtered (e.g., in barebones tests).
3797 env.Append(LINK=' --pnacl-use-emulator')
3798 env.Append(TRANSLATE=' --pnacl-use-emulator')
3801 # Blank out defaults.
3804 # Apply optional supplement if present in the directory tree.
3805 if os.path.exists(pre_base_env.subst('$MAIN_DIR/supplement/supplement.scons')):
3806 SConscript('supplement/supplement.scons', exports=['environment_list'])
3808 # print sytem info (optionally)
3809 if VerboseConfigInfo(pre_base_env):
3810 Banner('SCONS ARGS:' + str(sys.argv))
3811 os.system(pre_base_env.subst('${PYTHON} tools/sysinfo.py'))
3815 SanityCheckEnvironments(environment_list)
3816 selected_envs = FilterEnvironments(environment_list)
3818 # If we are building NaCl, build nacl_irt too. This works around it being
3819 # a separate mode due to the vagaries of scons when we'd really rather it
3820 # not be, while not requiring that every bot command line using --mode be
3821 # changed to list '...,nacl,nacl_irt' explicitly.
3822 if nacl_env in selected_envs:
3823 selected_envs.append(nacl_irt_env)
3825 # The nacl_irt_test_env requires nacl_env to build things correctly.
3826 if nacl_irt_test_env in selected_envs and nacl_env not in selected_envs:
3827 selected_envs.append(nacl_env)
3829 DumpEnvironmentInfo(selected_envs)
3830 LinkTrustedEnv(selected_envs)
3832 # When building NaCl, any intermediate build tool that is used during the
3833 # build process must be built using the current build environment, not the
3834 # target. Create a build environment for this purpose and link it into
3835 # the selected environments
3836 dbg_build_env, opt_build_env = GenerateOptimizationLevels(MakeBuildEnv())
3837 LinkBuildEnv(selected_envs)
3839 # This must happen after LinkTrustedEnv, since that is where TRUSTED_ENV
3840 # is finally set, and env.UsingEmulator() checks TRUSTED_ENV for the emulator.
3841 # This must also happen before BuildEnvironments.
3842 PnaclSetEmulatorForSandboxedTranslator(selected_envs)
3844 BuildEnvironments(selected_envs)
3846 # Change default to build everything, but not run tests.
3847 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
3850 # Sanity check whether we are ready to build nacl modules
3851 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3852 if nacl_env.Bit('naclsdk_validate') and (nacl_env in selected_envs or
3853 nacl_irt_env in selected_envs):
3854 nacl_env.ValidateSdk()
3856 if BROKEN_TEST_COUNT > 0:
3857 msg = "There are %d broken tests." % BROKEN_TEST_COUNT
3858 if GetOption('brief_comstr'):
3859 msg += " Add --verbose to the command line for more information."
3862 # separate warnings from actual build output
3863 Banner('B U I L D - O U T P U T:')