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.
6 from __future__ import print_function
16 sys.path.append("./common")
17 sys.path.append('../third_party')
19 from SCons.Errors import UserError
20 from SCons.Script import GetBuildFailures
25 SCons.Warnings.warningAsException()
27 sys.path.append("tools")
31 import pynacl.platform
33 # turning garbage collection off reduces startup time by 10%
40 def PrintFinalReport():
41 """This function is run just before scons exits and dumps various reports.
43 # Note, these global declarations are not strictly necessary
48 if pre_base_env.Bit('target_stats'):
51 print('COMMAND EXECUTION REPORT')
53 for k in sorted(CMD_COUNTER.keys()):
54 print("%4d %s" % (CMD_COUNTER[k], k))
58 print('ENVIRONMENT USAGE REPORT')
60 for k in sorted(ENV_COUNTER.keys()):
61 print("%4d %s" % (ENV_COUNTER[k], k))
64 for failure in GetBuildFailures():
65 for node in Flatten(failure.node):
67 # If this wasn't a test, "GetTestName" will return raw_name.
68 'test_name': GetTestName(node),
69 'raw_name': str(node.path),
70 'errstr': failure.errstr
73 json_path = ARGUMENTS.get('json_build_results_output_file')
75 with open(json_path, 'w') as f:
76 json.dump(failures, f, sort_keys=True, indent=2)
83 print('ERROR REPORT: %d failures' % len(failures))
86 for failure in failures:
87 test_name = failure['test_name']
88 if test_name != failure['raw_name']:
89 test_name = '%s (%s)' % (test_name, failure['raw_name'])
90 print("%s failed: %s\n" % (test_name, failure['errstr']))
93 def VerboseConfigInfo(env):
94 "Should we print verbose config information useful for bug reports"
95 if '--help' in sys.argv: return False
96 if env.Bit('prebuilt') or env.Bit('built_elsewhere'): return False
97 return env.Bit('sysinfo')
102 # NOTE BitFromArgument(...) implicitly defines additional ACCEPTABLE_ARGUMENTS.
103 ACCEPTABLE_ARGUMENTS = set([
104 # TODO: add comments what these mean
105 # TODO: check which ones are obsolete
106 #### ASCII SORTED ####
107 # Use a destination directory other than the default "scons-out".
111 # Limit bandwidth of browser tester
113 # Location to download Chromium binaries to and/or read them from.
114 'chrome_binaries_dir',
115 # used for chrome_browser_tests: path to the browser
116 'chrome_browser_path',
117 # A comma-separated list of test names to disable by excluding the
118 # tests from a test suite. For example, 'small_tests
119 # disable_tests=run_hello_world_test' will run small_tests without
120 # including hello_world_test. Note that if a test listed here
121 # does not exist you will not get an error or a warning.
123 # used for chrome_browser_tests: path to a pre-built browser plugin.
124 'force_ppapi_plugin',
125 # force emulator use by tests
127 # force sel_ldr use by tests
129 # force nacl_helper_bootstrap used by tests
131 # force irt image used by tests
133 # force tls_edit binary used by tests
135 # generate_ninja=FILE enables a Ninja backend for SCons. This writes a
136 # .ninja build file to FILE describing all of SCons' build targets.
138 # Path to a JSON file for machine-readable output.
139 'json_build_results_output_file',
140 # Replacement memcheck command for overriding the DEPS-in memcheck
141 # script. May have commas to separate separate shell args. There
142 # is no quoting, so this implies that this mechanism will fail if
143 # the args actually need to have commas. See
144 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
145 # the discussion of why this argument is needed.
147 # If the replacement memcheck command only works for trusted code,
148 # set memcheck_trusted_only to non-zero.
149 'memcheck_trusted_only',
150 # When building with MSan, this can be set to values 0 (fastest, least
151 # useful reports) through 2 (slowest, most useful reports). Default is 1.
152 'msan_track_origins',
153 # colon-separated list of linker flags, e.g. "-lfoo:-Wl,-u,bar".
155 # prefix to add in-front of perf tracking trace labels.
157 # colon-separated list of pnacl bcld flags, e.g. "-lfoo:-Wl,-u,bar".
158 # Not using nacl_linkflags since that gets clobbered in some tests.
161 # Run tests under this tool (e.g. valgrind, tsan, strace, etc).
162 # If the tool has options, pass them after comma: 'tool,--opt1,--opt2'.
163 # NB: no way to use tools the names or the args of
164 # which contains a comma.
166 # More args for the tool.
167 'run_under_extra_args',
168 # Multiply timeout values by this number.
170 # test_wrapper specifies a wrapper program such as
171 # tools/run_test_via_ssh.py, which runs tests on a remote host
172 # using rsync and SSH. Example usage:
173 # ./scons run_hello_world_test platform=arm force_emulator= \
174 # test_wrapper="./tools/run_test_via_ssh.py --host=armbox --subdir=tmp"
176 # Replacement tsan command for overriding the DEPS-in tsan
177 # script. May have commas to separate separate shell args. There
178 # is no quoting, so this implies that this mechanism will fail if
179 # the args actually need to have commas. See
180 # http://code.google.com/p/nativeclient/issues/detail?id=3158 for
181 # the discussion of why this argument is needed.
183 # Run browser tests under this tool. See
184 # tools/browser_tester/browsertester/browserlauncher.py for tool names.
186 # Where to install header files for public consumption.
188 # Where to install libraries for public consumption.
190 # Where to install trusted-code binaries for public (SDK) consumption.
192 # Where a Breakpad build output directory is for optional Breakpad testing.
193 'breakpad_tools_dir',
194 # Allows overriding of the nacl newlib toolchain directory.
196 # Allows override of the nacl glibc toolchain directory.
198 # Allows override of the pnacl newlib toolchain directory.
200 # Allows override of the pnacl newlib toolchain directory.
202 # Allows overriding the version number in the toolchain's
203 # FEATURE_VERSION file. This is used for PNaCl ABI compatibility
205 'toolchain_feature_version',
209 # Overly general to provide compatibility with existing build bots, etc.
210 # In the future it might be worth restricting the values that are accepted.
211 _TRUE_STRINGS = set(['1', 'true', 'yes'])
212 _FALSE_STRINGS = set(['0', 'false', 'no'])
215 # Converts a string representing a Boolean value, of some sort, into an actual
216 # Boolean value. Python's built in type coercion does not work because
217 # bool('False') == True
218 def StringValueToBoolean(value):
219 # ExpandArguments may stick non-string values in ARGUMENTS. Be accommodating.
220 if isinstance(value, bool):
223 if not isinstance(value, str):
224 raise Exception("Expecting a string but got a %s" % repr(type(value)))
226 if value.lower() in _TRUE_STRINGS:
228 elif value.lower() in _FALSE_STRINGS:
231 raise Exception("Cannot convert '%s' to a Boolean value" % value)
234 def GetBinaryArgumentValue(arg_name, default):
235 if not isinstance(default, bool):
236 raise Exception("Default value for '%s' must be a Boolean" % arg_name)
237 if arg_name not in ARGUMENTS:
239 return StringValueToBoolean(ARGUMENTS[arg_name])
242 # name is the name of the bit
243 # arg_name is the name of the command-line argument, if it differs from the bit
244 def BitFromArgument(env, name, default, desc, arg_name=None):
245 # In most cases the bit name matches the argument name
249 DeclareBit(name, desc)
250 assert arg_name not in ACCEPTABLE_ARGUMENTS, repr(arg_name)
251 ACCEPTABLE_ARGUMENTS.add(arg_name)
253 if GetBinaryArgumentValue(arg_name, default):
259 # SetUpArgumentBits declares binary command-line arguments and converts them to
260 # bits. For example, one of the existing declarations would result in the
261 # argument "bitcode=1" causing env.Bit('bitcode') to evaluate to true.
262 # NOTE Command-line arguments are a SCons-ism that is separate from
263 # command-line options. Options are prefixed by "-" or "--" whereas arguments
264 # are not. The function SetBitFromOption can be used for options.
265 # NOTE This function must be called before the bits are used
266 # NOTE This function must be called after all modifications of ARGUMENTS have
267 # been performed. See: ExpandArguments
268 def SetUpArgumentBits(env):
269 BitFromArgument(env, 'bitcode', default=False,
270 desc='We are building bitcode')
272 BitFromArgument(env, 'pnacl_native_clang_driver', default=False,
273 desc='Use the (experimental) native PNaCl Clang driver')
275 BitFromArgument(env, 'nacl_clang', default=(not env.Bit('bitcode') and
276 not env.Bit('nacl_glibc')),
277 desc='Use the native nacl-clang newlib compiler instead of nacl-gcc')
279 BitFromArgument(env, 'saigo', default=False, desc='Use the saigo toolchain')
281 BitFromArgument(env, 'translate_fast', default=False,
282 desc='When using pnacl TC (bitcode=1) use accelerated translation step')
284 BitFromArgument(env, 'use_sz', default=False,
285 desc='When using pnacl TC (bitcode=1) use Subzero for fast translation')
287 # Setting built_elsewhere means that no trusted or untrusted builds will run.
288 BitFromArgument(env, 'built_elsewhere', default=False,
289 desc='The programs have already been built by another system')
291 BitFromArgument(env, 'skip_trusted_tests', default=False,
292 desc='Only run untrusted tests - useful for translator testing'
293 ' (also skips tests of the IRT itself')
295 BitFromArgument(env, 'nacl_pic', default=False,
296 desc='generate position indepent code for (P)NaCl modules')
298 BitFromArgument(env, 'nacl_static_link', default=not env.Bit('nacl_glibc'),
299 desc='Whether to use static linking instead of dynamic linking '
300 'for building NaCl executables during tests. '
301 'For nacl-newlib, the default is 1 (static linking). '
302 'For nacl-glibc, the default is 0 (dynamic linking).')
304 BitFromArgument(env, 'nacl_disable_shared', default=not env.Bit('nacl_glibc'),
305 desc='Do not build shared versions of libraries. '
306 'For nacl-newlib, the default is 1 (static libraries only). '
307 'For nacl-glibc, the default is 0 (both static and shared libraries).')
309 # Defaults on when --verbose is specified.
310 # --verbose sets 'brief_comstr' to False, so this looks a little strange
311 BitFromArgument(env, 'target_stats', default=not GetOption('brief_comstr'),
312 desc='Collect and display information about which commands are executed '
313 'during the build process')
315 BitFromArgument(env, 'werror', default=True,
316 desc='Treat warnings as errors (-Werror)')
318 BitFromArgument(env, 'disable_nosys_linker_warnings', default=False,
319 desc='Disable warning mechanism in src/untrusted/nosys/warning.h')
321 BitFromArgument(env, 'naclsdk_validate', default=True,
322 desc='Verify the presence of the SDK')
324 # TODO(mseaborn): Remove this, since this is always False -- Valgrind is
325 # no longer supported. This will require removing some Chromium-side
327 BitFromArgument(env, 'running_on_valgrind', default=False,
328 desc='Compile and test using valgrind')
330 BitFromArgument(env, 'pp', default=False,
331 desc='Enable pretty printing')
333 # Defaults on when --verbose is specified
334 # --verbose sets 'brief_comstr' to False, so this looks a little strange
335 BitFromArgument(env, 'sysinfo', default=not GetOption('brief_comstr'),
336 desc='Print verbose system information')
338 BitFromArgument(env, 'disable_flaky_tests', default=False,
339 desc='Do not run potentially flaky tests - used on Chrome bots')
341 BitFromArgument(env, 'use_sandboxed_translator', default=False,
342 desc='use pnacl sandboxed translator for linking (not available for arm)')
344 BitFromArgument(env, 'pnacl_generate_pexe', default=env.Bit('bitcode'),
345 desc='use pnacl to generate pexes and translate in a separate step')
347 BitFromArgument(env, 'translate_in_build_step', default=True,
348 desc='Run translation during build phase (e.g. if do_not_run_tests=1)')
350 BitFromArgument(env, 'pnacl_unsandboxed', default=False,
351 desc='Translate pexe to an unsandboxed, host executable')
353 BitFromArgument(env, 'nonsfi_nacl', default=False,
354 desc='Use Non-SFI Mode instead of the original SFI Mode. This uses '
355 'nonsfi_loader instead of sel_ldr, and it tells the PNaCl toolchain '
356 'to translate pexes to Non-SFI nexes.')
358 BitFromArgument(env, 'use_newlib_nonsfi_loader', default=True,
359 desc='Test nonsfi_loader linked against NaCl newlib instead of the one '
360 'linked against host libc. This flag makes sense only with '
363 BitFromArgument(env, 'browser_headless', default=False,
364 desc='Where possible, set up a dummy display to run the browser on '
365 'when running browser tests. On Linux, this runs the browser through '
366 'xvfb-run. This Scons does not need to be run with an X11 display '
367 'and we do not open a browser window on the user\'s desktop. '
368 'Unfortunately there is no equivalent on Mac OS X.')
370 BitFromArgument(env, 'disable_crash_dialog', default=True,
371 desc='Disable Windows\' crash dialog box, which Windows pops up when a '
372 'process exits with an unhandled fault. Windows enables this by '
373 'default for processes launched from the command line or from the '
374 'GUI. Our default is to disable it, because the dialog turns crashes '
375 'into hangs on Buildbot, and our test suite includes various crash '
378 BitFromArgument(env, 'do_not_run_tests', default=False,
379 desc='Prevents tests from running. This lets SCons build the files needed '
380 'to run the specified test(s) without actually running them. This '
381 'argument is a counterpart to built_elsewhere.')
383 BitFromArgument(env, 'no_gdb_tests', default=False,
384 desc='Prevents GDB tests from running. If GDB is not available, you can '
385 'test everything else by specifying this flag.')
387 # TODO(shcherbina): add support for other golden-based tests, not only
388 # run_x86_*_validator_testdata_tests.
389 BitFromArgument(env, 'regenerate_golden', default=False,
390 desc='When running golden-based tests, instead of comparing results '
391 'save actual output as golden data.')
393 BitFromArgument(env, 'x86_64_zero_based_sandbox', default=False,
394 desc='Use the zero-address-based x86-64 sandbox model instead of '
395 'the r15-based model.')
397 BitFromArgument(env, 'android', default=False,
398 desc='Build for Android target')
400 BitFromArgument(env, 'skip_nonstable_bitcode', default=False,
401 desc='Skip tests involving non-stable bitcode')
403 # Setting force_sel_ldr means that no trusted builds will run, but (unlike
404 # built_elsewhere), untrusted builds will run.
405 DeclareBit('force_no_trusted_build', 'Prevent use of trusted toolchain')
406 if 'force_sel_ldr' in ARGUMENTS or 'force_tls_edit' in ARGUMENTS:
407 env.SetBits('force_no_trusted_build')
409 #########################################################################
411 # This is for generating a testing library for use within private test
412 # enuminsts, where we want to compare and test different validators.
414 BitFromArgument(env, 'ncval_testing', default=False,
415 desc='EXPERIMENTAL: Compile validator code for testing within enuminsts')
417 # PNaCl sanity checks
418 if not env.Bit('bitcode'):
419 pnacl_only_flags = ('nonsfi_nacl',
420 'pnacl_generate_pexe',
422 'skip_nonstable_bitcode',
425 'use_sandboxed_translator')
427 for flag_name in pnacl_only_flags:
428 if env.Bit(flag_name):
429 raise UserError('The option %r only makes sense when using the '
430 'PNaCl toolchain (i.e. with bitcode=1)'
433 pnacl_incompatible_flags = ('nacl_clang',
436 for flag_name in pnacl_incompatible_flags:
437 if env.Bit(flag_name):
438 raise UserError('The option %r cannot be used when building with '
439 'PNaCl (i.e. with bitcode=1)' % flag_name)
441 if env.Bit('saigo') and not env.Bit('nacl_clang'):
442 raise UserError('To use the saigo toolchain, set both saigo and nacl_clang '
443 'to 1. You can specify the toolchain location with the '
444 'saigo_newlib_dir argument (default: '
445 'toolchain/<os>_<arch>/saigo_newlib_raw )')
447 def CheckArguments():
448 for key in ARGUMENTS:
449 if key not in ACCEPTABLE_ARGUMENTS:
450 raise UserError('bad argument: %s' % key)
453 def GetTargetPlatform():
454 return pynacl.platform.GetArch3264(ARGUMENTS.get('platform', 'x86-32'))
456 def GetBuildPlatform():
457 return pynacl.platform.GetArch3264()
460 environment_list = []
462 # Base environment for both nacl and non-nacl variants.
464 if ARGUMENTS.get('DESTINATION_ROOT') is not None:
465 kwargs['DESTINATION_ROOT'] = ARGUMENTS.get('DESTINATION_ROOT')
466 pre_base_env = Environment(
467 # Use the environment that scons was run in to run scons invoked commands.
468 # This allows in things like externally provided PATH, PYTHONPATH.
469 ENV = os.environ.copy(),
470 tools = ['component_setup'],
471 # SOURCE_ROOT is one leave above the native_client directory.
472 SOURCE_ROOT = Dir('#/..').abspath,
473 # Publish dlls as final products (to staging).
474 COMPONENT_LIBRARY_PUBLISH = True,
476 # Use workaround in special scons version.
478 LIBS_DO_SUBST = True,
480 # Select where to find coverage tools.
481 COVERAGE_MCOV = '../third_party/lcov/bin/mcov',
482 COVERAGE_GENHTML = '../third_party/lcov/bin/genhtml',
487 if 'generate_ninja' in ARGUMENTS:
488 import pynacl.scons_to_ninja
489 pynacl.scons_to_ninja.GenerateNinjaFile(
490 pre_base_env, dest_file=ARGUMENTS['generate_ninja'])
493 breakpad_tools_dir = ARGUMENTS.get('breakpad_tools_dir')
494 if breakpad_tools_dir is not None:
495 pre_base_env['BREAKPAD_TOOLS_DIR'] = pre_base_env.Dir(
496 os.path.abspath(breakpad_tools_dir))
500 DeclareBit('clang', 'Use clang to build trusted code')
501 pre_base_env.SetBitFromOption('clang', True)
504 'Use AddressSanitizer to build trusted code (implies --clang)')
505 pre_base_env.SetBitFromOption('asan', False)
506 if pre_base_env.Bit('asan'):
507 pre_base_env.SetBits('clang')
510 'Use MemorySanitizer to build trusted code (implies --clang)')
511 pre_base_env.SetBitFromOption('msan', False)
512 if pre_base_env.Bit('msan'):
513 pre_base_env.SetBits('clang')
516 DeclareBit('coverage_enabled', 'The build should be instrumented to generate'
517 'coverage information')
519 # If the environment variable BUILDBOT_BUILDERNAME is set, we can determine
520 # if we are running in a VM by the lack of a '-bare-' (aka bare metal) in the
521 # bot name. Otherwise if the builder name is not set, then assume real HW.
522 DeclareBit('running_on_vm', 'Returns true when environment is running in a VM')
523 builder = os.environ.get('BUILDBOT_BUILDERNAME')
524 if builder and builder.find('-bare-') == -1:
525 pre_base_env.SetBits('running_on_vm')
527 pre_base_env.ClearBits('running_on_vm')
529 DeclareBit('nacl_glibc', 'Use nacl-glibc for building untrusted code')
530 pre_base_env.SetBitFromOption('nacl_glibc', False)
532 # This function should be called ASAP after the environment is created, but
533 # after ExpandArguments.
534 SetUpArgumentBits(pre_base_env)
536 # Register PrintFinalReport only after SetUpArgumentBits since it references
537 # bits that get declared in SetUpArgumentBits
538 atexit.register(PrintFinalReport)
540 def DisableCrashDialog():
541 if sys.platform == 'win32':
544 # The double call is to preserve existing flags, as discussed at
545 # http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
546 new_flags = win32con.SEM_NOGPFAULTERRORBOX
547 existing_flags = win32api.SetErrorMode(new_flags)
548 win32api.SetErrorMode(existing_flags | new_flags)
550 if pre_base_env.Bit('disable_crash_dialog'):
553 # We want to pull CYGWIN setup in our environment or at least set flag
554 # nodosfilewarning. It does not do anything when CYGWIN is not involved
555 # so let's do it in all cases.
556 pre_base_env['ENV']['CYGWIN'] = os.environ.get('CYGWIN', 'nodosfilewarning')
558 # Note: QEMU_PREFIX_HOOK may influence test runs and sb translator invocations
559 pre_base_env['ENV']['QEMU_PREFIX_HOOK'] = os.environ.get('QEMU_PREFIX_HOOK', '')
561 # Allow the zero-based sandbox model to run insecurely.
562 # TODO(arbenson): remove this once binutils bug is fixed (see
563 # src/trusted/service_runtime/arch/x86_64/sel_addrspace_posix_x86_64.c)
564 if pre_base_env.Bit('x86_64_zero_based_sandbox'):
565 pre_base_env['ENV']['NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX'] = 1
567 if pre_base_env.Bit('werror'):
568 werror_flags = ['-Werror']
572 # Allow variadic macros
573 werror_flags = werror_flags + ['-Wno-variadic-macros']
575 if pre_base_env.Bit('clang'):
576 # Allow 'default' label in switch even when all enumeration cases
578 werror_flags += ['-Wno-covered-switch-default']
579 # Allow C++11 extensions (for "override")
580 werror_flags += ['-Wno-c++11-extensions']
583 # Method to make sure -pedantic, etc, are not stripped from the
584 # default env, since occasionally an engineer will be tempted down the
585 # dark -- but wide and well-trodden -- path of expediency and stray
586 # from the path of correctness.
588 def EnsureRequiredBuildWarnings(env):
589 if (env.Bit('linux') or env.Bit('mac')) and not env.Bit('android'):
590 required_env_flags = set(['-pedantic', '-Wall'] + werror_flags)
591 ccflags = set(env.get('CCFLAGS'))
593 if not required_env_flags.issubset(ccflags):
594 raise UserError('required build flags missing: '
595 + ' '.join(required_env_flags.difference(ccflags)))
597 # windows get a pass for now
600 pre_base_env.AddMethod(EnsureRequiredBuildWarnings)
602 # Expose MakeTempDir and MakeTempFile to scons scripts
603 def MakeEmptyFile(env, **kwargs):
604 fd, path = test_lib.MakeTempFile(env, **kwargs)
608 pre_base_env.AddMethod(test_lib.MakeTempDir)
609 pre_base_env.AddMethod(MakeEmptyFile)
611 # Method to add target suffix to name.
612 def NaClTargetArchSuffix(env, name):
613 return name + '_' + env['TARGET_FULLARCH'].replace('-', '_')
615 pre_base_env.AddMethod(NaClTargetArchSuffix)
618 # Generic Test Wrapper
620 # Add list of Flaky or Bad tests to skip per platform. A
621 # platform is defined as build type
622 # <BUILD_TYPE>-<SUBARCH>
627 # This is a list of tests that do not yet pass when using nacl-glibc.
628 # TODO(mseaborn): Enable more of these tests!
629 nacl_glibc_skiplist = set([
630 # Struct layouts differ.
632 # Syscall wrappers not implemented yet.
635 # Fails because clock() is not hooked up.
636 'run_timefuncs_test',
637 # Needs further investigation.
639 # This test fails with nacl-glibc: glibc reports an internal
640 # sanity check failure in free().
641 # TODO(robertm): This needs further investigation.
642 'run_ppapi_event_test',
643 'run_ppapi_geturl_valid_test',
644 'run_ppapi_geturl_invalid_test',
645 # http://code.google.com/p/chromium/issues/detail?id=108131
646 # we would need to list all of the glibc components as
647 # web accessible resources in the extensions's manifest.json,
648 # not just the nexe and nmf file.
649 'run_ppapi_extension_mime_handler_browser_test',
651 nacl_glibc_skiplist.update(['%s_irt' % test for test in nacl_glibc_skiplist])
653 # Allowlist of tests to run for Non-SFI Mode. Note that typos here will
654 # not be caught automatically!
655 # TODO(mseaborn): Eventually we should run all of small_tests instead of
657 nonsfi_test_allowlist = set([
658 'run_arm_float_abi_test',
659 'run_clock_get_test',
661 'run_directory_test',
663 'run_example_irt_caller_test',
664 'run_exception_test',
666 'run_file_descriptor_test',
670 'run_hello_world_test',
672 'run_irt_futex_test',
673 'run_malloc_realloc_calloc_free_test',
675 'run_nanosleep_test',
676 'run_nonsfi_syscall_test',
682 'run_sigaction_test',
683 'run_signal_sigbus_test',
686 'run_stack_alignment_asm_test',
687 'run_stack_alignment_test',
690 'run_user_async_signal_test',
694 # If a test is not in one of these suites, it will probally not be run on a
695 # regular basis. These are the suites that will be run by the try bot or that
696 # a large number of users may run by hand.
697 MAJOR_TEST_SUITES = set([
701 # Tests using the pepper plugin, only run with chrome
702 # TODO(ncbray): migrate pepper_browser_tests to chrome_browser_tests
703 'pepper_browser_tests',
704 # Lightweight browser tests
705 'chrome_browser_tests',
707 'memcheck_bot_tests',
709 # Special testing environment for testing comparing x86 validators.
711 # Environment for validator difference testing
712 'validator_diff_tests',
713 # Subset of tests enabled for Non-SFI Mode.
717 # These are the test suites we know exist, but aren't run on a regular basis.
718 # These test suites are essentially shortcuts that run a specific subset of the
720 ACCEPTABLE_TEST_SUITES = set([
722 'dynamic_load_tests',
723 'eh_tests', # Tests for C++ exception handling
724 'exception_tests', # Tests for hardware exception handling
730 'sel_ldr_sled_tests',
733 'validator_modeling',
735 # Special testing of the decoder for the ARM validator.
739 # Under --mode=nacl_irt_test we build variants of numerous tests normally
740 # built under --mode=nacl. The test names and suite names for these
741 # variants are set (in IrtTestAddNodeToTestSuite, below) by appending _irt
742 # to the names used for the --mode=nacl version of the same tests.
743 MAJOR_TEST_SUITES |= set([name + '_irt'
744 for name in MAJOR_TEST_SUITES])
745 ACCEPTABLE_TEST_SUITES |= set([name + '_irt'
746 for name in ACCEPTABLE_TEST_SUITES])
748 # The major test suites are also acceptable names. Suite names are checked
749 # against this set in order to catch typos.
750 ACCEPTABLE_TEST_SUITES.update(MAJOR_TEST_SUITES)
753 def ValidateTestSuiteNames(suite_name, node_name):
754 if node_name is None:
755 node_name = '<unknown>'
757 # Prevent a silent failiure - strings are iterable!
758 if not isinstance(suite_name, (list, tuple)):
759 raise Exception("Test suites for %s should be specified as a list, "
760 "not as a %s: %s" % (node_name, type(suite_name).__name__,
764 raise Exception("No test suites are specified for %s. Set the 'broken' "
765 "parameter on AddNodeToTestSuite in the cases where there's a known "
766 "issue and you don't want the test to run" % (node_name,))
768 # Make sure each test is in at least one test suite we know will run
769 major_suites = set(suite_name).intersection(MAJOR_TEST_SUITES)
771 raise Exception("None of the test suites %s for %s are run on a "
772 "regular basis" % (repr(suite_name), node_name))
774 # Make sure a wierd test suite hasn't been inadvertantly specified
776 if s not in ACCEPTABLE_TEST_SUITES:
777 raise Exception("\"%s\" is not a known test suite. Either this is "
778 "a typo for %s, or it should be added to ACCEPTABLE_TEST_SUITES in "
779 "SConstruct" % (s, node_name))
781 BROKEN_TEST_COUNT = 0
784 def GetPlatformString(env):
785 build = env['BUILD_TYPE']
787 # If we are testing 'NACL' we really need the trusted info
788 if build=='nacl' and 'TRUSTED_ENV' in env:
789 trusted_env = env['TRUSTED_ENV']
790 build = trusted_env['BUILD_TYPE']
791 subarch = trusted_env['BUILD_SUBARCH']
793 subarch = env['BUILD_SUBARCH']
795 # Build the test platform string
796 return build + '-' + subarch
798 pre_base_env.AddMethod(GetPlatformString)
801 tests_to_disable_qemu = set([
802 # These tests do not work under QEMU but do work on ARM hardware.
804 # You should use the is_broken argument in preference to adding
805 # tests to this list.
807 # See: http://code.google.com/p/nativeclient/issues/detail?id=2437
808 # Note, for now these tests disable both the irt and non-irt variants
809 'run_egyptian_cotton_test',
810 'run_many_threads_sequential_test',
811 # subprocess needs to also have qemu prefix, which isn't supported
812 'run_subprocess_test',
813 'run_thread_suspension_test',
814 'run_dynamic_modify_test',
815 'run_irt_ext_libc_test', # Flaky for saigo
816 'run_nacl_desc_io_alloc_ctor_test',
819 tests_to_disable = set()
820 if ARGUMENTS.get('disable_tests', '') != '':
821 tests_to_disable.update(ARGUMENTS['disable_tests'].split(','))
824 def ShouldSkipTest(env, node_name):
825 if (env.Bit('skip_trusted_tests')
826 and (env['NACL_BUILD_FAMILY'] == 'TRUSTED'
827 or env['NACL_BUILD_FAMILY'] == 'UNTRUSTED_IRT')):
830 if env.Bit('do_not_run_tests'):
831 # This hack is used for pnacl testing where we might build tests
832 # without running them on one bot and then transfer and run them on another.
833 # The skip logic only takes the first bot into account e.g. qemu
834 # restrictions, while it really should be skipping based on the second
835 # bot. By simply disabling the skipping completely we work around this.
838 # There are no known-to-fail tests any more, but this code is left
839 # in so that if/when we port to a new architecture or add a test
840 # that is known to fail on some platform(s), we can continue to have
841 # a central location to disable tests from running. NB: tests that
842 # don't *build* on some platforms need to be omitted in another way.
844 if node_name in tests_to_disable:
847 if env.UsingEmulator():
848 if node_name in tests_to_disable_qemu:
850 # For now also disable the irt variant
851 if node_name.endswith('_irt') and node_name[:-4] in tests_to_disable_qemu:
854 # Retrieve list of tests to skip on this platform
855 skiplist = bad_build_lists.get(env.GetPlatformString(), [])
856 if node_name in skiplist:
859 if env.Bit('nacl_glibc') and node_name in nacl_glibc_skiplist:
864 pre_base_env.AddMethod(ShouldSkipTest)
867 def AddImplicitTestSuites(suite_list, node_name):
868 if node_name in nonsfi_test_allowlist:
869 suite_list = suite_list + ['nonsfi_tests']
873 def AddNodeToTestSuite(env, node, suite_name, node_name, is_broken=False,
875 global BROKEN_TEST_COUNT
877 # CommandTest can return an empty list when it silently discards a test
881 assert node_name is not None
882 test_name_regex = r'run_.*_(unit)?test.*$'
883 assert re.match(test_name_regex, node_name), (
884 'test %r does not match "run_..._test" naming convention '
885 '(precise regex is %s)' % (node_name, test_name_regex))
887 suite_name = AddImplicitTestSuites(suite_name, node_name)
888 ValidateTestSuiteNames(suite_name, node_name)
892 if is_broken or is_flaky and env.Bit('disable_flaky_tests'):
893 # Only print if --verbose is specified
894 if not GetOption('brief_comstr'):
895 print('*** BROKEN ', node_name)
896 BROKEN_TEST_COUNT += 1
897 env.Alias('broken_tests', node)
898 elif env.ShouldSkipTest(node_name):
899 print('*** SKIPPING ', env.GetPlatformString(), ':', node_name)
900 env.Alias('broken_tests', node)
902 env.Alias('all_tests', node)
908 env.ComponentTestOutput(node_name, node)
909 test_name = node_name
911 # This is rather shady, but the tests need a name without dots so they match
913 # TODO(ncbray) node_name should not be optional.
914 test_name = os.path.basename(str(node[0].path))
915 if test_name.endswith('.out'):
916 test_name = test_name[:-4]
917 test_name = test_name.replace('.', '_')
918 SetTestName(node, test_name)
920 pre_base_env.AddMethod(AddNodeToTestSuite)
923 def TestBindsFixedTcpPort(env, node):
924 # This tells Scons that tests that bind a fixed TCP port should not
925 # run concurrently, because they would interfere with each other.
926 # These tests are typically tests for NaCl's GDB debug stub. The
927 # dummy filename used below is an arbitrary token that just has to
928 # match across the tests.
929 SideEffect(env.File('${SCONSTRUCT_DIR}/test_binds_fixed_tcp_port'), node)
931 pre_base_env.AddMethod(TestBindsFixedTcpPort)
934 # Convenient testing aliases
935 # NOTE: work around for scons non-determinism in the following two lines
936 Alias('sel_ldr_sled_tests', [])
938 Alias('small_tests', [])
939 Alias('medium_tests', [])
940 Alias('large_tests', [])
942 Alias('small_tests_irt', [])
943 Alias('medium_tests_irt', [])
944 Alias('large_tests_irt', [])
946 Alias('pepper_browser_tests', [])
947 Alias('chrome_browser_tests', [])
949 Alias('unit_tests', 'small_tests')
950 Alias('smoke_tests', ['small_tests', 'medium_tests'])
952 if pre_base_env.Bit('nacl_glibc'):
953 Alias('memcheck_bot_tests', ['small_tests'])
954 Alias('tsan_bot_tests', ['small_tests'])
956 Alias('memcheck_bot_tests', ['small_tests', 'medium_tests', 'large_tests'])
957 Alias('tsan_bot_tests', [])
965 pre_base_env.AddMethod(Banner)
969 # Define the platforms, and use them to define the path for the
970 # scons-out directory (aka TARGET_ROOT)
972 # Various variables in the scons environment are related to this, e.g.
974 # BUILD_ARCH: (arm, mips, x86)
975 # BUILD_SUBARCH: (32, 64)
978 DeclareBit('build_x86_32', 'Building binaries for the x86-32 architecture',
979 exclusive_groups='build_arch')
980 DeclareBit('build_x86_64', 'Building binaries for the x86-64 architecture',
981 exclusive_groups='build_arch')
982 DeclareBit('build_mips32', 'Building binaries for the MIPS architecture',
983 exclusive_groups='build_arch')
984 DeclareBit('build_arm_arm', 'Building binaries for the ARM architecture',
985 exclusive_groups='build_arch')
987 # Shorthand for either the 32 or 64 bit version of x86.
988 DeclareBit('build_x86', 'Building binaries for the x86 architecture')
990 DeclareBit('build_arm', 'Building binaries for the arm architecture')
993 def MakeArchSpecificEnv(platform=None):
994 env = pre_base_env.Clone()
996 platform = GetTargetPlatform()
998 arch = pynacl.platform.GetArch(platform)
999 if pynacl.platform.IsArch64Bit(platform):
1004 env.Replace(BUILD_FULLARCH=platform)
1005 env.Replace(BUILD_ARCHITECTURE=arch)
1006 env.Replace(BUILD_SUBARCH=subarch)
1007 env.Replace(TARGET_FULLARCH=platform)
1008 env.Replace(TARGET_ARCHITECTURE=arch)
1009 env.Replace(TARGET_SUBARCH=subarch)
1011 env.SetBits('build_%s' % platform.replace('-', '_'))
1013 if env.Bit('build_x86_32') or env.Bit('build_x86_64'):
1014 env.SetBits('build_x86')
1015 if env.Bit('build_arm_arm'):
1016 env.SetBits('build_arm')
1017 if env.Bit('build_mips32') and env.Bit('clang'):
1018 raise UserError('Mips build not supported with clang')
1020 env.Replace(BUILD_ISA_NAME=platform)
1022 # Determine where the object files go
1023 env.Replace(BUILD_TARGET_NAME=platform)
1024 # This may be changed later; see target_variant_map, below.
1025 env.Replace(TARGET_VARIANT='')
1026 env.Replace(TARGET_ROOT=
1027 '${DESTINATION_ROOT}/${BUILD_TYPE}-${BUILD_TARGET_NAME}${TARGET_VARIANT}')
1032 pre_base_env.AddMethod(lambda self: ARGUMENTS.get('running_on_valgrind'),
1033 'IsRunningUnderValgrind')
1035 DeclareBit('with_leakcheck', 'Running under Valgrind leak checker')
1037 def RunningUnderLeakCheck():
1038 run_under = ARGUMENTS.get('run_under')
1040 extra_args = ARGUMENTS.get('run_under_extra_args')
1042 run_under += extra_args
1043 if run_under.find('leak-check=full') > 0:
1047 if RunningUnderLeakCheck():
1048 pre_base_env.SetBits('with_leakcheck')
1051 def StripSuffix(string, suffix):
1052 assert string.endswith(suffix)
1053 return string[:-len(suffix)]
1056 # TODO(mseaborn): Change code to use ComponentLibrary() directly.
1057 # DualLibrary() is left over from when we built libraries twice, with and
1058 # without "-fPIC", for building plugins as DSOs.
1059 def DualLibrary(env, lib_name, *args, **kwargs):
1060 return env.ComponentLibrary(lib_name, *args, **kwargs)
1062 def DualObject(env, *args, **kwargs):
1063 return env.ComponentObject(*args, **kwargs)
1066 def AddDualLibrary(env):
1067 env.AddMethod(DualLibrary)
1068 env.AddMethod(DualObject)
1071 # In prebuild mode we ignore the dependencies so that stuff does
1072 # NOT get build again
1073 # Optionally ignore the build process.
1074 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
1075 pre_base_env.SetBitFromOption('prebuilt', False)
1078 # HELPERS FOR TEST INVOLVING TRUSTED AND UNTRUSTED ENV
1079 def GetEmulator(env):
1080 emulator = ARGUMENTS.get('force_emulator')
1081 if emulator is None and 'TRUSTED_ENV' in env:
1082 emulator = env['TRUSTED_ENV'].get('EMULATOR')
1085 pre_base_env.AddMethod(GetEmulator)
1087 def UsingEmulator(env):
1088 return bool(env.GetEmulator())
1090 pre_base_env.AddMethod(UsingEmulator)
1093 def GetValidator(env, validator):
1094 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1095 if 'TRUSTED_ENV' not in env:
1098 # TODO(shyamsundarr): rename ncval_new to ncval.
1099 if validator is None:
1100 if env.Bit('build_arm'):
1101 validator = 'arm-ncval-core'
1102 elif env.Bit('build_mips32'):
1103 validator = 'mips-ncval-core'
1105 validator = 'ncval_new'
1107 trusted_env = env['TRUSTED_ENV']
1108 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}%s${PROGSUFFIX}' %
1111 pre_base_env.AddMethod(GetValidator)
1114 # Perform os.path.abspath rooted at the directory SConstruct resides in.
1115 def SConstructAbsPath(env, path):
1116 return os.path.normpath(os.path.join(env['MAIN_DIR'], path))
1118 pre_base_env.AddMethod(SConstructAbsPath)
1121 def GetPlatformBuildTargetDir(env):
1122 # Currently we do not support any cross OS compiles, eventually the OS name
1123 # will probably be passed in through arguments.
1124 os_name = pynacl.platform.GetOS()
1126 # Currently 32/64 share the same tool build target directory. When we have
1127 # separate toolchains for each the architectures will probably have to use
1128 # the Arch3264() variant.
1129 build_arch = pynacl.platform.GetArch(GetBuildPlatform())
1131 return '%s_%s' % (os_name, build_arch)
1133 pre_base_env.AddMethod(GetPlatformBuildTargetDir)
1136 def GetToolchainDir(env, platform_build_dir=None, toolchain_name=None,
1137 target_arch=None, is_pnacl=None, lib_name=None):
1138 if platform_build_dir is None:
1139 platform_build_dir = env.GetPlatformBuildTargetDir()
1141 if toolchain_name is None:
1142 # Fill in default arguments based on environment.
1143 if is_pnacl is None:
1144 # For the purposes of finding the toolchain dir, nacl_clang is PNaCl.
1145 is_pnacl = env.Bit('bitcode') or env.Bit('nacl_clang')
1146 if lib_name is None:
1147 if is_pnacl or not env.Bit('nacl_glibc'):
1152 is_saigo = env.Bit('saigo')
1154 if target_arch is None:
1155 target_arch = pynacl.platform.GetArch(GetTargetPlatform())
1157 # See if we have a custom toolchain directory set.
1158 if is_saigo and lib_name != 'glibc':
1159 toolchain_arg = 'saigo_%s_dir' % lib_name
1161 toolchain_arg = 'pnacl_%s_dir' % lib_name
1163 assert lib_name == 'glibc'
1164 toolchain_arg = 'nacl_%s_dir' % lib_name
1166 custom_toolchain_dir = ARGUMENTS.get(toolchain_arg, None)
1167 if custom_toolchain_dir:
1168 return env.SConstructAbsPath(custom_toolchain_dir)
1170 # Get the standard toolchain name since no directory custom was found.
1171 if is_saigo and lib_name != 'glibc':
1172 target_env = 'saigo'
1174 target_env = 'pnacl'
1176 target_env = 'nacl_%s' % target_arch
1177 toolchain_name = '%s_%s_raw' % (target_env, lib_name)
1179 # Get the absolute path for the platform build directory and toolchain.
1180 toolchain_sub_dir = os.path.join('toolchain',
1183 return env.SConstructAbsPath(toolchain_sub_dir)
1185 pre_base_env.AddMethod(GetToolchainDir)
1189 sel_ldr = ARGUMENTS.get('force_sel_ldr')
1191 return env.File(env.SConstructAbsPath(sel_ldr))
1193 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1194 if 'TRUSTED_ENV' not in env:
1197 trusted_env = env['TRUSTED_ENV']
1198 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}sel_ldr${PROGSUFFIX}')
1200 pre_base_env.AddMethod(GetSelLdr)
1203 def GetSelLdrSeccomp(env):
1204 # NOTE: that the variable TRUSTED_ENV is set by ExportSpecialFamilyVars()
1205 if 'TRUSTED_ENV' not in env:
1208 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1211 trusted_env = env['TRUSTED_ENV']
1212 return trusted_env.File('${STAGING_DIR}/${PROGPREFIX}'
1213 'sel_ldr_seccomp${PROGSUFFIX}')
1215 pre_base_env.AddMethod(GetSelLdrSeccomp)
1218 def SupportsSeccompBpfSandbox(env):
1219 if not (env.Bit('linux') and env.Bit('build_x86_64')):
1222 # The gcov runtime does some extra calls (such as 'access') that
1223 # are not permitted by the policy.
1224 if env.Bit('coverage_enabled'):
1227 # This is a lame detection if seccomp bpf filters are supported by the kernel.
1228 # We suppose that any Linux kernel v3.2+ supports it, but it is only true
1229 # for Ubuntu kernels. Seccomp BPF filters reached the mainline at 3.5,
1230 # so this check will be wrong on some relatively old non-Ubuntu Linux distros.
1231 kernel_version = list(map(int, platform.release().split('.', 2)[:2]))
1232 return kernel_version >= [3, 2]
1234 pre_base_env.AddMethod(SupportsSeccompBpfSandbox)
1237 def GetBootstrap(env):
1239 # Bootstrap doens't currently work with MSan. However, MSan is only
1240 # available on x86_64 where we don't need bootstrap anyway.
1242 bootstrap = ARGUMENTS.get('force_bootstrap')
1244 bootstrap = env.File(env.SConstructAbsPath(bootstrap))
1246 if 'TRUSTED_ENV' in env:
1247 trusted_env = env['TRUSTED_ENV']
1248 if trusted_env.Bit('linux'):
1249 bootstrap = trusted_env.File('${STAGING_DIR}/nacl_helper_bootstrap')
1251 template_digits = 'X' * 16
1253 ['--r_debug=0x' + template_digits,
1254 '--reserved_at_zero=0x' + template_digits])
1257 pre_base_env.AddMethod(GetBootstrap)
1259 def AddBootstrap(env, executable, args):
1260 bootstrap, bootstrap_args = env.GetBootstrap()
1261 if bootstrap is None:
1262 return [executable] + args
1264 return [bootstrap, executable] + bootstrap_args + args
1266 pre_base_env.AddMethod(AddBootstrap)
1269 def GetNonSfiLoader(env):
1270 if env.Bit('use_newlib_nonsfi_loader'):
1271 return nacl_env.GetTranslatedNexe(nacl_env.File(
1272 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}'))
1274 if 'TRUSTED_ENV' not in env:
1276 return env['TRUSTED_ENV'].File(
1277 '${STAGING_DIR}/${PROGPREFIX}nonsfi_loader${PROGSUFFIX}')
1279 pre_base_env.AddMethod(GetNonSfiLoader)
1282 def GetIrtNexe(env, chrome_irt=False):
1283 image = ARGUMENTS.get('force_irt')
1285 return env.SConstructAbsPath(image)
1288 return nacl_irt_env.File('${STAGING_DIR}/irt.nexe')
1290 return nacl_irt_env.File('${STAGING_DIR}/irt_core.nexe')
1292 pre_base_env.AddMethod(GetIrtNexe)
1295 # Note that we build elf_loader in the nacl_irt_env, not because it is
1296 # actually built like the IRT per se, but just because we need it always to
1297 # be built against newlib.
1298 def GetElfLoaderNexe(env):
1299 elf_loader_env = nacl_env
1300 if env.Bit('nacl_glibc'):
1301 elf_loader_env = nacl_irt_env
1302 return elf_loader_env.File('${STAGING_DIR}/elf_loader.nexe')
1304 pre_base_env.AddMethod(GetElfLoaderNexe)
1307 def ApplyTLSEdit(env, nexe_name, raw_nexe):
1308 # If the environment was built elsewhere, we do not need to apply tls_edit
1309 # since it only needs to be done during building.
1310 if env.Bit('built_elsewhere'):
1311 return env.File(nexe_name)
1313 tls_edit_forced = ARGUMENTS.get('force_tls_edit')
1315 tls_edit_exe = env.File(env.SConstructAbsPath(tls_edit_forced))
1317 tls_edit_exe = env['BUILD_ENV'].File('${STAGING_DIR}/tls_edit${PROGSUFFIX}')
1320 [tls_edit_exe, raw_nexe],
1321 '${SOURCES[0]} --verbose ${SOURCES[1:]} ${TARGET}')
1323 pre_base_env.AddMethod(ApplyTLSEdit)
1325 def CommandValidatorTestNacl(env, name, image,
1326 validator_flags=None,
1330 validator = env.GetValidator(validator)
1331 if validator is None:
1332 print('WARNING: no validator found. Skipping test %s' % name)
1335 if validator_flags is None:
1336 validator_flags = []
1338 if env.Bit('pnacl_generate_pexe'):
1341 command = [validator] + validator_flags + [image]
1342 return env.CommandTest(name, command, size, **extra)
1344 pre_base_env.AddMethod(CommandValidatorTestNacl)
1347 def ExtractPublishedFiles(env, target_name):
1348 run_files = ['$STAGING_DIR/' + os.path.basename(published_file.path)
1349 for published_file in env.GetPublished(target_name, 'run')]
1350 nexe = '$STAGING_DIR/%s${PROGSUFFIX}' % target_name
1351 return [env.File(file) for file in run_files + [nexe]]
1353 pre_base_env.AddMethod(ExtractPublishedFiles)
1356 # Only include the chrome side of the build if present.
1357 if os.path.exists(pre_base_env.File(
1358 '#/../ppapi/native_client/chrome_main.scons').abspath):
1359 SConscript('#/../ppapi/native_client/chrome_main.scons',
1360 exports=['pre_base_env'])
1361 enable_chrome = True
1363 def AddChromeFilesFromGroup(env, file_group):
1365 pre_base_env.AddMethod(AddChromeFilesFromGroup)
1366 enable_chrome = False
1367 DeclareBit('enable_chrome_side',
1368 'Is the chrome side present.')
1369 pre_base_env.SetBitFromOption('enable_chrome_side', enable_chrome)
1371 def ProgramNameForNmf(env, basename):
1372 """ Create an architecture-specific filename that can be used in an NMF URL.
1374 if env.Bit('pnacl_generate_pexe'):
1377 return '%s_%s' % (basename, env.get('TARGET_FULLARCH'))
1379 pre_base_env.AddMethod(ProgramNameForNmf)
1382 def MakeNaClLogOption(env, target):
1383 """ Make up a filename related to the [target], for use with NACLLOG.
1384 The file should end up in the build directory (scons-out/...).
1386 # NOTE: to log to the source directory use file.srcnode().abspath instead.
1387 # See http://www.scons.org/wiki/File%28%29
1388 return env.File(target + '.nacllog').abspath
1390 pre_base_env.AddMethod(MakeNaClLogOption)
1392 def MakeVerboseExtraOptions(env, target, log_verbosity, extra):
1393 """ Generates **extra options that will give access to service runtime logs,
1394 at a given log_verbosity. Slips the options into the given extra dict. """
1395 log_file = env.MakeNaClLogOption(target)
1396 extra['log_file'] = log_file
1397 extra_env = ['NACLLOG=%s' % log_file,
1398 'NACLVERBOSITY=%d' % log_verbosity]
1399 extra['osenv'] = extra.get('osenv', []) + extra_env
1401 pre_base_env.AddMethod(MakeVerboseExtraOptions)
1403 def ShouldUseVerboseOptions(env, extra):
1404 """ Heuristic for setting up Verbose NACLLOG options. """
1405 return ('process_output_single' in extra or
1406 'log_golden' in extra)
1408 pre_base_env.AddMethod(ShouldUseVerboseOptions)
1411 DeclareBit('tests_use_irt', 'Non-browser tests also load the IRT image', False)
1413 # Bit to be set by individual test/nacl.scons files that need to opt out.
1414 DeclareBit('nonstable_bitcode', 'Tests use non-stable bitcode features', False)
1417 def GetFinalizedPexe(env, pexe):
1418 """ Prep and finalize the ABI for a given pexe if needed.
1420 if not env.Bit('pnacl_generate_pexe') or env.Bit('nonstable_bitcode'):
1423 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1424 # file instead. There are currently some canned nexe tests in build.scons.
1425 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1428 # Otherwise, finalize during the build step, since there is no finalize tool
1429 # that can run on triggered bots such as the ARM HW bots.
1430 pexe_name = pexe.abspath
1431 final_name = StripSuffix(pexe_name, '.nonfinal.pexe') + '.final.pexe'
1432 # Make sure the pexe doesn't get removed by the fake builders when
1435 node = env.Command(target=final_name, source=[pexe_name],
1436 action=[Action('${PNACLFINALIZECOM}',
1437 '${PNACLFINALIZECOMSTR}')])
1438 env.Alias('all_programs', node)
1439 assert len(node) == 1, node
1442 pre_base_env.AddMethod(GetFinalizedPexe)
1445 # Translate the given pexe.
1446 def GetTranslatedNexe(env, pexe):
1447 # First finalize the pexe.
1448 pexe = GetFinalizedPexe(env, pexe)
1450 # Then check if we need to translate.
1451 # Check if we started with a pexe, so there is actually a translation step.
1452 if not env.Bit('pnacl_generate_pexe'):
1455 # We can remove this once we move all CommandSelLdrTestNacl to a nacl.scons
1456 # file instead. There are currently some canned nexe tests in build.scons.
1457 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1460 # Often there is a build step (do_not_run_tests=1) and a test step
1461 # (which is run with -j1). Normally we want to translate in the build step
1462 # so we can translate in parallel. However when we do sandboxed translation
1463 # on arm hw, we do the build step on x86 and translation on arm, so we have
1464 # to force the translation to be done in the test step. Hence,
1465 # we check the bit 'translate_in_build_step' / check if we are
1467 if not env.Bit('translate_in_build_step') and env.Bit('do_not_run_tests'):
1470 pexe_name = pexe.abspath
1471 # Tidy up the suffix (remove the .final.pexe or .nonfinal.pexe),
1472 # depending on whether or not the pexe was finalized.
1473 suffix_to_strip = '.final.pexe'
1474 if not pexe_name.endswith(suffix_to_strip):
1475 suffix_to_strip = '.nonfinal.pexe'
1476 nexe_name = StripSuffix(pexe_name, suffix_to_strip) + '.nexe'
1477 # Make sure the pexe doesn't get removed by the fake builders when
1480 command = '${TRANSLATECOM}'
1481 if env.Bit('nonstable_bitcode'):
1482 command += ' --allow-llvm-bitcode-input'
1483 node = env.Command(target=nexe_name, source=[pexe_name],
1484 action=[Action(command, '${TRANSLATECOMSTR}')])
1485 env.Alias('all_programs', node)
1486 assert len(node) == 1, node
1489 pre_base_env.AddMethod(GetTranslatedNexe)
1492 def CommandTestFileDumpCheck(env,
1497 """Create a test that disassembles a binary (|target|) and checks for
1498 patterns in the |check_file|. Disassembly is done using |objdump_flags|.
1501 # Do not try to run OBJDUMP if 'built_elsewhere', since that *might* mean
1502 # that a toolchain is not even present. E.g., the arm hw buildbots do
1503 # not have the pnacl toolchain. We should be able to look for the host
1504 # ARM objdump though... a TODO(jvoung) for when there is time.
1505 if env.Bit('built_elsewhere'):
1507 target = env.GetTranslatedNexe(target)
1508 return env.CommandTestFileCheck(name,
1509 ['${OBJDUMP}', objdump_flags, target],
1512 pre_base_env.AddMethod(CommandTestFileDumpCheck)
1514 def CommandTestFileCheck(env, name, cmd, check_file):
1515 """Create a test that runs a |cmd| (array of strings),
1516 which is expected to print to stdout. The results
1517 of stdout will then be piped to the file_check.py tool which
1518 will search for the regexes specified in |check_file|. """
1520 return env.CommandTest(
1523 env.File('${SCONSTRUCT_DIR}/tools/llvm_file_check_wrapper.py'),
1526 direct_emulation=False)
1528 pre_base_env.AddMethod(CommandTestFileCheck)
1530 def CommandSelLdrTestNacl(env, name, nexe,
1536 # True for *.nexe statically linked with glibc
1538 skip_bootstrap=False,
1539 wrapper_program_prefix=None,
1540 # e.g., [ 'python', 'time_check.py', '--' ]
1542 # Disable all sel_ldr tests for windows under coverage.
1543 # Currently several .S files block sel_ldr from being instrumented.
1544 # See http://code.google.com/p/nativeclient/issues/detail?id=831
1545 if ('TRUSTED_ENV' in env and
1546 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1547 env['TRUSTED_ENV'].Bit('windows')):
1550 # The nexe might be a pexe that needs finalization, and translation.
1551 nexe = env.GetTranslatedNexe(nexe)
1554 if args is not None:
1557 if env.Bit('pnacl_unsandboxed') or (env.Bit('nonsfi_nacl') and
1558 not env.Bit('tests_use_irt')):
1559 # Run unsandboxed executable directly, without sel_ldr.
1560 return env.CommandTest(name, command, size, **extra)
1563 if env.Bit('nonsfi_nacl'):
1564 loader = env.GetNonSfiLoader()
1566 loader = env.GetSelLdr()
1568 print('WARNING: no sel_ldr found. Skipping test %s' % name)
1571 # Avoid problems with [] as default arguments
1572 if sel_ldr_flags is None:
1575 # Avoid modifying original list
1576 sel_ldr_flags = list(sel_ldr_flags)
1578 # Disable the validator if running a GLibC test under Valgrind.
1579 # http://code.google.com/p/nativeclient/issues/detail?id=1799
1580 if env.IsRunningUnderValgrind() and env.Bit('nacl_glibc'):
1581 sel_ldr_flags += ['-cc']
1582 # https://code.google.com/p/nativeclient/issues/detail?id=3158
1583 # We don't currently have valgrind.so for LD_PRELOAD to use. That .so
1584 # is not used for newlib.
1585 # TODO(sehr): add valgrind.so built for NaCl.
1588 # Skip platform qualification checks on configurations with known issues.
1589 if env.GetEmulator() or env.IsRunningUnderValgrind():
1590 sel_ldr_flags += ['-Q']
1592 # Skip validation if we are using the x86-64 zero-based sandbox.
1593 # TODO(arbenson): remove this once the validator supports the x86-64
1594 # zero-based sandbox model.
1595 if env.Bit('x86_64_zero_based_sandbox'):
1596 sel_ldr_flags += ['-c']
1598 # The glibc modifications only make sense for nacl_env tests.
1599 # But this function gets used by some base_env (i.e. src/trusted/...)
1600 # tests too. Don't add the --nacl_glibc changes to the command
1601 # line for those cases.
1602 if env.Bit('nacl_glibc') and env['NACL_BUILD_FAMILY'] != 'TRUSTED':
1603 if not glibc_static and not env.Bit('nacl_static_link'):
1604 # Enable file access so shared libraries can be loaded.
1605 sel_ldr_flags.append('-a')
1606 # Locally-built shared libraries come from ${LIB_DIR} while
1607 # toolchain-provided ones come from ${NACL_SDK_LIB}.
1608 library_path = '${LIB_DIR}:${NACL_SDK_LIB}'
1609 if env.Bit('build_x86'):
1610 # In the old glibc, we run via runnable-ld.so (the dynamic linker).
1611 command = ['${NACL_SDK_LIB}/runnable-ld.so',
1612 '--library-path', library_path] + command
1614 # In the new glibc, we run via elf_loader and direct it where to
1615 # find the dynamic linker in the toolchain.
1616 command = [env.GetElfLoaderNexe(),
1618 os.path.dirname(env.subst('${NACL_SDK_LIB}'))] + command
1619 sel_ldr_flags.extend(['-E', 'LD_LIBRARY_PATH=' + library_path])
1621 # Turn off sandbox for mac so coverage files can be written out.
1622 if ('TRUSTED_ENV' in env and
1623 env['TRUSTED_ENV'].Bit('coverage_enabled') and
1624 env.Bit('host_mac') and
1625 '-a' not in sel_ldr_flags):
1626 sel_ldr_flags += ['-a']
1628 if env.Bit('tests_use_irt'):
1629 sel_ldr_flags += ['-B', nacl_env.GetIrtNexe()]
1632 loader_cmd = [loader]
1634 loader_cmd = env.AddBootstrap(loader, [])
1636 if env.Bit('nonsfi_nacl'):
1637 # nonsfi_loader does not accept the same flags as sel_ldr yet, so
1638 # we ignore sel_ldr_flags here.
1639 command = [loader] + command
1641 command = loader_cmd + sel_ldr_flags + ['--'] + command
1643 if env.Bit('host_linux'):
1644 extra['using_nacl_signal_handler'] = True
1646 if env.ShouldUseVerboseOptions(extra):
1647 env.MakeVerboseExtraOptions(name, log_verbosity, extra)
1649 node = env.CommandTest(name, command, size, posix_path=True,
1650 wrapper_program_prefix=wrapper_program_prefix, **extra)
1651 if env.Bit('tests_use_irt'):
1652 env.Alias('irt_tests', node)
1655 pre_base_env.AddMethod(CommandSelLdrTestNacl)
1658 TEST_EXTRA_ARGS = ['stdin', 'log_file',
1659 'stdout_golden', 'stderr_golden', 'log_golden',
1660 'filter_regex', 'filter_inverse', 'filter_group_only',
1661 'osenv', 'arch', 'subarch', 'exit_status',
1662 'num_runs', 'process_output_single',
1663 'process_output_combined', 'using_nacl_signal_handler',
1664 'declares_exit_status', 'time_warning', 'time_error']
1666 TEST_TIME_THRESHOLD = {
1673 # Valgrind handles SIGSEGV in a way our testing tools do not expect.
1674 UNSUPPORTED_VALGRIND_EXIT_STATUS = ['trusted_sigabrt',
1675 'untrusted_sigill' ,
1676 'untrusted_segfault',
1677 'untrusted_sigsegv_or_equivalent',
1679 'trusted_sigsegv_or_equivalent']
1682 def GetPerfEnvDescription(env):
1683 """Return a string describing architecture, library, etc. options.
1685 This function attempts to gather a string that might inform why a performance
1686 change has occurred.
1688 if env['NACL_BUILD_FAMILY'] == 'TRUSTED':
1689 # Trusted tests do not depend on the untrusted toolchain, untrusted libc,
1690 # whether or not the IRT is used, etc.
1691 description_list = ['trusted',
1692 env['TARGET_PLATFORM'].lower(),
1693 env['TARGET_FULLARCH']]
1694 return ARGUMENTS.get('perf_prefix', '') + '_'.join(description_list)
1695 description_list = [env['TARGET_FULLARCH']]
1696 # Using a list to keep the order consistent.
1697 bit_to_description = [ ('tests_use_irt', ('with_irt', '')),
1698 ('bitcode', ('pnacl', 'nnacl')),
1699 ('translate_fast', ('fast', '')),
1700 ('use_sz', ('sz', '')),
1701 ('nacl_glibc', ('glibc', 'newlib')),
1702 ('nacl_static_link', ('static', 'dynamic')),
1704 for (bit, (descr_yes, descr_no)) in bit_to_description:
1706 additional = descr_yes
1708 additional = descr_no
1710 description_list.append(additional)
1711 return ARGUMENTS.get('perf_prefix', '') + '_'.join(description_list)
1713 pre_base_env.AddMethod(GetPerfEnvDescription)
1718 def GetTestName(target):
1719 key = str(target.path)
1720 return TEST_NAME_MAP.get(key, key)
1722 pre_base_env['GetTestName'] = GetTestName
1725 def SetTestName(node, name):
1726 for target in Flatten(node):
1727 TEST_NAME_MAP[str(target.path)] = name
1730 def ApplyTestWrapperCommand(command_args, extra_deps):
1731 new_args = ARGUMENTS['test_wrapper'].split()
1732 for input_file in extra_deps:
1733 new_args.extend(['-F', input_file])
1734 for arg in command_args:
1735 if isinstance(arg, str):
1736 new_args.extend(['-a', arg])
1738 new_args.extend(['-f', arg])
1742 def CommandTest(env, name, command, size='small', direct_emulation=True,
1743 extra_deps=[], posix_path=False, capture_output=True,
1744 capture_stderr=True, wrapper_program_prefix=None,
1745 scale_timeout=None, **extra):
1746 if not name.endswith('.out') or name.startswith('$'):
1747 raise Exception('ERROR: bad test filename for test output %r' % name)
1749 if env.IsRunningUnderValgrind():
1751 elif env.Bit('asan'):
1752 skip = 'AddressSanitizer'
1755 # Valgrind tends to break crash tests by changing the exit status.
1756 # So far, tests using declares_exit_status are crash tests. If this
1757 # changes, we will have to find a way to make declares_exit_status
1758 # work with Valgrind.
1759 if (skip is not None and
1760 (extra.get('exit_status') in UNSUPPORTED_VALGRIND_EXIT_STATUS or
1761 bool(int(extra.get('declares_exit_status', 0))))):
1762 print('Skipping death test "%s" under %s' % (name, skip))
1766 extra.setdefault('osenv', [])
1767 # Ensure that 'osenv' is a list.
1768 if isinstance(extra['osenv'], str):
1769 extra['osenv'] = [extra['osenv']]
1770 # ASan normally intercepts SIGSEGV and SIGFPE and disables our signal
1771 # handlers, which interferes with various NaCl tests, including the
1772 # platform qualification test built into sel_ldr. We fix this by telling
1773 # ASan not to mess with SIGSEGV and SIGFPE.
1774 asan_options = ['handle_segv=0', 'handle_sigfpe=0']
1775 # ASan aborts on errors rather than exits. This changes the expected exit
1776 # codes for some tests.
1777 asan_options.append('abort_on_error=0')
1779 if env.Bit('host_mac') and int(platform.mac_ver()[0].split('.')[1]) < 7:
1780 # MacOS 10.6 has a bug in the libsandbox system library where it
1781 # makes a memcmp call that reads off the end of a malloc'd block.
1782 # The bug appears to be harmless, but trips an ASan report. So
1783 # tell ASan to suppress memcmp checks.
1784 asan_options.append('strict_memcmp=0')
1785 # TODO(mcgrathr): Remove this when we clean up all the crufty old
1786 # code to be leak-free.
1787 # https://code.google.com/p/nativeclient/issues/detail?id=3874
1788 asan_options.append('detect_leaks=0')
1789 # Note that the ASan runtime doesn't use : specifically as a separator.
1790 # It actually just looks for "foo=" anywhere in the string with strstr,
1791 # so any separator will do. The most obvious choices, ' ', ',', and ';'
1792 # all cause command_tester.py to split things up and get confused.
1793 extra['osenv'].append('ASAN_OPTIONS=' + ':'.join(asan_options))
1795 name = '${TARGET_ROOT}/test_results/' + name
1796 # NOTE: using the long version of 'name' helps distinguish opt vs dbg
1797 max_time = TEST_TIME_THRESHOLD[size]
1798 if 'scale_timeout' in ARGUMENTS:
1799 max_time = max_time * int(ARGUMENTS['scale_timeout'])
1801 max_time = max_time * scale_timeout
1803 if env.Bit('nacl_glibc'):
1804 suite = 'nacl_glibc'
1806 suite = 'nacl_newlib'
1807 if env.Bit('bitcode'):
1810 script_flags = ['--name', '%s.${GetTestName(TARGET)}' % suite,
1811 '--time_warning', str(max_time),
1812 '--time_error', str(10 * max_time),
1815 run_under = ARGUMENTS.get('run_under')
1817 run_under_extra_args = ARGUMENTS.get('run_under_extra_args')
1818 if run_under_extra_args:
1819 run_under = run_under + ',' + run_under_extra_args
1820 script_flags.append('--run_under')
1821 script_flags.append(run_under)
1823 emulator = env.GetEmulator()
1824 if emulator and direct_emulation:
1825 command = [emulator] + command
1827 # test wrapper should go outside of emulators like qemu, since the
1828 # test wrapper code is not emulated.
1829 if wrapper_program_prefix is not None:
1830 command = wrapper_program_prefix + command
1832 script_flags.append('--perf_env_description')
1833 script_flags.append(env.GetPerfEnvDescription())
1835 # Add architecture info.
1836 extra['arch'] = env['BUILD_ARCHITECTURE']
1837 extra['subarch'] = env['BUILD_SUBARCH']
1839 for flag_name, flag_value in extra.items():
1840 assert flag_name in TEST_EXTRA_ARGS, repr(flag_name)
1841 if isinstance(flag_value, list):
1842 # Options to command_tester.py which are actually lists must not be
1843 # separated by whitespace. This stringifies the lists with a separator
1844 # char to satisfy command_tester.
1845 flag_value = command_tester.StringifyList(flag_value)
1846 # do not add --flag + |flag_name| |flag_value| if
1847 # |flag_value| is false (empty).
1849 script_flags.append('--' + flag_name)
1850 # Make sure flag values are strings (or SCons objects) when building
1851 # up the command. Right now, this only means convert ints to strings.
1852 if isinstance(flag_value, int):
1853 flag_value = str(flag_value)
1854 script_flags.append(flag_value)
1857 if not capture_output:
1858 script_flags.extend(['--capture_output', '0'])
1859 if not capture_stderr:
1860 script_flags.extend(['--capture_stderr', '0'])
1862 # Set command_tester.py's output filename. We skip this when using
1863 # test_wrapper because the run_test_via_ssh.py wrapper does not have
1864 # the ability to copy result files back from the remote host.
1865 if 'test_wrapper' not in ARGUMENTS:
1866 script_flags.extend(['--output_stamp', name])
1868 test_script = env.File('${SCONSTRUCT_DIR}/tools/command_tester.py')
1869 extra_deps = extra_deps + [env.File('${SCONSTRUCT_DIR}/tools/test_lib.py')]
1870 command = ['${PYTHON}', test_script] + script_flags + command
1871 if 'test_wrapper' in ARGUMENTS:
1872 command = ApplyTestWrapperCommand(command, extra_deps)
1873 return env.AutoDepsCommand(name, command,
1874 extra_deps=extra_deps, posix_path=posix_path,
1875 disabled=env.Bit('do_not_run_tests'))
1877 pre_base_env.AddMethod(CommandTest)
1880 def FileSizeTest(env, name, envFile, max_size=None):
1881 """FileSizeTest() returns a scons node like the other XYZTest generators.
1882 It logs the file size of envFile in a perf-buildbot-recognizable format.
1883 Optionally, it can cause a test failure if the file is larger than max_size.
1885 def doSizeCheck(target, source, env):
1886 filepath = source[0].abspath
1887 actual_size = os.stat(filepath).st_size
1888 command_tester.LogPerfResult(name,
1889 env.GetPerfEnvDescription(),
1890 '%.3f' % (actual_size / 1024.0),
1892 # Also get zipped size.
1893 nexe_file = open(filepath, 'rb')
1894 zipped_size = len(zlib.compress(nexe_file.read()))
1896 command_tester.LogPerfResult(name,
1897 'ZIPPED_' + env.GetPerfEnvDescription(),
1898 '%.3f' % (zipped_size / 1024.0),
1900 # Finally, do the size check.
1901 if max_size is not None and actual_size > max_size:
1902 # NOTE: this exception only triggers a failure for this particular test,
1903 # just like any other test failure.
1904 raise Exception("File %s larger than expected: expected up to %i, got %i"
1905 % (filepath, max_size, actual_size))
1906 # If 'built_elsewhere', the file should should have already been built.
1907 # Do not try to built it and/or its pieces.
1908 if env.Bit('built_elsewhere'):
1909 env.Ignore(name, envFile)
1910 return env.Command(name, envFile, doSizeCheck)
1912 pre_base_env.AddMethod(FileSizeTest)
1914 def StripExecutable(env, name, exe):
1915 """StripExecutable returns a node representing the stripped version of |exe|.
1916 The stripped version will be given the basename |name|.
1917 NOTE: for now this only works with the untrusted toolchain.
1918 STRIP does not appear to be a first-class citizen in SCons and
1919 STRIP has only been set to point at the untrusted toolchain.
1924 action=[Action('${STRIPCOM} ${SOURCES} -o ${TARGET}', '${STRIPCOMSTR}')])
1926 pre_base_env.AddMethod(StripExecutable)
1929 # TODO(ncbray): pretty up the log output when running this builder.
1930 def DisabledCommand(target, source, env):
1933 pre_base_env['BUILDERS']['DisabledCommand'] = Builder(action=DisabledCommand)
1936 def AutoDepsCommand(env, name, command, extra_deps=[], posix_path=False,
1938 """AutoDepsCommand() takes a command as an array of arguments. Each
1939 argument may either be:
1942 * a Scons file object, e.g. one created with env.File() or as the
1943 result of another build target.
1945 In the second case, the file is automatically declared as a
1946 dependency of this command.
1948 command = list(command)
1950 for index, arg in enumerate(command):
1951 if not isinstance(arg, str):
1952 if len(Flatten(arg)) != 1:
1953 # Do not allow this, because it would cause "deps" to get out
1954 # of sync with the indexes in "command".
1955 # See http://code.google.com/p/nativeclient/issues/detail?id=1086
1956 raise AssertionError('Argument to AutoDepsCommand() actually contains '
1957 'multiple (or zero) arguments: %r' % arg)
1959 command[index] = '${SOURCES[%d].posix}' % len(deps)
1961 command[index] = '${SOURCES[%d].abspath}' % len(deps)
1964 # If built_elsewhere, build commands are replaced by no-ops, so make sure
1965 # the targets don't get removed first
1966 if env.Bit('built_elsewhere'):
1968 env.Depends(name, extra_deps)
1971 return env.DisabledCommand(name, deps)
1973 return env.Command(name, deps, ' '.join(command))
1976 pre_base_env.AddMethod(AutoDepsCommand)
1979 def GetPrintableCommandName(cmd):
1980 """Look at the first few elements of cmd to derive a suitable command name."""
1981 cmd_tokens = cmd.split()
1982 if "python" in cmd_tokens[0] and len(cmd_tokens) >= 2:
1983 cmd_name = cmd_tokens[1]
1985 cmd_name = cmd_tokens[0].split('(')[0]
1987 # undo some pretty printing damage done by hammer
1988 cmd_name = cmd_name.replace('________','')
1989 # use file name part of a path
1990 return cmd_name.split('/')[-1]
1993 def GetPrintableEnvironmentName(env):
1994 # use file name part of a obj root path as env name
1995 return env.subst('${TARGET_ROOT}').split('/')[-1]
1997 pre_base_env.AddMethod(GetPrintableEnvironmentName)
2000 def CustomCommandPrinter(cmd, targets, source, env):
2001 # Abuse the print hook to count the commands that are executed
2002 if env.Bit('target_stats'):
2003 cmd_name = GetPrintableCommandName(cmd)
2004 env_name = env.GetPrintableEnvironmentName()
2005 CMD_COUNTER[cmd_name] = CMD_COUNTER.get(cmd_name, 0) + 1
2006 ENV_COUNTER[env_name] = ENV_COUNTER.get(env_name, 0) + 1
2009 # Our pretty printer
2011 cmd_name = GetPrintableCommandName(cmd)
2012 env_name = env.GetPrintableEnvironmentName()
2013 sys.stdout.write('[%s] [%s] %s\n' % (cmd_name, env_name,
2014 targets[0].get_path()))
2016 # The SCons default (copied from print_cmd_line in Action.py)
2017 sys.stdout.write(cmd + u'\n')
2019 if 'generate_ninja' not in ARGUMENTS:
2020 pre_base_env.Append(PRINT_CMD_LINE_FUNC=CustomCommandPrinter)
2023 def GetAbsDirArg(env, argument, target):
2024 """Fetch the named command-line argument and turn it into an absolute
2025 directory name. If the argument is missing, raise a UserError saying
2026 that the given target requires that argument be given."""
2027 dir = ARGUMENTS.get(argument)
2029 raise UserError('%s must be set when invoking %s' % (argument, target))
2030 return os.path.join(env.Dir('$MAIN_DIR').abspath, dir)
2032 pre_base_env.AddMethod(GetAbsDirArg)
2035 def MakeGTestEnv(env):
2036 # Create an environment to run unit tests using Gtest.
2037 gtest_env = env.Clone()
2039 if gtest_env['NACL_BUILD_FAMILY'] != 'TRUSTED' or not gtest_env.Bit('mac'):
2040 # This became necessary for the arm cross TC v4.6 but probable applies
2041 # to all new gcc TCs. MacOS does not have this switch.
2042 gtest_env.Append(LINKFLAGS=['-pthread'])
2044 # Define compile-time flag that communicates that we are compiling in the test
2045 # environment (rather than for the TCB).
2046 if gtest_env['NACL_BUILD_FAMILY'] == 'TRUSTED':
2047 gtest_env.Append(CCFLAGS=['-DNACL_TRUSTED_BUT_NOT_TCB'])
2049 # This is necessary for unittest_main.c which includes gtest/gtest.h
2050 # The problem is that gtest.h includes other files expecting the
2051 # include path to be set.
2052 gtest_env.Prepend(CPPPATH=['${SOURCE_ROOT}/testing/gtest/include'])
2054 # gtest does not compile with our stringent settings.
2055 if gtest_env.Bit('linux') or gtest_env.Bit('mac'):
2056 # "-pedantic" is because of: gtest-typed-test.h:236:46: error:
2057 # anonymous variadic macros were introduced in C99
2058 # Also, gtest does not compile successfully with "-Wundef".
2059 gtest_env.FilterOut(CCFLAGS=['-pedantic', '-Wundef'])
2060 gtest_env.FilterOut(CXXFLAGS=['-fno-rtti', '-Weffc++'])
2062 # gtest is incompatible with static linking due to obscure libstdc++
2063 # linking interactions.
2064 # See http://code.google.com/p/nativeclient/issues/detail?id=1987
2065 gtest_env.FilterOut(LINKFLAGS=['-static'])
2067 gtest_env.Prepend(LIBS=['gtest'])
2070 pre_base_env.AddMethod(MakeGTestEnv)
2072 def MakeUntrustedNativeEnv(env):
2073 native_env = nacl_env.Clone()
2074 if native_env.Bit('bitcode') and not native_env.Bit('build_mips32'):
2075 native_env = native_env.PNaClGetNNaClEnv()
2078 pre_base_env.AddMethod(MakeUntrustedNativeEnv)
2080 def MakeBaseTrustedEnv(platform=None):
2081 base_env = MakeArchSpecificEnv(platform)
2083 IS_BUILD_ENV = False,
2090 EXTRA_CXXFLAGS = [],
2092 CFLAGS = ['${EXTRA_CFLAGS}'],
2093 CXXFLAGS = ['${EXTRA_CXXFLAGS}'],
2095 if base_env.Bit('ncval_testing'):
2096 base_env.Append(CPPDEFINES = ['NCVAL_TESTING'])
2098 base_env.Append(BUILD_SCONSCRIPTS = [
2099 # KEEP THIS SORTED PLEASE
2100 'build/package_version/build.scons',
2101 'pynacl/build.scons',
2102 'src/nonsfi/irt/build.scons',
2103 'src/nonsfi/loader/build.scons',
2104 'src/shared/gio/build.scons',
2105 'src/shared/imc/build.scons',
2106 'src/shared/platform/build.scons',
2107 'src/third_party/gtest/build.scons',
2108 'src/trusted/cpu_features/build.scons',
2109 'src/trusted/debug_stub/build.scons',
2110 'src/trusted/desc/build.scons',
2111 'src/trusted/fault_injection/build.scons',
2112 'src/trusted/interval_multiset/build.scons',
2113 'src/trusted/nacl_base/build.scons',
2114 'src/trusted/perf_counter/build.scons',
2115 'src/trusted/platform_qualify/build.scons',
2116 'src/trusted/seccomp_bpf/build.scons',
2117 'src/trusted/service_runtime/build.scons',
2118 'src/trusted/validator/build.scons',
2119 'src/trusted/validator/driver/build.scons',
2120 'src/trusted/validator_arm/build.scons',
2121 'src/trusted/validator_ragel/build.scons',
2122 'src/trusted/validator_x86/build.scons',
2123 'tests/common/build.scons',
2124 'tests/lock_manager/build.scons',
2125 'tests/performance/build.scons',
2126 'tests/python_version/build.scons',
2127 'tests/sel_ldr_seccomp/build.scons',
2128 'tests/tools/build.scons',
2129 'tests/unittests/shared/imc/build.scons',
2130 'tests/unittests/shared/platform/build.scons',
2131 'tests/unittests/trusted/asan/build.scons',
2132 'tests/unittests/trusted/bits/build.scons',
2133 'tests/unittests/trusted/platform_qualify/build.scons',
2134 'tests/unittests/trusted/service_runtime/build.scons',
2135 'toolchain_build/build.scons',
2138 base_env.AddMethod(SDKInstallBin)
2140 # The ARM and MIPS validators can be built for any target that doesn't use
2142 if not base_env.Bit('build_x86_64'):
2144 BUILD_SCONSCRIPTS = [
2145 'src/trusted/validator_mips/build.scons',
2148 base_env.AddChromeFilesFromGroup('trusted_scons_files')
2151 NACL_BUILD_FAMILY = 'TRUSTED',
2154 # Add optional scons files if present in the directory tree.
2155 if os.path.exists(pre_base_env.subst('${MAIN_DIR}/supplement/build.scons')):
2156 base_env.Append(BUILD_SCONSCRIPTS=['${MAIN_DIR}/supplement/build.scons'])
2161 # Select tests to run under coverage build.
2162 pre_base_env['COVERAGE_TARGETS'] = [
2163 'small_tests', 'medium_tests', 'large_tests',
2164 'chrome_browser_tests']
2167 pre_base_env.Help("""\
2168 ======================================================================
2170 ======================================================================
2175 * cleaning: scons -c
2177 * smoke test: scons --mode=nacl,opt-linux -k pp=1 smoke_tests
2179 * sel_ldr: scons --mode=opt-linux sel_ldr
2181 Targets to build trusted code destined for the SDK:
2182 * build trusted-code tools: scons build_bin
2183 * install trusted-code tools: scons install_bin bindir=...
2184 * These default to opt build, or add --mode=dbg-host for debug build.
2186 Targets to build untrusted code destined for the SDK:
2187 * build just libraries: scons build_lib
2188 * install just headers: scons install_headers includedir=...
2189 * install just libraries: scons install_lib libdir=...
2190 * install headers and libraries:scons install includedir=... libdir=...
2192 * dump system info: scons --mode=nacl,opt-linux dummy
2197 --prebuilt Do not build things, just do install steps
2199 --verbose Full command line logging before command execution
2201 pp=1 Use command line pretty printing (more concise output)
2203 sysinfo=1 Verbose system info printing
2205 naclsdk_validate=0 Suppress presence check of sdk
2209 Automagically generated help:
2210 -----------------------------
2214 def SetUpClang(env):
2215 env['CLANG_DIR'] = '${SOURCE_ROOT}/third_party/llvm-build/Release+Asserts/bin'
2216 env['CLANG_OPTS'] = []
2218 if not (env.Bit('host_linux') or env.Bit('host_mac')):
2219 raise UserError("ERROR: ASan is only available for Linux and Mac")
2220 env.Append(CLANG_OPTS=['-fsanitize=address',
2221 '-gline-tables-only',
2222 '-fno-omit-frame-pointer',
2223 '-DADDRESS_SANITIZER'])
2224 if env.Bit('host_mac'):
2225 # The built executables will try to find this library at runtime
2226 # in the directory containing the executable itself. In the
2227 # Chromium build, the library just gets copied into that
2228 # directory. Here, there isn't a single directory from which
2229 # all the test binaries are run (sel_ldr is run from staging/
2230 # but other trusted test binaries are run from their respective
2231 # obj/.../ directories). So instead just point the dynamic linker
2232 # at the right directory using an environment variable.
2233 # Be sure to check and update clang_lib_version whenever updating
2234 # tools/clang revs in DEPS.
2235 clang_lib_version = '4.0.0'
2236 clang_lib_dir = str(env.Dir('${CLANG_DIR}/../lib/clang/%s/lib/darwin' %
2237 clang_lib_version).abspath)
2238 env['ENV']['DYLD_LIBRARY_PATH'] = clang_lib_dir
2239 if 'PROPAGATE_ENV' not in env:
2240 env['PROPAGATE_ENV'] = []
2241 env['PROPAGATE_ENV'].append('DYLD_LIBRARY_PATH')
2244 if not env.Bit('host_linux') or not env.Bit('build_x86_64'):
2245 raise UserError('ERROR: MSan is only available for x86-64 Linux')
2246 track_origins = ARGUMENTS.get('msan_track_origins', '1')
2247 env.Append(CLANG_OPTS=['-fsanitize=memory',
2248 '-fsanitize-memory-track-origins=%s' % track_origins,
2249 '-gline-tables-only',
2250 '-fno-omit-frame-pointer',
2251 '-DMEMORY_SANITIZER'])
2253 env['CC'] = '${CLANG_DIR}/clang ${CLANG_OPTS}'
2254 env['CXX'] = '${CLANG_DIR}/clang++ ${CLANG_OPTS}'
2255 # Make sure we find Clang-supplied libraries like -lprofile_rt
2256 # in the Clang build we use, rather than from the system.
2257 # The system-installed versions go with the system-installed Clang
2258 # and might not be compatible with the Clang we're running.
2259 env.Append(LIBPATH=['${CLANG_DIR}/../lib'])
2261 def GenerateOptimizationLevels(env):
2262 if env.Bit('clang') and not env.Bit('built_elsewhere'):
2265 # Generate debug variant.
2266 debug_env = env.Clone(tools = ['target_debug'])
2267 debug_env['OPTIMIZATION_LEVEL'] = 'dbg'
2268 debug_env['BUILD_TYPE'] = debug_env.subst('$BUILD_TYPE')
2269 debug_env['BUILD_DESCRIPTION'] = debug_env.subst('$BUILD_DESCRIPTION')
2270 AddDualLibrary(debug_env)
2271 # Add to the list of fully described environments.
2272 environment_list.append(debug_env)
2274 # Generate opt variant.
2275 opt_env = env.Clone(tools = ['target_optimized'])
2276 opt_env['OPTIMIZATION_LEVEL'] = 'opt'
2277 opt_env['BUILD_TYPE'] = opt_env.subst('$BUILD_TYPE')
2278 opt_env['BUILD_DESCRIPTION'] = opt_env.subst('$BUILD_DESCRIPTION')
2279 AddDualLibrary(opt_env)
2280 # Add to the list of fully described environments.
2281 environment_list.append(opt_env)
2283 return (debug_env, opt_env)
2286 def SDKInstallBin(env, name, node, target=None):
2287 """Add the given node to the build_bin and install_bin targets.
2288 It will be installed under the given name with the build target appended.
2289 The optional target argument overrides the setting of what that target is."""
2290 env.Alias('build_bin', node)
2291 if 'install_bin' in COMMAND_LINE_TARGETS:
2292 dir = env.GetAbsDirArg('bindir', 'install_bin')
2294 target = env['TARGET_FULLARCH'].replace('-', '_')
2295 file_name, file_ext = os.path.splitext(name)
2296 output_name = file_name + '_' + target + file_ext
2297 install_node = env.InstallAs(os.path.join(dir, output_name), node)
2298 env.Alias('install_bin', install_node)
2301 def MakeWindowsEnv(platform=None):
2302 base_env = MakeBaseTrustedEnv(platform)
2303 windows_env = base_env.Clone(
2304 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-win',
2305 BUILD_TYPE_DESCRIPTION = 'Windows ${OPTIMIZATION_LEVEL} build',
2306 tools = ['target_platform_windows'],
2307 # Windows /SAFESEH linking requires either an .sxdata section be
2308 # present or that @feat.00 be defined as a local, absolute symbol
2309 # with an odd value.
2310 ASCOM = ('$ASPPCOM /E /D__ASSEMBLER__ | '
2311 '$WINASM -defsym @feat.00=1 -o $TARGET'),
2312 PDB = '${TARGET.base}.pdb',
2313 # Strict doesn't currently work for Windows since some of the system
2314 # libraries like wsock32 are magical.
2315 LIBS_STRICT = False,
2316 TARGET_ARCH='x86_64' if base_env.Bit('build_x86_64') else 'x86',
2321 ['_WIN32_WINNT', '0x0501'],
2322 ['__STDC_LIMIT_MACROS', '1'],
2324 # WIN32 is used by ppapi
2326 # WIN32_LEAN_AND_MEAN tells windows.h to omit obsolete and rarely
2327 # used #include files. This allows use of Winsock 2.0 which otherwise
2328 # would conflict with Winsock 1.x included by windows.h.
2329 ['WIN32_LEAN_AND_MEAN', ''],
2331 LIBS = ['ws2_32', 'advapi32'],
2332 # TODO(bsy) remove 4355 once cross-repo
2333 # NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
2334 CCFLAGS = ['/EHsc', '/WX', '/wd4355', '/wd4800']
2337 # This linker option allows us to ensure our builds are compatible with
2338 # Chromium, which uses it.
2339 if windows_env.Bit('build_x86_32'):
2340 windows_env.Append(LINKFLAGS = "/safeseh")
2342 # We use the GNU assembler (gas) on Windows so that we can use the
2343 # same .S assembly files on all platforms. Microsoft's assembler uses
2344 # a completely different syntax for x86 code.
2345 if windows_env.Bit('build_x86_64'):
2346 # This assembler only works for x86-64 code.
2347 windows_env['WINASM'] = \
2348 windows_env.File('$SOURCE_ROOT/third_party/mingw-w64/mingw/bin/'
2349 'x86_64-w64-mingw32-as.exe').abspath
2351 # This assembler only works for x86-32 code.
2352 windows_env['WINASM'] = \
2353 windows_env.File('$SOURCE_ROOT/third_party/gnu_binutils/files/'
2358 windows_optimized_env) = GenerateOptimizationLevels(MakeWindowsEnv())
2360 def MakeUnixLikeEnv(platform=None):
2361 unix_like_env = MakeBaseTrustedEnv(platform)
2362 # -Wdeclaration-after-statement is desirable because MS studio does
2363 # not allow declarations after statements in a block, and since much
2364 # of our code is portable and primarily initially tested on Linux,
2365 # it'd be nice to get the build error earlier rather than later
2366 # (building and testing on Linux is faster).
2367 # TODO(nfullagar): should we consider switching to -std=c99 ?
2368 unix_like_env.Prepend(
2371 '-Wdeclaration-after-statement',
2372 # Require defining functions as "foo(void)" rather than
2373 # "foo()" because, in C (but not C++), the latter defines a
2374 # function with unspecified arguments rather than no
2376 '-Wstrict-prototypes',
2387 '-fdiagnostics-show-option',
2388 '-fvisibility=hidden',
2389 '-fstack-protector',
2391 # NOTE: pthread is only neeeded for libppNaClPlugin.so and on arm
2393 CPPDEFINES = [['__STDC_LIMIT_MACROS', '1'],
2394 ['__STDC_FORMAT_MACROS', '1'],
2397 # Android's stlport uses __STRICT_ANSI__ to exclude "long long".
2398 # This breaks basically all C++ code that uses stlport.
2399 if not unix_like_env.Bit('android'):
2400 unix_like_env.Prepend(CXXFLAGS=['-std=c++98'])
2402 if not unix_like_env.Bit('clang'):
2403 unix_like_env.Append(CCFLAGS=['--param', 'ssp-buffer-size=4'])
2405 if unix_like_env.Bit('werror'):
2406 unix_like_env.Append(LINKFLAGS=['-Werror'])
2408 return unix_like_env
2411 def MakeMacEnv(platform=None):
2412 mac_env = MakeUnixLikeEnv(platform).Clone(
2413 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-mac',
2414 BUILD_TYPE_DESCRIPTION = 'MacOS ${OPTIMIZATION_LEVEL} build',
2415 tools = ['target_platform_mac'],
2416 # TODO(bradnelson): this should really be able to live in unix_like_env
2417 # but can't due to what the target_platform_x module is
2420 PLUGIN_SUFFIX = '.bundle',
2422 # On Mac, only the newer clang toolchains can parse some of the trusted
2423 # code's assembly syntax, so turn clang on by default.
2424 mac_env.SetBits('clang')
2426 # For no good reason, this all gets instantiated on every platform,
2427 # and then only actually used on Mac. But the find_sdk.py script
2428 # will barf if run on a non-Mac.
2429 if pynacl.platform.IsMac():
2430 # mac_sdk_min must be kept in synch with mac_sdk_min in
2431 # chromium/src/build/config/mac/mac_sdk.gni.
2432 mac_sdk_min = '10.10'
2433 # Find the Mac SDK to use as sysroot.
2434 # This invocation matches the model in //build/config/mac/mac_sdk.gni.
2435 mac_sdk_sysroot, mac_sdk_version = subprocess.check_output([
2437 os.path.join(os.path.pardir, 'build', 'mac', 'find_sdk.py'),
2440 ], encoding='utf-8').splitlines()
2442 mac_sdk_sysroot = 'ThisIsNotAMac'
2444 # This should be kept in synch with mac_deployment_target
2445 # in build/common.gypi, which in turn should be kept in synch
2446 # with chromium/src/build/common.gypi.
2447 mac_deployment_target = '10.6'
2449 sdk_flags = ['-isysroot', mac_sdk_sysroot,
2450 '-mmacosx-version-min=' + mac_deployment_target]
2451 mac_env.Append(CCFLAGS=sdk_flags, ASFLAGS=sdk_flags, LINKFLAGS=sdk_flags)
2453 subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
2455 # '-Wno-gnu' is required for the statement expression defining dirfd
2456 # for OSX -- otherwise, a warning is generated.
2457 CCFLAGS=[subarch_flag, '-fPIC', '-Wno-gnu'],
2458 CXXFLAGS=['-stdlib=libc++'],
2459 ASFLAGS=[subarch_flag],
2460 LINKFLAGS=[subarch_flag, '-fPIC', '-stdlib=libc++'],
2461 CPPDEFINES = [# defining _DARWIN_C_SOURCE breaks 10.4
2462 #['_DARWIN_C_SOURCE', '1'],
2463 #['__STDC_LIMIT_MACROS', '1']
2469 (mac_debug_env, mac_optimized_env) = GenerateOptimizationLevels(MakeMacEnv())
2472 def which(cmd, paths=os.environ.get('PATH', '').split(os.pathsep)):
2474 if os.access(os.path.join(p, cmd), os.X_OK):
2479 def SetUpLinuxEnvArm(env):
2480 jail = env.GetToolchainDir(toolchain_name='arm_trusted')
2481 if not platform.machine().startswith('arm'):
2482 # Allow emulation on non-ARM hosts.
2483 env.Replace(EMULATOR=jail + '/run_under_qemu_arm')
2484 if env.Bit('built_elsewhere'):
2485 def FakeInstall(dest, source, env):
2486 print('Not installing', dest)
2487 # Replace build commands with no-ops
2488 env.Replace(CC='true', CXX='true', LD='true',
2489 AR='true', RANLIB='true', INSTALL=FakeInstall)
2491 sysroot=os.path.join(
2492 '${SOURCE_ROOT}/build/linux/debian_bullseye_arm-sysroot')
2493 env.Prepend(CCFLAGS=['--sysroot='+sysroot],
2495 # The -rpath-link argument is needed on Ubuntu/Precise to
2496 # avoid linker warnings about missing ld.linux.so.3.
2497 # TODO(sbc): remove this once we stop supporting Precise
2498 # as a build environment.
2499 LINKFLAGS=['-fuse-ld=lld',
2500 '--sysroot='+sysroot]
2502 # Note we let the compiler choose whether it's -marm or -mthumb by
2503 # default. The hope is this will have the best chance of testing
2504 # the prevailing compilation mode used for Chromium et al.
2505 # TODO(dschuff): gn seems to use mthumb, try changing later
2506 if env.Bit('clang'):
2507 env.Prepend(CCFLAGS=['--target=arm-linux-gnueabihf'])
2508 env.Prepend(LINKFLAGS=['--target=arm-linux-gnueabihf'])
2510 env.Replace(CC='arm-linux-gnueabihf-gcc',
2511 CXX='arm-linux-gnueabihf-g++',
2512 LD='arm-linux-gnueabihf-ld')
2513 env.Prepend(CCFLAGS=['-march=armv7-a','-mfloat-abi=hard',
2514 '-mtune=generic-armv7-a', '-mfpu=neon'])
2516 # get_plugin_dirname.cc has a dependency on dladdr
2517 env.Append(LIBS=['dl'])
2519 def SetUpAndroidEnv(env):
2520 env.FilterOut(CPPDEFINES=[['_LARGEFILE64_SOURCE', '1']])
2521 android_ndk_root = os.path.join('${SOURCE_ROOT}', 'third_party',
2523 android_ndk_experimental_root = os.path.join('${SOURCE_ROOT}',
2524 'third_party', 'android_tools',
2526 android_sdk_root = os.path.join('${SOURCE_ROOT}', 'third_party',
2527 'android_sdk', 'public')
2528 android_sdk_version = 21
2529 android_stlport_root = os.path.join(android_ndk_root, 'sources', 'cxx-stl',
2532 pynacl.platform.OS_WIN : 'win',
2533 pynacl.platform.OS_MAC: 'darwin',
2534 pynacl.platform.OS_LINUX : 'linux'
2536 host_os = ndk_host_os_map[pynacl.platform.GetOS()]
2537 android_sdk = os.path.join(android_sdk_root, 'platforms',
2538 'android-%s' % android_sdk_version)
2540 if env.Bit('build_arm'):
2541 android_ndk_target_prefix = 'arm-linux-androideabi'
2542 android_ndk_version = '4.8'
2543 android_app_abi = 'armeabi-v7a'
2544 android_ndk_sysroot = os.path.join(android_ndk_root, 'platforms',
2545 'android-14', 'arch-arm')
2546 android_ndk_lib_dir = os.path.join('usr', 'lib')
2547 android_toolchain = os.path.join(android_ndk_root, 'toolchains',
2548 'arm-linux-androideabi-4.8', 'prebuilt',
2549 '%s-x86_64' % host_os, 'bin')
2550 arch_cflags += ['-march=armv7-a', '-mfloat-abi=softfp']
2551 elif env.Bit('build_x86_32'):
2552 android_ndk_target_prefix = 'i686-linux-android'
2553 android_ndk_version = '4.8'
2554 android_app_abi = 'x86'
2555 android_ndk_sysroot = os.path.join(android_ndk_root, 'platforms',
2556 'android-14', 'arch-x86')
2557 android_ndk_lib_dir = os.path.join('usr', 'lib')
2558 android_toolchain = os.path.join(android_ndk_root, 'toolchains',
2559 'x86-4.8', 'prebuilt',
2560 '%s-x86_64' % host_os, 'bin')
2561 arch_cflags += ['-m32', '-msse2']
2562 # TODO(sehr): add other android architecture platform settings here.
2563 android_ndk_include = os.path.join(android_ndk_sysroot, 'usr', 'include')
2564 android_ndk_lib = os.path.join(android_ndk_sysroot, android_ndk_lib_dir)
2565 android_sdk_jar = os.path.join(android_sdk, 'android.jar')
2566 android_stlport_include = os.path.join(android_stlport_root, 'stlport')
2567 android_stlport_libs_dir = os.path.join(android_stlport_root, 'libs',
2569 android_ndk_libgcc_path = os.path.join(android_toolchain, '..', 'lib', 'gcc',
2570 android_ndk_target_prefix,
2571 android_ndk_version)
2572 env.Replace(CC=os.path.join(android_toolchain,
2573 '%s-gcc' % android_ndk_target_prefix),
2574 CXX=os.path.join(android_toolchain,
2575 '%s-g++' % android_ndk_target_prefix),
2576 LD=os.path.join(android_toolchain,
2577 '%s-g++' % android_ndk_target_prefix),
2578 AR=os.path.join(android_toolchain,
2579 '%s-ar' % android_ndk_target_prefix),
2580 RANLIB=os.path.join(android_toolchain,
2581 '%s-ranlib' % android_ndk_target_prefix),
2582 READELF=os.path.join(android_toolchain,
2583 '%s-readelf' % android_ndk_target_prefix),
2584 STRIP=os.path.join(android_toolchain,
2585 '%s-strip' % android_ndk_target_prefix),
2586 EMULATOR=os.path.join(android_sdk_root, 'tools', 'emulator'),
2587 LIBPATH=['${LIB_DIR}',
2589 android_ndk_libgcc_path,
2590 os.path.join(android_stlport_root, 'libs',
2593 LIBS=['stlport_shared',
2600 # SHLINKFLAGS should not inherit options from LINKFLAGS.
2601 env.FilterOut(SHLINKFLAGS=['$LINKFLAGS'])
2602 env.Append(CCFLAGS=['--sysroot=' + android_ndk_sysroot,
2603 '-isystem=' + os.path.join(android_ndk_sysroot, 'usr',
2605 '-I%s' % android_stlport_include,
2606 '-ffunction-sections',
2608 '-fstack-protector',
2610 '-finline-limit=64',
2611 '-Wa,--noexecstack',
2614 # Due to bogus warnings on uintptr_t formats.
2617 CXXFLAGS=['-I%s' % android_stlport_include,
2618 '-I%s' % android_ndk_include,
2621 LINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2623 '-Wl,--no-undefined',
2624 # Don't export symbols from statically linked libraries.
2625 '-Wl,--exclude-libs=ALL',
2626 # crtbegin_dynamic.o should be the last item in ldflags.
2627 os.path.join(android_ndk_lib, 'crtbegin_dynamic.o'),
2629 LINKCOM=' $ANDROID_EXTRA_LIBS',
2630 ANDROID_EXTRA_LIBS=os.path.join(android_ndk_lib,
2631 'crtend_android.o'),
2632 SHLINKFLAGS=['--sysroot=' + android_ndk_sysroot,
2634 # crtbegin_so.o should be the last item in ldflags.
2635 os.path.join(android_ndk_lib, 'crtbegin_so.o'),
2637 SHLINKCOM=' $ANDROID_EXTRA_SHLIBS',
2638 ANDROID_EXTRA_SHLIBS=os.path.join(android_ndk_lib,
2643 def SetUpLinuxEnvMips(env):
2644 jail = env.GetToolchainDir(toolchain_name='mips_trusted')
2645 if not platform.machine().startswith('mips'):
2646 # Allow emulation on non-MIPS hosts.
2647 env.Replace(EMULATOR=jail + '/run_under_qemu_mips32')
2648 if env.Bit('built_elsewhere'):
2649 def FakeInstall(dest, source, env):
2650 print('Not installing', dest)
2651 # Replace build commands with no-ops
2652 env.Replace(CC='true', CXX='true', LD='true',
2653 AR='true', RANLIB='true', INSTALL=FakeInstall)
2655 tc_dir = os.path.join(jail, 'bin')
2656 if not which(os.path.join(tc_dir, 'mipsel-linux-gnu-gcc')):
2658 "MIPS trusted toolchain not found - try running:\n"
2659 " build/package_version/package_version.py --packages"
2660 " linux_x86/mips_trusted sync -x\n"
2661 "Or build it yourself with:\n"
2662 " tools/trusted_cross_toolchains/trusted-toolchain-creator"
2663 ".mipsel.debian.sh nacl_sdk")
2664 env.Replace(CC=os.path.join(tc_dir, 'mipsel-linux-gnu-gcc'),
2665 CXX=os.path.join(tc_dir, 'mipsel-linux-gnu-g++'),
2666 LD=os.path.join(tc_dir, 'mipsel-linux-gnu-ld'),
2668 LIBPATH=['${LIB_DIR}',
2669 jail + '/sysroot/usr/lib']
2672 env.Append(LIBS=['rt', 'dl', 'pthread'],
2673 CCFLAGS=['-march=mips32r2'])
2675 # Makes a generic Linux development environment.
2676 # Linux development environments are used in two different ways.
2677 # 1) To produce trusted tools (e.g., sel_ldr), called TRUSTED_ENV
2678 # 2) To produce build tools (e.g., tls_edit), called BUILD_ENV
2679 def MakeGenericLinuxEnv(platform=None):
2680 linux_env = MakeUnixLikeEnv(platform).Clone(
2681 BUILD_TYPE = '${OPTIMIZATION_LEVEL}-linux',
2682 BUILD_TYPE_DESCRIPTION = 'Linux ${OPTIMIZATION_LEVEL} build',
2683 tools = ['target_platform_linux'],
2684 # TODO(bradnelson): this should really be able to live in unix_like_env
2685 # but can't due to what the target_platform_x module is
2690 # Prepend so we can disable warnings via Append
2692 CPPDEFINES = [['_POSIX_C_SOURCE', '199506'],
2693 ['_XOPEN_SOURCE', '600'],
2694 ['_GNU_SOURCE', '1'],
2695 ['_LARGEFILE64_SOURCE', '1'],
2698 LINKFLAGS=['-static-libstdc++'],
2701 if linux_env.Bit('build_x86_32'):
2704 LINKFLAGS = ['-m32'],
2706 elif linux_env.Bit('build_x86_64'):
2709 LINKFLAGS = ['-m64'],
2711 elif linux_env.Bit('build_arm'):
2712 SetUpLinuxEnvArm(linux_env)
2713 elif linux_env.Bit('build_mips32'):
2714 SetUpLinuxEnvMips(linux_env)
2716 Banner('Strange platform: %s' % GetTargetPlatform())
2718 # These are desireable options for every Linux platform:
2719 # _FORTIFY_SOURCE: general paranoia "hardening" option for library functions
2720 # -fPIE/-pie: create a position-independent executable
2721 # relro/now: "hardening" options for linking
2722 # noexecstack: ensure that the executable does not get a PT_GNU_STACK
2723 # header that causes the kernel to set the READ_IMPLIES_EXEC
2724 # personality flag, which disables NX page protection.
2725 linux_env.Prepend(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2726 # By default SHLINKFLAGS uses $LINKFLAGS, but we do not want -pie
2727 # in $SHLINKFLAGS, only in $LINKFLAGS. So move LINKFLAGS over to
2728 # COMMON_LINKFLAGS, and add the "hardening" options there. Then
2729 # make both LINKFLAGS and SHLINKFLAGS refer to that, and add -pie
2730 # only to LINKFLAGS.
2731 linux_env.Replace(COMMON_LINKFLAGS=linux_env['LINKFLAGS'],
2732 LINKFLAGS=['$COMMON_LINKFLAGS'])
2733 linux_env.FilterOut(SHLINKFLAGS=['$LINKFLAGS'])
2734 linux_env.Prepend(SHLINKFLAGS=['$COMMON_LINKFLAGS'])
2735 linux_env.Prepend(COMMON_LINKFLAGS=['-Wl,-z,relro',
2737 '-Wl,-z,noexecstack'])
2738 linux_env.Prepend(LINKFLAGS=['-pie'])
2739 # The ARM toolchain has a linker that doesn't handle the code its
2740 # compiler generates under -fPIE.
2741 if linux_env.Bit('build_arm') or linux_env.Bit('build_mips32'):
2742 linux_env.Prepend(CCFLAGS=['-fPIC'])
2743 # TODO(mcgrathr): Temporarily punt _FORTIFY_SOURCE for ARM because
2744 # it causes a libc dependency newer than the old bots have installed.
2745 linux_env.FilterOut(CPPDEFINES=[['-D_FORTIFY_SOURCE', '2']])
2747 linux_env.Prepend(CCFLAGS=['-fPIE'])
2749 # We always want to use the same flags for .S as for .c because
2750 # code-generation flags affect the predefines we might test there.
2751 linux_env.Replace(ASFLAGS=['${CCFLAGS}'])
2755 # Specializes a generic Linux development environment to be a trusted
2757 def MakeTrustedLinuxEnv(platform=None):
2758 linux_env = MakeGenericLinuxEnv(platform)
2759 if linux_env.Bit('android'):
2760 SetUpAndroidEnv(linux_env)
2763 (linux_debug_env, linux_optimized_env) = \
2764 GenerateOptimizationLevels(MakeTrustedLinuxEnv())
2767 def BiasedBitcodeFlags(env):
2768 """ Return clang flags to use biased bitcode and generate native-ABI-compliant
2769 code. Does not imply pre-translation.
2771 if env.Bit('build_x86_32'):
2772 return ['--target=i686-unknown-nacl']
2773 if env.Bit('build_x86_64'):
2774 return ['--target=x86_64-unknown-nacl']
2775 if env.Bit('build_arm'):
2776 return ['--target=armv7-unknown-nacl-gnueabihf', '-mfloat-abi=hard']
2777 if env.Bit('build_mips32'):
2779 raise UserError('No known target bits set')
2781 pre_base_env.AddMethod(BiasedBitcodeFlags)
2783 # Do this before the site_scons/site_tools/naclsdk.py stuff to pass it along.
2784 pre_base_env.Append(
2785 PNACL_BCLDFLAGS = ARGUMENTS.get('pnacl_bcldflags', '').split(':'))
2788 # The nacl_env is used to build native_client modules
2789 # using a special tool chain which produces platform
2790 # independent binaries
2791 # NOTE: this loads stuff from: site_scons/site_tools/naclsdk.py
2792 nacl_env = MakeArchSpecificEnv()
2793 # See comment below about libc++ and libpthread in NONIRT_LIBS.
2794 using_nacl_libcxx = nacl_env.Bit('bitcode') or nacl_env.Bit('nacl_clang')
2795 nacl_env = nacl_env.Clone(
2796 tools = ['naclsdk'],
2797 NACL_BUILD_FAMILY = 'UNTRUSTED',
2798 BUILD_TYPE = 'nacl',
2799 BUILD_TYPE_DESCRIPTION = 'NaCl module build',
2803 # ${SOURCE_ROOT} for #include <ppapi/...>
2809 EXTRA_CXXFLAGS = [],
2811 EXTRA_LINKFLAGS = ARGUMENTS.get('nacl_linkflags', '').split(':'),
2813 # always optimize binaries
2816 '-fomit-frame-pointer',
2817 # This makes sure unwind/backtrace info is available for
2818 # all code locations. Note build/untrusted.gypi uses it too.
2819 '-fasynchronous-unwind-tables',
2822 '-fdiagnostics-show-option',
2827 CFLAGS = ['-std=gnu99',
2829 CXXFLAGS = ['-std=gnu++98',
2833 # This magic is copied from scons-2.0.1/engine/SCons/Defaults.py
2834 # where this pattern is used for _LIBDIRFLAGS, which produces -L
2835 # switches. Here we are producing a -Wl,-rpath-link,DIR for each
2836 # element of LIBPATH, i.e. for each -LDIR produced.
2837 RPATH_LINK_FLAGS = '$( ${_concat(RPATHLINKPREFIX, LIBPATH, RPATHLINKSUFFIX,'
2838 '__env__, RDirs, TARGET, SOURCE)} $)',
2839 RPATHLINKPREFIX = '-Wl,-rpath-link,',
2840 RPATHLINKSUFFIX = '',
2843 LINKFLAGS = ['${RPATH_LINK_FLAGS}'] + (['-Werror'] if nacl_env.Bit('werror')
2846 # These are settings for in-tree, non-browser tests to use.
2847 # They use libraries that circumvent the IRT-based implementations
2848 # in the public libraries.
2849 # Note that pthread_private is part of NONIRT_LIBS for clang because
2850 # libc++ depends on libpthread. However we can't just add
2851 # libpthread_private to the link line because those libs get added before
2852 # the standard libs, so the references that come from libc++ itself will
2853 # still get satisfied from libpthread instead of libpthread_private (and
2854 # that code will crash because it requires the IRT). So put libc++ on the
2855 # user link line before libpthread_private to ensure that its references
2856 # to libpthread also get satisfied by libpthread_private.
2857 # TODO(dschuff): Also remove the hack in pnacl-ld and use this for pnacl.
2858 NONIRT_LIBS = (['nacl_sys_private'] +
2859 (['c++','pthread_private'] if using_nacl_libcxx else [])),
2860 PTHREAD_LIBS = ['pthread_private'],
2861 DYNCODE_LIBS = ['nacl_dyncode_private'],
2862 EXCEPTION_LIBS = ['nacl_exception_private'],
2863 LIST_MAPPINGS_LIBS = ['nacl_list_mappings_private'],
2864 RANDOM_LIBS = ['nacl_random_private'],
2867 def UsesAbiNote(env):
2868 """Return True if using a new-style GCC with .note.NaCl.ABI.* notes.
2869 This means there will always be an RODATA segment, even if just for the note."""
2870 return env.Bit('build_arm') and not env.Bit('bitcode')
2872 nacl_env.AddMethod(UsesAbiNote)
2874 def UnderWindowsCoverage(env):
2875 """Return True if using running on coverage under windows."""
2876 if 'TRUSTED_ENV' not in env:
2878 return env['TRUSTED_ENV'].Bit('coverage_enabled') and env.Bit('host_windows')
2880 nacl_env.AddMethod(UnderWindowsCoverage)
2882 def SetNonStableBitcodeIfAllowed(env, allow_sb_translator=False):
2883 """ This modifies the environment to allow features that aren't part
2884 of PNaCl's stable ABI. If tests using these features should be
2885 skipped entirely, this returns False. Otherwise, on success, it
2888 if env.Bit('bitcode') and env.Bit('skip_nonstable_bitcode'):
2890 # The PNaCl sandboxed translator (for the most part) only accepts stable
2891 # bitcode, so in most cases we skip building non-stable tests.
2892 # However, there are some limited cases like debug information which
2893 # we support but do not guarantee stability. Tests targeting such cases
2894 # can opt-in to testing w/ allow_sb_translator=True.
2895 if env.Bit('use_sandboxed_translator') and not allow_sb_translator:
2897 # Change environment to skip finalization step.
2898 env.SetBits('nonstable_bitcode')
2901 nacl_env.AddMethod(SetNonStableBitcodeIfAllowed)
2904 def AllowInlineAssembly(env):
2905 """ This modifies the environment to allow inline assembly in
2906 untrusted code. If the environment cannot be modified to allow
2907 inline assembly, it returns False. Otherwise, on success, it
2910 if env.Bit('bitcode'):
2911 # For each architecture, we only attempt to make our inline
2912 # assembly code work with one untrusted-code toolchain. For x86,
2913 # we target GCC, but not PNaCl/Clang, because the latter's
2914 # assembly support has various quirks that we don't want to have
2915 # to debug. For ARM, we target PNaCl/Clang, because that is the
2916 # only current ARM toolchain. One day, we will have an ARM GCC
2917 # toolchain, and we will no longer need to use inline assembly
2918 # with PNaCl/Clang at all.
2920 # For Non-SFI NaCl we use inline assembly in PNaCl/Clang.
2921 if not (env.Bit('build_arm') or env.Bit('build_mips32')
2922 or env.Bit('nonsfi_nacl')):
2924 # Inline assembly does not work in pexes.
2925 if env.Bit('pnacl_generate_pexe'):
2927 env.AddBiasForPNaCl()
2928 env.PNaClForceNative()
2930 if env.Bit('build_x86_32'):
2931 env.AppendUnique(CCFLAGS=['--target=i686-unknown-nacl'])
2932 elif env.Bit('build_x86_64'):
2933 env.AppendUnique(CCFLAGS=['--target=x86_64-unknown-nacl'])
2934 elif env.Bit('build_arm'):
2935 env.AppendUnique(CCFLAGS=['--target=armv7a-unknown-nacl-gnueabihf',
2936 '-mfloat-abi=hard'])
2937 # Enable the use of inline assembly.
2938 env.Append(CCFLAGS=['-fgnu-inline-asm'])
2941 nacl_env.AddMethod(AllowInlineAssembly)
2944 # TODO(mseaborn): Enable this unconditionally once the C code on the
2945 # Chromium side compiles successfully with this warning.
2946 if not enable_chrome:
2947 nacl_env.Append(CFLAGS=['-Wstrict-prototypes'])
2949 # This is the address at which a user executable is expected to place its
2950 # data segment in order to be compatible with the integrated runtime (IRT)
2951 # library. This address should not be changed lightly.
2952 irt_compatible_rodata_addr = 0x10000000
2953 # This is the address at which the IRT's own code will be located.
2954 # It must be below irt_compatible_rodata and leave enough space for
2955 # the code segment of the IRT. It should be as close as possible to
2956 # irt_compatible_rodata so as to leave the maximum contiguous area
2957 # available for the dynamic code loading area that falls below it.
2958 # This can be adjusted as necessary for the actual size of the IRT code.
2959 irt_code_addr = irt_compatible_rodata_addr - (6 << 20) # max 6M IRT code
2960 # This is the address at which the IRT's own data will be located. The
2961 # 32-bit sandboxes limit the address space to 1GB; the initial thread's
2962 # stack sits at the top of the address space and extends down for
2963 # NACL_DEFAULT_STACK_MAX (src/trusted/service_runtime/sel_ldr.h) below.
2964 # So this must be below there, and leave enough space for the IRT's own
2965 # data segment. It should be as high as possible so as to leave the
2966 # maximum contiguous area available for the user's data and break below.
2967 # This can be adjusted as necessary for the actual size of the IRT data
2968 # (that is RODATA, rounded up to 64k, plus writable data).
2969 # 1G (address space) - 16M (NACL_DEFAULT_STACK_MAX) - 1MB (IRT rodata+data)
2970 irt_data_addr = (1 << 30) - (16 << 20) - (1 << 20)
2973 IRT_DATA_REGION_START = '%#.8x' % irt_compatible_rodata_addr,
2974 # Load addresses of the IRT's code and data segments.
2975 IRT_BLOB_CODE_START = '%#.8x' % irt_code_addr,
2976 IRT_BLOB_DATA_START = '%#.8x' % irt_data_addr,
2979 def TestsUsePublicListMappingsLib(env):
2980 """Use the public list_mappings library for in-tree tests."""
2981 env.Replace(LIST_MAPPINGS_LIBS=['nacl_list_mappings'])
2983 def TestsUsePublicLibs(env):
2984 """Change the environment so it uses public libraries for in-tree tests."""
2985 env.Replace(NONIRT_LIBS=['pthread'] if env.Bit('bitcode') else [],
2986 PTHREAD_LIBS=['pthread'],
2987 DYNCODE_LIBS=['nacl_dyncode', 'nacl'],
2988 EXCEPTION_LIBS=['nacl_exception', 'nacl'],
2989 RANDOM_LIBS=['nacl'])
2991 # glibc is incompatible with libpthread_private and libnacl_sys_private.
2992 if nacl_env.Bit('nacl_glibc'):
2993 nacl_env.Replace(NONIRT_LIBS=[],
2994 PTHREAD_LIBS=['pthread'])
2996 # These add on to those set in pre_base_env, above.
2999 # This ensures that UINT32_MAX gets defined.
3000 ['__STDC_LIMIT_MACROS', '1'],
3001 # This ensures that PRId64 etc. get defined.
3002 ['__STDC_FORMAT_MACROS', '1'],
3003 # _GNU_SOURCE ensures that strtof() gets declared.
3005 ['_POSIX_C_SOURCE', '199506'],
3006 ['_XOPEN_SOURCE', '600'],
3008 ['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3009 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ],
3011 ['NACL_BUILD_ARCH', '${BUILD_ARCHITECTURE}'],
3012 ['NACL_BUILD_SUBARCH', '${BUILD_SUBARCH}'],
3016 def FixWindowsAssembler(env):
3017 if env.Bit('host_windows'):
3018 # ASCOM is the rule used by .s files and ASPPCOM is the rule used by .S
3019 # files; the latter uses the C preprocessor. This is needed because Windows
3020 # builds are case-insensitive, so they all appear as .s files.
3021 env.Replace(ASCOM='${ASPPCOM}')
3023 FixWindowsAssembler(nacl_env)
3025 # Look in the local include and lib directories before the toolchain's.
3026 nacl_env['INCLUDE_DIR'] = '${TARGET_ROOT}/include'
3027 # Remove the default $LIB_DIR element so that we prepend it without duplication.
3028 # Using PrependUnique alone would let it stay last, where we want it first.
3029 nacl_env.FilterOut(LIBPATH=['${LIB_DIR}'])
3030 nacl_env.PrependUnique(
3031 CPPPATH = ['${INCLUDE_DIR}'],
3032 LIBPATH = ['${LIB_DIR}'],
3035 if nacl_env.Bit('bitcode'):
3036 # passing -O when linking requests LTO, which does additional global
3037 # optimizations at link time
3038 nacl_env.Append(LINKFLAGS=['-O3'])
3039 if not nacl_env.Bit('nacl_glibc'):
3040 nacl_env.Append(LINKFLAGS=['-static'])
3042 if nacl_env.Bit('translate_fast'):
3043 nacl_env.Append(LINKFLAGS=['-Xlinker', '-translate-fast'])
3044 nacl_env.Append(TRANSLATEFLAGS=['-translate-fast'])
3045 if nacl_env.Bit('use_sz'):
3046 nacl_env.Append(TRANSLATEFLAGS=['--use-sz'])
3048 # With pnacl's clang base/ code uses the "override" keyword.
3049 nacl_env.Append(CXXFLAGS=['-Wno-c++11-extensions'])
3050 # Allow extraneous semicolons. (Until these are removed.)
3051 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3052 nacl_env.Append(CCFLAGS=['-Wno-extra-semi'])
3053 # Allow unused private fields. (Until these are removed.)
3054 # http://code.google.com/p/nativeclient/issues/detail?id=2861
3055 nacl_env.Append(CCFLAGS=['-Wno-unused-private-field'])
3056 # native_client/src/nonsfi/linux/linux_syscall_structs.h uses designated
3057 # initializers, which causes a warning when included from c++98 code.
3058 nacl_env.Append(CXXFLAGS=['-Wno-c99-extensions'])
3060 if nacl_env.Bit('nacl_clang'):
3061 # third_party/valgrind/nacl_valgrind.h uses asm instead of __asm__
3062 # https://code.google.com/p/nativeclient/issues/detail?id=3974
3063 # TODO(dschuff): change it to __asm__ and remove this suppression.
3064 nacl_env.Append(CCFLAGS=['-Wno-language-extension-token'])
3066 # We use a special environment for building the IRT image because it must
3067 # always use the newlib toolchain, regardless of --nacl_glibc. We clone
3068 # it from nacl_env here, before too much other cruft has been added.
3069 # We do some more magic below to instantiate it the way we need it.
3070 nacl_irt_env = nacl_env.Clone(
3071 BUILD_TYPE = 'nacl_irt',
3072 BUILD_TYPE_DESCRIPTION = 'NaCl IRT build',
3073 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT',
3076 # Provide access to the IRT build environment from the default environment
3077 # which is needed when compiling custom IRT for testing purposes.
3078 nacl_env['NACL_IRT_ENV'] = nacl_irt_env
3080 # Since we don't build src/untrusted/pthread/nacl.scons in
3081 # nacl_irt_env, we must tell the IRT how to find the pthread.h header.
3082 nacl_irt_env.Append(CPPPATH='${MAIN_DIR}/src/untrusted/pthread')
3084 # Map certain flag bits to suffices on the build output. This needs to
3085 # happen pretty early, because it affects any concretized directory names.
3086 target_variant_map = [
3087 ('bitcode', 'pnacl'),
3088 ('translate_fast', 'fast'),
3089 ('use_sz', 'subzero'),
3090 ('nacl_pic', 'pic'),
3091 ('use_sandboxed_translator', 'sbtc'),
3092 ('nacl_glibc', 'glibc'),
3093 ('pnacl_generate_pexe', 'pexe'),
3094 ('nonsfi_nacl', 'nonsfi'),
3096 for variant_bit, variant_suffix in target_variant_map:
3097 if nacl_env.Bit(variant_bit):
3098 nacl_env['TARGET_VARIANT'] += '-' + variant_suffix
3100 if nacl_env.Bit('bitcode'):
3101 nacl_env['TARGET_VARIANT'] += '-clang'
3103 nacl_env.Replace(TESTRUNNER_LIBS=['testrunner'])
3105 # TODO(mseaborn): Make nacl-glibc-based static linking work with just
3106 # "-static", without specifying a linker script.
3107 # See http://code.google.com/p/nativeclient/issues/detail?id=1298
3108 def GetLinkerScriptBaseName(env):
3109 if env.Bit('build_x86_64'):
3110 return 'elf_x86_64_nacl'
3112 return 'elf_i386_nacl'
3114 if (nacl_env.Bit('nacl_glibc') and
3115 nacl_env.Bit('nacl_static_link')):
3116 nacl_env.Append(LINKFLAGS=['-static'])
3117 if nacl_env.Bit('build_x86'):
3118 # The "-lc" is necessary because libgcc_eh depends on libc but for
3119 # some reason nacl-gcc is not linking with "--start-group/--end-group".
3120 nacl_env.Append(LINKFLAGS=[
3121 '-T', 'ldscripts/%s.x.static' % GetLinkerScriptBaseName(nacl_env),
3124 if nacl_env.Bit('running_on_valgrind'):
3125 nacl_env.Append(CCFLAGS = ['-g', '-Wno-overlength-strings',
3126 '-fno-optimize-sibling-calls'],
3127 CPPDEFINES = [['DYNAMIC_ANNOTATIONS_ENABLED', '1' ],
3128 ['DYNAMIC_ANNOTATIONS_PREFIX', 'NACL_' ]])
3129 # With GLibC, libvalgrind.so is preloaded at runtime.
3130 # With Newlib, it has to be linked in.
3131 if not nacl_env.Bit('nacl_glibc'):
3132 nacl_env.Append(LINKFLAGS = ['-Wl,-u,have_nacl_valgrind_interceptors'],
3133 LIBS = ['valgrind'])
3135 environment_list.append(nacl_env)
3137 if not nacl_env.Bit('nacl_glibc'):
3138 # These are all specific to nacl-newlib so we do not include them
3139 # when building against nacl-glibc. The functionality of
3140 # pthread/startup/stubs/nosys is provided by glibc. The valgrind
3141 # code currently assumes nc_threads.
3143 BUILD_SCONSCRIPTS = [
3144 #### ALPHABETICALLY SORTED ####
3145 'src/untrusted/elf_loader/nacl.scons',
3146 'src/untrusted/pthread/nacl.scons',
3147 'src/untrusted/stubs/nacl.scons',
3148 'src/untrusted/nosys/nacl.scons',
3149 #### ALPHABETICALLY SORTED ####
3152 BUILD_SCONSCRIPTS = [
3153 #### ALPHABETICALLY SORTED ####
3154 'src/nonsfi/irt/build.scons',
3155 'src/nonsfi/linux/nacl.scons',
3156 'src/nonsfi/loader/build.scons',
3157 'src/shared/gio/nacl.scons',
3158 'src/shared/imc/nacl.scons',
3159 'src/shared/platform/nacl.scons',
3160 'src/trusted/service_runtime/nacl.scons',
3161 'src/trusted/validator/nacl.scons',
3162 'src/untrusted/irt/nacl_headers.scons',
3163 'src/untrusted/minidump_generator/nacl.scons',
3164 'src/untrusted/nacl/nacl.scons',
3165 'src/untrusted/pll_loader/nacl.scons',
3166 'src/untrusted/pnacl_dynloader/nacl.scons',
3167 'src/untrusted/valgrind/nacl.scons',
3168 #### ALPHABETICALLY SORTED ####
3170 nacl_env.AddChromeFilesFromGroup('untrusted_scons_files')
3172 # These are tests that are worthwhile to run in IRT variant only.
3174 #### ALPHABETICALLY SORTED ####
3175 'tests/elf_loader/nacl.scons',
3176 'tests/irt/nacl.scons',
3177 'tests/irt_compatibility/nacl.scons',
3178 'tests/irt_entry_alignment/nacl.scons',
3179 'tests/irt_ext/nacl.scons',
3180 'tests/irt_stack_alignment/nacl.scons',
3181 'tests/sbrk/nacl.scons',
3182 'tests/translator_size_limits/nacl.scons',
3185 # These are tests that are worthwhile to run in both IRT and non-IRT variants.
3186 # The nacl_irt_test mode runs them in the IRT variants.
3187 irt_variant_tests = [
3188 #### ALPHABETICALLY SORTED ####
3189 'tests/app_lib/nacl.scons',
3190 'tests/benchmark/nacl.scons',
3191 'tests/bigalloc/nacl.scons',
3192 'tests/callingconv/nacl.scons',
3193 'tests/callingconv_ppapi/nacl.scons',
3194 'tests/callingconv_case_by_case/nacl.scons',
3195 'tests/clock/nacl.scons',
3196 'tests/common/nacl.scons',
3197 'tests/compiler_thread_suspension/nacl.scons',
3198 'tests/computed_gotos/nacl.scons',
3199 'tests/data_below_data_start/nacl.scons',
3200 'tests/data_not_executable/nacl.scons',
3201 'tests/debug_stub/nacl.scons',
3202 'tests/dup/nacl.scons',
3203 'tests/dynamic_code_loading/nacl.scons',
3204 'tests/dynamic_linking/nacl.scons',
3205 'tests/egyptian_cotton/nacl.scons',
3206 'tests/environment_variables/nacl.scons',
3207 'tests/exception_test/nacl.scons',
3208 'tests/fdopen_test/nacl.scons',
3209 'tests/file/nacl.scons',
3210 'tests/futexes/nacl.scons',
3211 'tests/gc_instrumentation/nacl.scons',
3212 'tests/gdb/nacl.scons',
3213 'tests/glibc_file64_test/nacl.scons',
3214 'tests/glibc_static_test/nacl.scons',
3215 'tests/glibc_syscall_wrappers/nacl.scons',
3216 'tests/glibc_socket_wrappers/nacl.scons',
3217 'tests/hello_world/nacl.scons',
3218 'tests/imc_shm_mmap/nacl.scons',
3219 'tests/includability/nacl.scons',
3220 'tests/infoleak/nacl.scons',
3221 'tests/libc/nacl.scons',
3222 'tests/libc_free_hello_world/nacl.scons',
3223 'tests/limited_file_access/nacl.scons',
3224 'tests/list_mappings/nacl.scons',
3225 'tests/longjmp/nacl.scons',
3226 'tests/loop/nacl.scons',
3227 'tests/math/nacl.scons',
3228 'tests/memcheck_test/nacl.scons',
3229 'tests/mmap/nacl.scons',
3230 'tests/mmap_main_nexe/nacl.scons',
3231 'tests/mmap_prot_exec/nacl.scons',
3232 'tests/mmap_race_protect/nacl.scons',
3233 'tests/nacl_log/nacl.scons',
3234 'tests/nanosleep/nacl.scons',
3235 'tests/nonsfi/nacl.scons',
3236 'tests/noop/nacl.scons',
3237 'tests/nrd_xfer/nacl.scons',
3238 'tests/nthread_nice/nacl.scons',
3239 'tests/null/nacl.scons',
3240 'tests/nullptr/nacl.scons',
3241 'tests/pagesize/nacl.scons',
3242 'tests/performance/nacl.scons',
3243 'tests/pnacl_abi/nacl.scons',
3244 'tests/pnacl_dynamic_loading/nacl.scons',
3245 'tests/pnacl_native_objects/nacl.scons',
3246 'tests/random/nacl.scons',
3247 'tests/redir/nacl.scons',
3248 'tests/rodata_not_writable/nacl.scons',
3249 'tests/run_py/nacl.scons',
3250 'tests/sel_ldr/nacl.scons',
3251 'tests/sel_ldr_seccomp/nacl.scons',
3252 'tests/sel_main_chrome/nacl.scons',
3253 'tests/signal_handler/nacl.scons',
3254 'tests/simd/nacl.scons',
3255 'tests/sleep/nacl.scons',
3256 'tests/stack_alignment/nacl.scons',
3257 'tests/stubout_mode/nacl.scons',
3258 'tests/sysbasic/nacl.scons',
3259 'tests/syscall_return_regs/nacl.scons',
3260 'tests/syscall_return_sandboxing/nacl.scons',
3261 'tests/syscalls/nacl.scons',
3262 'tests/thread_capture/nacl.scons',
3263 'tests/threads/nacl.scons',
3264 'tests/time/nacl.scons',
3265 'tests/tls/nacl.scons',
3266 'tests/tls_segment_x86_32/nacl.scons',
3267 'tests/toolchain/nacl.scons',
3268 'tests/toolchain/arm/nacl.scons',
3269 'tests/toolchain/mips/nacl.scons',
3270 'tests/unittests/shared/platform/nacl.scons',
3271 'tests/untrusted_check/nacl.scons',
3272 'tests/unwind_restores_regs/nacl.scons',
3273 'tests/validator/nacl.scons',
3274 #### ALPHABETICALLY SORTED ####
3275 # NOTE: The following tests are really IRT-only tests, but they
3276 # are in this category so that they can generate libraries (which
3277 # works in nacl_env but not in nacl_irt_test_env) while also
3278 # adding tests to nacl_irt_test_env.
3279 'tests/inbrowser_test_runner/nacl.scons',
3280 'tests/untrusted_minidump/nacl.scons',
3283 # These are tests that are NOT worthwhile to run in an IRT variant.
3284 # In some cases, that's because they are browser tests which always
3285 # use the IRT. In others, it's because they are special-case tests
3286 # that are incompatible with having an IRT loaded.
3287 nonvariant_tests = [
3288 #### ALPHABETICALLY SORTED ####
3289 'tests/barebones/nacl.scons',
3290 'tests/chrome_extension/nacl.scons',
3291 'tests/custom_desc/nacl.scons',
3292 'tests/faulted_thread_queue/nacl.scons',
3293 'tests/gold_plugin/nacl.scons',
3294 'tests/imc_sockets/nacl.scons',
3295 'tests/minnacl/nacl.scons',
3296 'tests/multiple_sandboxes/nacl.scons',
3297 # Potential issue with running them:
3298 # http://code.google.com/p/nativeclient/issues/detail?id=2092
3299 # See also the comment in "buildbot/buildbot_standard.py"
3300 'tests/pnacl_shared_lib_test/nacl.scons',
3301 'tests/pwrite/nacl.scons',
3302 'tests/signal_handler_single_step/nacl.scons',
3303 'tests/thread_suspension/nacl.scons',
3304 'tests/trusted_crash/crash_in_syscall/nacl.scons',
3305 'tests/trusted_crash/osx_crash_filter/nacl.scons',
3306 'tests/trusted_crash/osx_crash_forwarding/nacl.scons',
3307 'tests/unittests/shared/imc/nacl.scons',
3308 #### ALPHABETICALLY SORTED ####
3311 nacl_env.Append(BUILD_SCONSCRIPTS=nonvariant_tests)
3312 nacl_env.AddChromeFilesFromGroup('nonvariant_test_scons_files')
3313 nacl_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3314 nacl_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3316 # Defines TESTS_TO_RUN_INBROWSER.
3317 SConscript('tests/inbrowser_test_runner/selection.scons',
3318 exports=['nacl_env'])
3320 # Possibly install a toolchain by downloading it
3321 # TODO: explore using a less heavy weight mechanism
3322 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3325 SCons.Script.AddOption('--download',
3329 action='store_true',
3330 help='deprecated - allow tools to download')
3332 if nacl_env.GetOption('download'):
3333 print('@@@@ --download is deprecated, use gclient runhooks --force')
3334 nacl_sync_env = nacl_env.Clone()
3335 nacl_sync_env['ENV'] = os.environ
3336 nacl_sync_env.Execute('gclient runhooks --force')
3339 def NaClSharedLibrary(env, lib_name, *args, **kwargs):
3340 env_shared = env.Clone(COMPONENT_STATIC=False)
3341 soname = SCons.Util.adjustixes(lib_name, 'lib', '.so')
3342 env_shared.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s' % (soname)])
3343 return env_shared.ComponentLibrary(lib_name, *args, **kwargs)
3345 nacl_env.AddMethod(NaClSharedLibrary)
3347 def NaClSdkLibrary(env, lib_name, *args, **kwargs):
3348 n = [env.ComponentLibrary(lib_name, *args, **kwargs)]
3349 if not env.Bit('nacl_disable_shared'):
3350 n.append(env.NaClSharedLibrary(lib_name, *args, **kwargs))
3353 nacl_env.AddMethod(NaClSdkLibrary)
3356 # Special environment for untrusted test binaries that use raw syscalls
3357 def RawSyscallObjects(env, sources):
3358 raw_syscall_env = env.Clone()
3359 raw_syscall_env.Append(
3361 ['USE_RAW_SYSCALLS', '1'],
3365 for source_file in sources:
3366 target_name = 'raw_' + os.path.basename(source_file).rstrip('.c')
3367 object = raw_syscall_env.ComponentObject(target_name,
3369 objects.append(object)
3372 nacl_env.AddMethod(RawSyscallObjects)
3375 # The IRT-building environment was cloned from nacl_env, but it should
3376 # ignore the --nacl_glibc, nacl_pic=1 and bitcode=1 switches.
3377 # We have to reinstantiate the naclsdk.py magic after clearing those flags,
3378 # so it regenerates the tool paths right.
3379 # TODO(mcgrathr,bradnelson): could get cleaner if naclsdk.py got folded back in.
3380 nacl_irt_env.ClearBits('nacl_glibc')
3381 nacl_irt_env.ClearBits('nacl_pic')
3382 nacl_irt_env.ClearBits('pnacl_generate_pexe')
3383 nacl_irt_env.ClearBits('use_sandboxed_translator')
3384 nacl_irt_env.ClearBits('bitcode')
3385 # The choice of toolchain used to build the IRT does not depend on the toolchain
3386 # used to build user/test code. nacl-clang is used everywhere for the IRT.
3387 nacl_irt_env.SetBits('nacl_clang')
3389 nacl_irt_env.Tool('naclsdk')
3390 # These are unfortunately clobbered by running Tool, which
3391 # we needed to do to get the destination directory reset.
3392 # We want all the same values from nacl_env.
3393 nacl_irt_env.Replace(EXTRA_CFLAGS=nacl_env['EXTRA_CFLAGS'],
3394 EXTRA_CXXFLAGS=nacl_env['EXTRA_CXXFLAGS'],
3395 CCFLAGS=nacl_env['CCFLAGS'],
3396 CFLAGS=nacl_env['CFLAGS'],
3397 CXXFLAGS=nacl_env['CXXFLAGS'])
3398 FixWindowsAssembler(nacl_irt_env)
3399 # Make it find the libraries it builds, rather than the SDK ones.
3400 nacl_irt_env.Replace(LIBPATH='${LIB_DIR}')
3402 # The IRT must be built using LLVM's assembler on x86-64 to preserve sandbox
3403 # base address hiding. It's also used on x86-32 for consistency.
3404 if nacl_irt_env.Bit('build_x86_64') or nacl_irt_env.Bit('build_x86_32'):
3405 nacl_irt_env.Append(CCFLAGS=['-integrated-as'])
3406 if nacl_irt_env.Bit('build_x86_32'):
3407 # The x86-32 IRT needs to be callable with an under-aligned stack.
3408 # See https://code.google.com/p/nativeclient/issues/detail?id=3935
3409 nacl_irt_env.Append(CCFLAGS=['-mstackrealign', '-mno-sse'])
3411 # The IRT is C only, don't link with the C++ linker so that it doesn't
3412 # start depending on the C++ standard library and (in the case of
3414 nacl_irt_env.Replace(LINK=(nacl_irt_env['LINK'].
3415 replace('nacl-clang++', 'nacl-clang')))
3417 # TODO(mcgrathr): Clean up uses of these methods.
3418 def AddLibraryDummy(env, nodes):
3420 nacl_irt_env.AddMethod(AddLibraryDummy, 'AddLibraryToSdk')
3422 def AddObjectInternal(env, nodes):
3423 return env.Replicate('${LIB_DIR}', nodes)
3424 nacl_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3425 nacl_irt_env.AddMethod(AddObjectInternal, 'AddObjectToSdk')
3427 def IrtNaClSdkLibrary(env, lib_name, *args, **kwargs):
3428 env.ComponentLibrary(lib_name, *args, **kwargs)
3429 nacl_irt_env.AddMethod(IrtNaClSdkLibrary, 'NaClSdkLibrary')
3431 nacl_irt_env.AddMethod(SDKInstallBin)
3433 # Populate the internal include directory when AddHeaderToSdk
3434 # is used inside nacl_env.
3435 def AddHeaderInternal(env, nodes, subdir='nacl'):
3436 dir = '${INCLUDE_DIR}'
3437 if subdir is not None:
3439 n = env.Replicate(dir, nodes)
3442 nacl_irt_env.AddMethod(AddHeaderInternal, 'AddHeaderToSdk')
3444 def PublishHeader(env, nodes, subdir):
3445 if ('install' in COMMAND_LINE_TARGETS or
3446 'install_headers' in COMMAND_LINE_TARGETS):
3447 dir = env.GetAbsDirArg('includedir', 'install_headers')
3448 if subdir is not None:
3450 n = env.Install(dir, nodes)
3451 env.Alias('install', env.Alias('install_headers', n))
3454 def PublishLibrary(env, nodes):
3455 env.Alias('build_lib', nodes)
3457 if ('install' in COMMAND_LINE_TARGETS or
3458 'install_lib' in COMMAND_LINE_TARGETS):
3459 dir = env.GetAbsDirArg('libdir', 'install_lib')
3460 n = env.Install(dir, nodes)
3461 env.Alias('install', env.Alias('install_lib', n))
3464 def NaClAddHeader(env, nodes, subdir='nacl'):
3465 n = AddHeaderInternal(env, nodes, subdir)
3466 PublishHeader(env, n, subdir)
3468 nacl_env.AddMethod(NaClAddHeader, 'AddHeaderToSdk')
3470 def NaClAddLibrary(env, nodes):
3471 nodes = env.Replicate('${LIB_DIR}', nodes)
3472 PublishLibrary(env, nodes)
3474 nacl_env.AddMethod(NaClAddLibrary, 'AddLibraryToSdk')
3476 def NaClAddObject(env, nodes):
3477 lib_nodes = env.Replicate('${LIB_DIR}', nodes)
3478 PublishLibrary(env, lib_nodes)
3480 nacl_env.AddMethod(NaClAddObject, 'AddObjectToSdk')
3482 # We want to do this for nacl_env when not under --nacl_glibc,
3483 # but for nacl_irt_env whether or not under --nacl_glibc, so
3484 # we do it separately for each after making nacl_irt_env and
3485 # clearing its Bit('nacl_glibc').
3486 def AddImplicitLibs(env):
3489 # Require the pnacl_irt_shim for pnacl x86-64 and arm.
3490 # Use -B to have the compiler look for the fresh libpnacl_irt_shim.a.
3491 if ( env.Bit('bitcode') and
3492 (env.Bit('build_x86_64') or env.Bit('build_arm'))
3493 and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT'):
3494 # Note: without this hack ibpnacl_irt_shim.a will be deleted
3495 # when "built_elsewhere=1"
3496 # Since we force the build in a previous step the dependency
3497 # is not really needed.
3498 # Note: the "precious" mechanism did not work in this case
3499 if not env.Bit('built_elsewhere'):
3500 if env.Bit('enable_chrome_side'):
3501 implicit_libs += ['libpnacl_irt_shim.a']
3503 if not env.Bit('nacl_glibc'):
3504 # These are automatically linked in by the compiler, either directly
3505 # or via the linker script that is -lc. In the non-glibc build, we
3506 # are the ones providing these files, so we need dependencies.
3507 # The ComponentProgram method (site_scons/site_tools/component_builders.py)
3508 # adds dependencies on env['IMPLICIT_LIBS'] if that's set.
3509 if env.Bit('bitcode'):
3510 implicit_libs += ['libnacl.a']
3512 implicit_libs += ['crt1.o',
3516 # TODO(mcgrathr): multilib nonsense defeats -B! figure out a better way.
3517 if GetTargetPlatform() == 'x86-32':
3518 implicit_libs.append(os.path.join('32', 'crt1.o'))
3519 # libc++ depends on libpthread, and because PPAPI applications always need
3520 # threads anyway, nacl-clang just includes -lpthread unconditionally.
3521 if using_nacl_libcxx and env['NACL_BUILD_FAMILY'] != 'UNTRUSTED_IRT':
3522 implicit_libs += ['libpthread.a']
3524 if implicit_libs != []:
3525 env['IMPLICIT_LIBS'] = [env.File(os.path.join('${LIB_DIR}', file))
3526 for file in implicit_libs]
3527 # The -B<dir>/ flag is necessary to tell gcc to look for crt[1in].o there.
3528 env.Prepend(LINKFLAGS=['-B${LIB_DIR}/'])
3530 AddImplicitLibs(nacl_env)
3531 AddImplicitLibs(nacl_irt_env)
3533 nacl_irt_env.Append(
3534 BUILD_SCONSCRIPTS = [
3535 'src/shared/gio/nacl.scons',
3536 'src/shared/platform/nacl.scons',
3537 'src/tools/tls_edit/build.scons',
3538 'src/untrusted/elf_loader/nacl.scons',
3539 'src/untrusted/irt/nacl.scons',
3540 'src/untrusted/nacl/nacl.scons',
3541 'src/untrusted/stubs/nacl.scons',
3542 'tests/irt_private_pthread/nacl.scons',
3544 nacl_irt_env.AddChromeFilesFromGroup('untrusted_irt_scons_files')
3546 environment_list.append(nacl_irt_env)
3548 # Since browser_tests already use the IRT normally, those are fully covered
3549 # in nacl_env. But the non_browser_tests don't use the IRT in nacl_env.
3550 # We want additional variants of those tests with the IRT, so we make
3551 # another environment and repeat them with that adjustment.
3552 nacl_irt_test_env = nacl_env.Clone(
3553 BUILD_TYPE = 'nacl_irt_test',
3554 BUILD_TYPE_DESCRIPTION = 'NaCl tests build with IRT',
3555 NACL_BUILD_FAMILY = 'UNTRUSTED_IRT_TESTS',
3556 NACL_ENV = nacl_env,
3558 INCLUDE_DIR = nacl_env.Dir('${INCLUDE_DIR}'),
3559 LIB_DIR = nacl_env.Dir('${LIB_DIR}'),
3560 BUILD_SCONSCRIPTS = [],
3562 nacl_irt_test_env.SetBits('tests_use_irt')
3563 if nacl_irt_test_env.Bit('enable_chrome_side'):
3564 nacl_irt_test_env.Replace(TESTRUNNER_LIBS=['testrunner_browser'])
3566 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_variant_tests)
3567 nacl_irt_test_env.AddChromeFilesFromGroup('irt_variant_test_scons_files')
3568 nacl_irt_test_env.Append(BUILD_SCONSCRIPTS=irt_only_tests)
3569 TestsUsePublicLibs(nacl_irt_test_env)
3570 TestsUsePublicListMappingsLib(nacl_irt_test_env)
3572 # We add the following settings after creating nacl_irt_test_env because we
3573 # don't want them to be inherited by nacl_irt_test_env.
3574 if nacl_env.Bit('nonsfi_nacl'):
3575 if nacl_env.Bit('pnacl_generate_pexe'):
3576 # Not-IRT-using non-SFI code uses Linux syscalls directly. Since this
3577 # involves using inline assembly, this requires turning off the PNaCl ABI
3579 nacl_env.SetBits('nonstable_bitcode')
3580 nacl_env.Append(LINKFLAGS=['--pnacl-disable-abi-check'])
3581 # Tell the PNaCl translator to link a Linux executable.
3582 nacl_env.Append(TRANSLATEFLAGS=['--noirt'])
3584 nacl_env.Append(LINKFLAGS=['--pnacl-allow-native', '-Wt,--noirt'])
3586 # If a tests/.../nacl.scons file builds a library, we will just use
3587 # the one already built in nacl_env instead.
3588 def IrtTestDummyLibrary(*args, **kwargs):
3590 nacl_irt_test_env.AddMethod(IrtTestDummyLibrary, 'ComponentLibrary')
3592 def IrtTestAddNodeToTestSuite(env, node, suite_name, node_name=None,
3593 is_broken=False, is_flaky=False,
3594 disable_irt_suffix=False):
3595 # The disable_irt_suffix argument is there for allowing tests
3596 # defined in nacl_irt_test_env to be part of chrome_browser_tests
3597 # (rather than part of chrome_browser_tests_irt).
3598 # TODO(mseaborn): But really, all of chrome_browser_tests should be
3599 # placed in nacl_irt_test_env rather than in nacl_env.
3600 suite_name = AddImplicitTestSuites(suite_name, node_name)
3601 if not disable_irt_suffix:
3602 if node_name is not None:
3604 suite_name = [name + '_irt' for name in suite_name]
3605 # NOTE: This needs to be called directly to as we're overriding the
3607 return AddNodeToTestSuite(env, node, suite_name, node_name,
3608 is_broken, is_flaky)
3609 nacl_irt_test_env.AddMethod(IrtTestAddNodeToTestSuite, 'AddNodeToTestSuite')
3611 environment_list.append(nacl_irt_test_env)
3614 windows_coverage_env = windows_debug_env.Clone(
3615 tools = ['code_coverage'],
3616 BUILD_TYPE = 'coverage-win',
3617 BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
3618 # TODO(bradnelson): switch nacl to common testing process so this won't be
3620 MANIFEST_FILE = None,
3621 COVERAGE_ANALYZER_DIR=r'..\third_party\coverage_analyzer\bin',
3622 COVERAGE_ANALYZER='$COVERAGE_ANALYZER_DIR\coverage_analyzer.exe',
3624 # TODO(bradnelson): Switch nacl to common testing process so this won't be
3625 # needed. Ignoring instrumentation failure as that's easier
3626 # than trying to gate out the ones with asm we can't handle.
3627 windows_coverage_env['LINKCOM'] = windows_coverage_env.Action([
3628 windows_coverage_env.get('LINKCOM', []),
3629 '-$COVERAGE_VSINSTR /COVERAGE ${TARGET}'])
3630 windows_coverage_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
3631 AddDualLibrary(windows_coverage_env)
3632 environment_list.append(windows_coverage_env)
3634 mac_coverage_env = mac_debug_env.Clone(
3635 tools = ['code_coverage'],
3636 BUILD_TYPE = 'coverage-mac',
3637 BUILD_TYPE_DESCRIPTION = 'MacOS code coverage build',
3638 # Strict doesnt't currently work for coverage because the path to gcov is
3639 # magically baked into the compiler.
3640 LIBS_STRICT = False,
3642 AddDualLibrary(mac_coverage_env)
3643 environment_list.append(mac_coverage_env)
3645 linux_coverage_env = linux_debug_env.Clone(
3646 tools = ['code_coverage'],
3647 BUILD_TYPE = 'coverage-linux',
3648 BUILD_TYPE_DESCRIPTION = 'Linux code coverage build',
3649 # Strict doesnt't currently work for coverage because the path to gcov is
3650 # magically baked into the compiler.
3651 LIBS_STRICT = False,
3654 linux_coverage_env.FilterOut(CCFLAGS=['-fPIE'])
3655 linux_coverage_env.Append(CCFLAGS=['-fPIC'])
3657 linux_coverage_env['OPTIONAL_COVERAGE_LIBS'] = '$COVERAGE_LIBS'
3658 AddDualLibrary(linux_coverage_env)
3659 environment_list.append(linux_coverage_env)
3662 # Environment Massaging
3663 RELEVANT_CONFIG = ['NACL_BUILD_FAMILY',
3667 'BUILD_TYPE_DESCRIPTION',
3670 MAYBE_RELEVANT_CONFIG = ['BUILD_OS',
3671 'BUILD_ARCHITECTURE',
3674 'TARGET_ARCHITECTURE',
3678 def DumpCompilerVersion(cc, env):
3680 env.Execute(env.Action('set'))
3681 env.Execute(env.Action('${CC} -v -c'))
3682 env.Execute(env.Action('${CC} -print-search-dirs'))
3683 env.Execute(env.Action('${CC} -print-libgcc-file-name'))
3684 elif cc.startswith('cl'):
3687 p = subprocess.Popen(env.subst('${CC} /V'),
3689 stdout=subprocess.PIPE,
3690 stderr=subprocess.PIPE)
3691 stdout, stderr = p.communicate()
3692 print(stderr[0:stderr.find("\r")])
3693 except WindowsError:
3694 # If vcvars was not run before running SCons, we won't be able to find
3695 # the compiler at this point. SCons has built in functions for finding
3696 # the compiler, but they haven't run yet.
3697 print('Can not find the compiler, assuming SCons will find it later.')
3699 print("UNKNOWN COMPILER")
3702 def SanityCheckEnvironments(all_envs):
3703 # simple completeness check
3704 for env in all_envs:
3705 for tag in RELEVANT_CONFIG:
3706 assert tag in env, repr(tag)
3707 assert env[tag], repr(env[tag])
3710 def LinkTrustedEnv(selected_envs):
3711 # Collect build families and ensure that we have only one env per family.
3713 for env in selected_envs:
3714 family = env['NACL_BUILD_FAMILY']
3715 if family not in family_map:
3716 family_map[family] = env
3718 msg = 'You are using incompatible environments simultaneously\n'
3719 msg += '%s vs %s\n' % (env['BUILD_TYPE'],
3720 family_map[family]['BUILD_TYPE'])
3721 msg += ('Please specfy the exact environments you require, e.g. '
3722 'MODE=dbg-host,nacl')
3723 raise Exception(msg)
3725 # Set TRUSTED_ENV so that tests of untrusted code can locate sel_ldr
3726 # etc. We set this on trusted envs too because some tests on
3727 # trusted envs run sel_ldr (e.g. using checked-in binaries).
3728 if 'TRUSTED' in family_map:
3729 for env in selected_envs:
3730 env['TRUSTED_ENV'] = family_map['TRUSTED']
3731 # Propagate some environment variables from the trusted environment,
3732 # in case some (e.g. Mac's DYLD_LIBRARY_PATH) are necessary for
3733 # running sel_ldr et al in untrusted environments' tests.
3734 for var in env['TRUSTED_ENV'].get('PROPAGATE_ENV', []):
3735 env['ENV'][var] = env['TRUSTED_ENV']['ENV'][var]
3736 if 'TRUSTED' not in family_map or 'UNTRUSTED' not in family_map:
3737 Banner('Warning: "--mode" did not specify both trusted and untrusted '
3738 'build environments. As a result, many tests will not be run.')
3741 build_platform = GetBuildPlatform()
3743 # Build Platform Base Function
3744 platform_func_map = {
3745 'win32' : MakeWindowsEnv,
3746 'cygwin': MakeWindowsEnv,
3747 'linux' : MakeGenericLinuxEnv,
3748 'linux2': MakeGenericLinuxEnv,
3749 'darwin': MakeMacEnv,
3751 if sys.platform not in platform_func_map:
3752 raise UserError('Unrecognized host platform: %s', sys.platform)
3753 make_env_func = platform_func_map[sys.platform]
3755 build_env = make_env_func(build_platform)
3756 build_env['IS_BUILD_ENV'] = True
3758 # Building tls_edit depends on gio, platform, and validator_ragel.
3759 build_env['BUILD_SCONSCRIPTS'] = [
3760 # KEEP THIS SORTED PLEASE
3761 'src/shared/gio/build.scons',
3762 'src/shared/platform/build.scons',
3763 'src/trusted/validator_ragel/build.scons',
3766 # The build environment is only used for intermediate steps and should
3767 # not be creating any targets. Aliases are used as means to add targets
3768 # to builds (IE, all_programs, all_libraries...etc.). Since we want to
3769 # share all of our build scripts but not define any aliases, we should
3770 # override the alias function and essentially stub it out.
3771 build_env.Alias = lambda env, target, source=[], actions=None, **kw : []
3775 def LinkBuildEnv(selected_envs):
3777 'opt': opt_build_env,
3778 'dbg': dbg_build_env,
3781 # We need to find the optimization level in order to know which
3782 # build environment we want to use
3784 for env in selected_envs:
3785 if env.get('OPTIMIZATION_LEVEL', None):
3786 opt_level = env['OPTIMIZATION_LEVEL']
3789 build_env = build_env_map.get(opt_level, opt_build_env)
3790 for env in selected_envs:
3791 env['BUILD_ENV'] = build_env
3793 # If the build environment is different from all the selected environments,
3794 # we will need to also append it to the selected environments so the targets
3796 build_env_root = build_env.subst('${TARGET_ROOT}')
3797 for env in selected_envs:
3798 if build_env_root == env.subst('${TARGET_ROOT}'):
3801 # Did not find a matching environment, append the build environment now.
3802 selected_envs.append(build_env)
3804 def DumpEnvironmentInfo(selected_envs):
3805 if VerboseConfigInfo(pre_base_env):
3806 Banner("The following environments have been configured")
3807 for env in selected_envs:
3808 for tag in RELEVANT_CONFIG:
3809 assert tag in env, repr(tag)
3810 print("%s: %s" % (tag, env.subst(env.get(tag))))
3811 for tag in MAYBE_RELEVANT_CONFIG:
3812 print("%s: %s" % (tag, env.subst(env.get(tag))))
3813 cc = env.subst('${CC}')
3815 asppcom = env.subst('${ASPPCOM}')
3816 print('ASPPCOM:', asppcom)
3817 DumpCompilerVersion(cc, env)
3819 rev_file = 'toolchain/linux_x86/pnacl_newlib_raw/REV'
3820 if os.path.exists(rev_file):
3821 for line in open(rev_file).read().split('\n'):
3822 if "Revision:" in line:
3823 print("PNACL : %s" % line)
3825 def PnaclSetEmulatorForSandboxedTranslator(selected_envs):
3826 # Slip in emulator flags if necessary, for the sandboxed pnacl translator
3827 # on ARM, once emulator is actually known (vs in naclsdk.py, where it
3828 # is not yet known).
3829 for env in selected_envs:
3830 if (env['NACL_BUILD_FAMILY'] != 'TRUSTED'
3831 and env.Bit('bitcode')
3832 and env.Bit('use_sandboxed_translator')
3833 and env.UsingEmulator()):
3834 # This must modify the LINK command itself, since LINKFLAGS may
3835 # be filtered (e.g., in barebones tests).
3836 env.Append(LINK=' --pnacl-use-emulator')
3837 env.Append(TRANSLATE=' --pnacl-use-emulator')
3840 # Blank out defaults.
3843 # Apply optional supplement if present in the directory tree.
3844 if os.path.exists(pre_base_env.subst('$MAIN_DIR/supplement/supplement.scons')):
3845 SConscript('supplement/supplement.scons', exports=['environment_list'])
3847 # print sytem info (optionally)
3848 if VerboseConfigInfo(pre_base_env):
3849 Banner('SCONS ARGS:' + str(sys.argv))
3850 os.system(pre_base_env.subst('${PYTHON} tools/sysinfo.py'))
3854 SanityCheckEnvironments(environment_list)
3855 selected_envs = FilterEnvironments(environment_list)
3857 # If we are building NaCl, build nacl_irt too. This works around it being
3858 # a separate mode due to the vagaries of scons when we'd really rather it
3859 # not be, while not requiring that every bot command line using --mode be
3860 # changed to list '...,nacl,nacl_irt' explicitly.
3861 if nacl_env in selected_envs:
3862 selected_envs.append(nacl_irt_env)
3864 # The nacl_irt_test_env requires nacl_env to build things correctly.
3865 if nacl_irt_test_env in selected_envs and nacl_env not in selected_envs:
3866 selected_envs.append(nacl_env)
3868 DumpEnvironmentInfo(selected_envs)
3869 LinkTrustedEnv(selected_envs)
3871 # When building NaCl, any intermediate build tool that is used during the
3872 # build process must be built using the current build environment, not the
3873 # target. Create a build environment for this purpose and link it into
3874 # the selected environments
3875 dbg_build_env, opt_build_env = GenerateOptimizationLevels(MakeBuildEnv())
3876 LinkBuildEnv(selected_envs)
3878 # This must happen after LinkTrustedEnv, since that is where TRUSTED_ENV
3879 # is finally set, and env.UsingEmulator() checks TRUSTED_ENV for the emulator.
3880 # This must also happen before BuildEnvironments.
3881 PnaclSetEmulatorForSandboxedTranslator(selected_envs)
3883 BuildEnvironments(selected_envs)
3885 # Change default to build everything, but not run tests.
3886 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
3889 # Sanity check whether we are ready to build nacl modules
3890 # NOTE: this uses stuff from: site_scons/site_tools/naclsdk.py
3891 if nacl_env.Bit('naclsdk_validate') and (nacl_env in selected_envs or
3892 nacl_irt_env in selected_envs):
3893 nacl_env.ValidateSdk()
3895 if BROKEN_TEST_COUNT > 0:
3896 msg = "There are %d broken tests." % BROKEN_TEST_COUNT
3897 if GetOption('brief_comstr'):
3898 msg += " Add --verbose to the command line for more information."
3901 # separate warnings from actual build output
3902 Banner('B U I L D - O U T P U T:')