Load 57 into trunk.
[nativeclient.git] / SConstruct
blob3f6e3ba34b82df8dbec052502535cfe14466bd36
1 # -*- python -*-
2 # Copyright 2008, Google Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 import glob
33 import os
34 import stat
35 import sys
36 sys.path.append("./common")
37 import nacl_util
40 # Underlay gtest
41 Dir('gtest').addRepository(Dir('../third_party/gtest/files'))
44 environment_list = []
46 # ----------------------------------------------------------
47 # Base environment for both nacl and non-nacl variants.
48 pre_base_env = Environment(
49 tools = ['component_setup'],
50 # Makes SOURCE_ROOT independent of site_init.
51 SOURCE_ROOT = Dir('#/../..').abspath,
52 # Publish dlls as final products (to staging).
53 COMPONENT_LIBRARY_PUBLISH = True,
55 pre_base_env.Append(BUILD_GROUPS=['most'])
56 # ----------------------------------------------------------
57 # Small tests are usually unit tests
59 def AddNodeToSmallTestsSuite(env, node):
60 Alias('small_tests', node)
62 pre_base_env.AddMethod(AddNodeToSmallTestsSuite)
64 # ----------------------------------------------------------
65 # Convenient alias
66 Alias('unit_tests', 'small_tests')
68 # ----------------------------------------------------------
69 # Medium tests are usually larger than unit tests, but don't take as much time
70 # as large tests
71 def AddNodeToMediumTestsSuite(env, node):
72 Alias('medium_tests', node)
74 pre_base_env.AddMethod(AddNodeToMediumTestsSuite)
76 # ----------------------------------------------------------
77 # Large tests are usually long tests
79 def AddNodeToLargeTestsSuite(env, node):
80 Alias('large_tests', node)
82 pre_base_env.AddMethod(AddNodeToLargeTestsSuite)
84 # ----------------------------------------------------------
86 def AddNodeToSmokeTestSuite(env, node):
87 env.Alias('smoke_test', node)
89 pre_base_env.AddMethod(AddNodeToSmokeTestSuite)
91 def _SmokeTestIntro(**args):
92 Banner("Running Smoke Test")
94 node = pre_base_env.Command(target='dummy',
95 source=[],
96 action=_SmokeTestIntro)
98 AlwaysBuild(node)
99 pre_base_env.AddNodeToSmokeTestSuite(node)
101 # ----------------------------------------------------------
102 def Banner(text):
103 print '=' * 70
104 print text
105 print '=' * 70
107 pre_base_env.AddMethod(Banner)
110 def FindLikelySelLdr(directory):
111 candidates = []
112 if (nacl_util.GetSelLdr('opt')):
113 candidates.append(nacl_util.GetSelLdr('opt'))
114 if (nacl_util.GetSelLdr('dbg')):
115 candidates.append(nacl_util.GetSelLdr('dbg'))
116 latest = (None, 0)
117 for c in candidates:
118 mtime = os.stat(c)[stat.ST_MTIME]
119 if mtime > latest[1]:
120 latest = (c, mtime)
121 return latest[0]
124 def CommandSelLdrTestNacl(env, name, exe, guess_sel_ldr=False, flags='" "',
125 stdin='None', stdout='None', filter='""',
126 stderr='None',
127 stderr_filter=('"^(NeverMatched AlwaysIgnoreStderr)'
128 '{999}"'),
129 exit_status=0,
130 log_golden='None', log_filter='".*"',
131 log_verbosity=2):
132 # TODO: retire the sel_ldr_tester.py script in favor of command_tester.py
134 # the default for stderr_filter is a heuristic: it should only
135 # match the phrase "NeverMatched AlwaysIgnoreStderr" repeated 999
136 # times, so should serve as a filter that ignores all stderr
137 # output. (There is, AFAIK, no regexp that always fails to match.)
138 # Since for non-death tests we had been ignoring stderr output,
139 # this way we get (approximately) the same behavior.
140 script = '${SCONSTRUCT_DIR}/tools/sel_ldr_tester.py'
142 if guess_sel_ldr:
143 sel_ldr = FindLikelySelLdr(env.subst('$DESTINATION_ROOT'))
144 # Bail out if sel_ldr can't be found.
145 if not sel_ldr: return []
146 else:
147 sel_ldr = '$STAGING_DIR/${PROGPREFIX}sel_ldr${PROGSUFFIX}'
148 deps = [script, sel_ldr, exe]
149 if stdin != 'None': deps.append(stdin)
150 if stdout != 'None': deps.append(stdout)
151 log_output = 'None'
152 if log_golden != 'None':
153 log_output = '${TARGET}.log'
154 # TODO: consider redirecting output into tests/results
155 return env.Command(name, deps,
156 '$PYTHON ${SOURCES[0].abspath} '
157 '${SOURCES[1].abspath} '
158 '${SOURCES[2].abspath} '
159 '%s %s %s %s %s %s %d %s %s %d %s > $TARGET' % (
160 flags, stdin, stdout, filter,
161 stderr, stderr_filter, exit_status,
162 log_golden, log_filter, log_verbosity, log_output))
164 pre_base_env.AddMethod(CommandSelLdrTestNacl)
166 # ----------------------------------------------------------
168 TEST_EXTRA_ARGS = ['stdin', 'stdout', 'stderr', 'log',
169 're_stdout', 're_stderr', 're_log']
170 TEST_SCRIPT = '${SCONSTRUCT_DIR}/tools/command_tester.py'
172 def CommandTestAgainstGoldenOuput(env, name, command, **extra):
173 script_flags = ['--name', name]
174 deps = [TEST_SCRIPT]
176 for n, c in enumerate(command):
177 if type(c) != str:
178 deps.append(c)
179 command[n] = '${SOURCES[%d].abspath}' % (len(deps) - 1)
181 for e in extra:
182 assert e in TEST_EXTRA_ARGS
183 if type(extra[e]) != str:
184 deps.append(extra[e])
185 extra[e] = '${SOURCES[%d].abspath}' % (len(deps) - 1)
186 script_flags.append('--' + e)
187 script_flags.append(extra[e])
189 # NOTE: "SOURCES[X]" references the scons object in deps[x]
190 command = ['${PYTHON}',
191 '${SOURCES[0].abspath}',
192 ' '.join(script_flags),
193 ' '.join(command),
194 '> ${TARGET}',
197 # TODO: consider redirecting output into tests/results
198 return env.Command(name, deps, " ".join(command))
200 pre_base_env.AddMethod(CommandTestAgainstGoldenOuput)
201 # ----------------------------------------------------------
202 if ARGUMENTS.get('pp', 0):
203 def CommandPrettyPrinter(cmd, targets, source, env):
204 prefix = env.subst('$SOURCE_ROOT') + '/googleclient/'
205 target = targets[0]
206 cmd_tokens = cmd.split()
207 if "python" in cmd_tokens[0]:
208 cmd_name = cmd_tokens[1]
209 else:
210 cmd_name = cmd_tokens[0].split('(')[0]
211 if cmd_name.startswith(prefix):
212 cmd_name = cmd_name[len(prefix):]
213 env_name = env.subst('${BUILD_TYPE}${BUILD_SUBTYPE}')
214 print '[%s] [%s] %s' % (cmd_name, env_name, target.get_path())
215 pre_base_env.Append(PRINT_CMD_LINE_FUNC = CommandPrettyPrinter)
217 # ----------------------------------------------------------
218 base_env = pre_base_env.Clone()
219 base_env.Append(
220 BUILD_SUBTYPE = '',
221 BUILD_SCONSCRIPTS = [
222 # NOTE: this dir also has a nacl.scons
223 'tests/npapi_bridge/build.scons',
224 'ncv/build.scons',
225 'platform_qual_test/build.scons',
226 'service_runtime/build.scons',
227 'service_runtime/nrd_xfer_lib/build.scons',
228 'tools/libsrpc/build.scons',
229 'tools/npapi_runtime/build.scons',
230 'intermodule_comm/build.scons',
231 'npapi_plugin/build.scons',
232 'npapi_plugin/install.scons',
233 'gtest/build.scons',
234 'nonnacl_util/build.scons',
235 # 'nacl_ie_plugin/build.scons',
237 CPPDEFINES = [
238 ['NACL_BLOCK_SHIFT', '5'],
239 ['NACL_BLOCK_SIZE', '32'],
241 GEN2_FLAGS = '-c -f "Video|Audio|Multimedia"',
243 base_env.Replace(
244 SDL_HERMETIC_LINUX_DIR='$MAIN_DIR/../third_party/sdl/linux/v1_2_13',
245 SDL_HERMETIC_MAC_DIR='$MAIN_DIR/../third_party/sdl/osx/v1_2_13',
246 SDL_HERMETIC_WINDOWS_DIR='$MAIN_DIR/../third_party/sdl/win/v1_2_13',
251 # Optionally ignore the build process.
252 DeclareBit('prebuilt', 'Disable all build steps, only support install steps')
253 base_env.SetBitFromOption('prebuilt', False)
254 if base_env.Bit('prebuilt'):
255 base_env.Replace(BUILD_SCONSCRIPTS = ['npapi_plugin/install.scons'])
257 # Add the sdk root path (without setting up the tools).
258 base_env['NACL_SDK_ROOT_ONLY'] = True
259 base_env.Tool('naclsdk')
262 base_env.Help("""\
263 ======================================================================
264 Help for NaCl
265 ======================================================================
267 Common tasks:
268 -------------
270 * cleaning: scons -c
271 * building: scons
272 * + nacl: scons -c MODE=most
273 * + doc and more: scons -c MODE=all
274 * just the doc: scons MODE=doc
275 * build mandel: scons MODE=most mandel.nexe
276 * some unittests: scons small_tests
277 * a smoke test: scons -k pp=1 smoke_test
278 * 2nd smoke test: scons -k pp=1 MODE=nacl smoke_test
279 * firefox plugin: scons MODE=opt-linux npGoogleNaClPlugin
280 * sel_ldr: scons MODE=opt-linux sel_ldr
281 * firefox install: scons firefox_install
282 * firefox install pre-built copy: scons firefox_install --prebuilt
284 Options:
285 --------
286 pp=1 use command line pretty printing (more concise output)
287 sdl=<mode> where <mode>:
288 'none': don't use SDL (default)
289 'local': use locally installed SDL
290 'hermetic': use the hermetic SDL copy
291 naclsdk_mode=<mode> where <mode>:
292 'local': use locally installed sdk kit
293 'download': use the download copy (default)
294 'custom:<path>': use kit at <path>
296 --prebuilt Do not build things, just do install steps
298 Automagically generated help:
299 -----------------------------
300 """)
302 # ----------------------------------------------------------
303 windows_env = base_env.Clone(
304 tools = ['target_platform_windows'],
305 ASCOM = '$ASPPCOM /E | as -o $TARGET',
306 PDB = '${TARGET.base}.pdb',
308 windows_env.Append(
309 CPPDEFINES = [
310 ['NACL_WINDOWS', '1'],
311 ['NACL_OSX', '0'],
312 ['NACL_LINUX', '0'],
313 ['_WIN32_WINNT', '0x0501']
315 NACL_PLATFORM = 'win',
316 LIBS = ['wsock32', 'advapi32'],
317 CCFLAGS = ['/EHsc', '/WX'],
320 windows_debug_env = windows_env.Clone(
321 tools = ['target_debug'],
322 BUILD_TYPE = 'dbg-win',
323 BUILD_TYPE_DESCRIPTION = 'Windows debug build',
326 windows_debug_env.Append(BUILD_GROUPS = ['default'])
327 environment_list.append(windows_debug_env)
329 windows_optimized_env = windows_env.Clone(
330 tools = ['target_optimized'],
331 BUILD_TYPE = 'opt-win',
332 BUILD_TYPE_DESCRIPTION = 'Windows optimized build',
334 environment_list.append(windows_optimized_env)
336 if ARGUMENTS.get('sdl', 'hermetic') != 'none':
337 # These will only apply to sdl!=none builds!
338 windows_debug_env.Append(
339 CPPDEFINES = [
340 '_DLL',
341 '_MT'])
342 windows_optimized_env.Append(
343 CPPDEFINES = [
344 '_DLL',
345 '_MT'])
346 # SDL likes DLLs
347 if '/MT' in windows_optimized_env['CCFLAGS']:
348 windows_optimized_env.FilterOut(CCFLAGS=['/MT']);
349 windows_optimized_env.Append(CCFLAGS=['/MD']);
350 if '/MTd' in windows_debug_env['CCFLAGS']:
351 windows_debug_env.FilterOut(CCFLAGS=['/MTd']);
352 windows_debug_env.Append(CCFLAGS=['/MDd']);
353 # this doesn't feel right, but fixes dbg-win
354 windows_debug_env.Append(LINKFLAGS = ['/NODEFAULTLIB:msvcrt'])
355 # make source level debugging a little easier
356 if '/Z7' not in windows_debug_env['CCFLAGS']:
357 if '/Zi' not in windows_debug_env['CCFLAGS']:
358 windows_debug_env.Append(CCFLAGS=['/Z7'])
360 # ----------------------------------------------------------
362 unix_like_env = base_env.Clone()
363 unix_like_env.Append(
364 CCFLAGS = [
365 # '-malign-double',
366 '-Werror',
367 '-Wall',
368 # '-Wswitch-enum',
369 '-fvisibility=hidden',
370 '-Wno-unused-variable',
371 # '-Wsign-compare',
373 CFLAGS = ['-std=gnu99'],
374 LIBS = ['pthread', 'ssl', 'crypto'],
377 # ----------------------------------------------------------
379 mac_env = unix_like_env.Clone(
380 tools = ['target_platform_mac'],
381 # TODO: this should really be able to live in unix_like_env
382 # but can't due to what the target_platform_x module is
383 # doing.
384 LINK = '$CXX',
385 PLUGIN_SUFFIX = '.bundle',
387 mac_env.Append(
388 CPPDEFINES = [
389 ['NACL_WINDOWS', '0'],
390 ['NACL_OSX', '1'],
391 ['NACL_LINUX', '0'],
392 ['MAC_OS_X_VERSION_MIN_REQUIRED', 'MAC_OS_X_VERSION_10_4'],
394 NACL_PLATFORM = 'osx',
395 CCFLAGS = ['-mmacosx-version-min=10.4']
398 mac_debug_env = mac_env.Clone(
399 tools = ['target_debug'],
400 BUILD_TYPE = 'dbg-mac',
401 BUILD_TYPE_DESCRIPTION = 'MacOS debug build',
403 mac_debug_env.Append(BUILD_GROUPS = ['default'])
404 environment_list.append(mac_debug_env)
406 mac_optimized_env = mac_env.Clone(
407 tools = ['target_optimized'],
408 BUILD_TYPE = 'opt-mac',
409 BUILD_TYPE_DESCRIPTION = 'MacOS optimized build',
411 environment_list.append(mac_optimized_env)
413 # ----------------------------------------------------------
415 linux_env = unix_like_env.Clone(
416 tools = ['target_platform_linux'],
417 # TODO: this should really be able to live in unix_like_env
418 # but can't due to what the target_platform_x module is
419 # doing.
420 LINK = '$CXX',
423 # -m32 and -L/usr/lib32 are needed to do 32-bit builds on 64-bit
424 # user-space machines; requires ia32-libs-dev to be installed; or,
425 # failing that, ia32-libs and symbolic links *manually* created for
426 # /usr/lib32/libssl.so and /usr/lib32/libcrypto.so to the current
427 # /usr/lib32/lib*.so.version (tested with ia32-libs 2.2ubuntu11; no
428 # ia32-libs-dev was available for testing).
429 # Additional symlinks of this sort are needed for gtk,
430 # see nonnacl_util/build.scons.
432 linux_env.SetDefault(
433 # NOTE: look into http://www.scons.org/wiki/DoxygenBuilder
434 DOXYGEN = ARGUMENTS.get('DOXYGEN', '/usr/bin/doxygen'),
437 linux_env.Append(
438 ASFLAGS = [ '-m32', ],
439 CFLAGS = [ '-m32', ],
440 CCFLAGS = [ '-m32', ],
441 CPPDEFINES = [
442 ['NACL_WINDOWS', '0'],
443 ['NACL_OSX', '0'],
444 ['NACL_LINUX', '1'],
446 LIBS = ['rt'],
447 LINKFLAGS = [ '-m32', '-L/usr/lib32', ],
448 NACL_PLATFORM = 'linux',
452 linux_debug_env = linux_env.Clone(
453 tools = ['target_debug'],
454 BUILD_TYPE = 'dbg-linux',
455 BUILD_TYPE_DESCRIPTION = 'Linux debug build',
457 linux_debug_env.Append(BUILD_GROUPS = ['default'])
458 environment_list.append(linux_debug_env)
460 linux_optimized_env = linux_env.Clone(
461 tools = ['target_optimized'],
462 BUILD_TYPE = 'opt-linux',
463 BUILD_TYPE_DESCRIPTION = 'Linux optimized build',
465 environment_list.append(linux_optimized_env)
468 # ----------------------------------------------------------
469 # The nacl_env is used to build native_client modules
470 # using a special tool chain which produces platform
471 # independent binaries
472 # ----------------------------------------------------------
473 nacl_env = pre_base_env.Clone(
474 tools = ['naclsdk'],
475 BUILD_TYPE = 'nacl',
476 BUILD_TYPE_DESCRIPTION = 'NaCl module build',
477 # TODO: explain this
478 LINK = '$CXX',
479 # TODO: This doesn't work at the moment due to a scons
480 # limitation. Commented out until scons is fixed.
481 # hook for app to specify extra libraries
482 #LIBS = "$EXTRA_LIBS",
483 # optimize binaries
484 CCFLAGS = ['-O2', '-mfpmath=sse', '-msse', '-fomit-frame-pointer'],
485 # TODO: explain this
486 CPPPATH = ['$SOURCE_ROOT/googleclient'],
489 Banner('Building nexe binaries using sdk at [%s]' %
490 nacl_env.subst('$NACL_SDK_ROOT'))
493 nacl_env.Append(
494 BUILD_SCONSCRIPTS = [
495 #### ALPHABETICALLY SORTED ####
496 'intermodule_comm/nacl.scons',
499 'tests/app_lib/nacl.scons',
500 'tests/contest_issues/nacl.scons',
501 'tests/cloudfs/nacl.scons',
502 'tests/earth/nacl.scons',
503 'tests/fib/nacl.scons',
504 'tests/file/nacl.scons',
505 'tests/hello_world/nacl.scons',
506 'tests/imc_shm_mmap/nacl.scons',
507 'tests/life/nacl.scons',
508 'tests/mandel/nacl.scons',
509 'tests/mandel_nav/nacl.scons',
510 'tests/many/nacl.scons',
511 'tests/mmap/nacl.scons',
512 'tests/noop/nacl.scons',
513 'tests/npapi_bridge/nacl.scons',
514 'tests/npapi_hw/nacl.scons',
515 'tests/npapi_pi/nacl.scons',
516 'tests/nrd_xfer/nacl.scons',
517 'tests/null/nacl.scons',
518 'tests/nullptr/nacl.scons',
519 'tests/srpc/nacl.scons',
520 'tests/srpc_hw/nacl.scons',
521 'tests/syscalls/nacl.scons',
522 'tests/threads/nacl.scons',
523 'tests/tone/nacl.scons',
524 'tests/voronoi/nacl.scons',
526 'tools/stubs/nacl.scons',
527 'tools/libnacl/nacl.scons',
528 'tools/libsrpc/nacl.scons',
529 'tools/nc_threads/nacl.scons',
530 'tools/libav/nacl.scons',
531 'tools/libunimpl/nacl.scons',
532 'tools/npapi_runtime/nacl.scons',
533 #### ALPHABETICALLY SORTED ####
537 # Uncomment this if you want the nacl stuff to be build by default.
538 #nacl_env.Append(BUILD_GROUPS = ['default'])
539 environment_list.append(nacl_env)
541 # ----------------------------------------------------------
542 # CODE COVERAGE
543 # ----------------------------------------------------------
544 # ----------------------------------------------------------
545 # VARIOUS HELPERS
546 # ----------------------------------------------------------
548 doc_env = pre_base_env.Clone(
549 BUILD_TYPE = 'doc',
550 BUILD_TYPE_DESCRIPTION = 'Documentation build',
551 HOST_PLATFORMS = '*',
553 doc_env.FilterOut(BUILD_GROUPS=['most'])
554 environment_list.append(doc_env)
555 doc_env.Append(
556 BUILD_SCONSCRIPTS = [
557 'documentation',
562 # ----------------------------------------------------------
564 # Blank out defaults.
565 Default(None)
567 BuildComponents(environment_list)
569 # Change default to build everything, but not run tests.
570 Default(['all_programs', 'all_bundles', 'all_test_programs', 'all_libraries'])
572 # ----------------------------------------------------------
575 # Generate a solution, defer to the end.
576 solution_env = base_env.Clone(tools = ['visual_studio_solution'])
577 solution = solution_env.Solution(
578 'nacl', environment_list,
579 exclude_pattern = '.*third_party.*',
580 extra_build_targets = {
581 'Firefox': 'c:/Program Files/Mozilla FireFox/firefox.exe',
584 solution_env.Alias('solution', solution)