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 """Recipes for NativeClient toolchain packages.
8 The real entry plumbing is in toolchain_main.py.
17 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
18 import pynacl.gsd_storage
19 import pynacl.platform
25 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
26 NACL_DIR = os.path.dirname(SCRIPT_DIR)
29 # See command.GenerateGitPatches for the schema of entries in this dict.
30 # Additionally, each may contain a 'repo' key whose value is the name
31 # to use in place of the package name when calling GitUrl (below).
34 'rev': '7deface59753c3b249ac08d854d471951796343f',
35 'upstream-branch': 'upstream/binutils-2_24-branch',
36 'upstream-name': 'binutils-2.24',
37 # This is tag binutils-2_24, but Gerrit won't let us push
38 # non-annotated tags, and the upstream tag is not annotated.
39 'upstream-base': '237df3fa4a1d939e6fd1af0c3e5029a25a137310',
42 'rev': 'a2e4a3140c035233409598487c56b76108f8c74d',
43 'upstream-branch': 'upstream/gcc-4_8-branch',
44 'upstream-name': 'gcc-4.8.2',
45 # Upstream tag gcc-4_8_2-release:
46 'upstream-base': '9bcca88e24e64d4e23636aafa3404088b13bcb0e',
49 'rev': 'a9ae3c60b36dea3d8a10e18b1b6db952d21268c2',
50 'upstream-branch': 'upstream/master',
51 'upstream-name': 'newlib-2.0.0',
52 # Upstream tag newlib_2_0_0:
53 'upstream-base': 'c3fc84e062cacc2b3e13c1f6b9151d0cc85392ba',
56 'rev': '41afdf9d511d95073c4403c838d8ccba582d8eed',
58 'upstream-branch': 'upstream/gdb-7.7-branch',
59 'upstream-name': 'gdb-7.7',
60 # Upstream tag gdb-7.7-release:
61 'upstream-base': 'fe284cd86ba9761655a9281fef470d364e27eb85',
66 'gmp': command.path.join('gmp', 'gmp-5.1.3.tar.bz2'),
67 'mpfr': command.path.join('mpfr', 'mpfr-3.1.2.tar.bz2'),
68 'mpc': command.path.join('mpc', 'mpc-1.0.2.tar.gz'),
69 'isl': command.path.join('cloog', 'isl-0.12.2.tar.bz2'),
70 'cloog': command.path.join('cloog', 'cloog-0.18.1.tar.gz'),
71 'expat': command.path.join('expat', 'expat-2.0.1.tar.gz'),
74 GIT_BASE_URL = 'https://chromium.googlesource.com/native_client'
78 repo = GIT_REVISIONS[package].get('repo', package)
79 return '%s/nacl-%s.git' % (GIT_BASE_URL, repo)
85 for package in TAR_FILES:
86 tar_file = TAR_FILES[package]
87 if fnmatch.fnmatch(tar_file, '*.bz2'):
88 extract = EXTRACT_STRIP_TBZ2
89 elif fnmatch.fnmatch(tar_file, '*.gz'):
90 extract = EXTRACT_STRIP_TGZ
92 raise Exception('unexpected file name pattern in TAR_FILES[%r]' % package)
96 command.Command(extract + [command.path.join('%(abs_top_srcdir)s',
105 for package, info in GIT_REVISIONS.iteritems():
108 'commands': [command.SyncGitRepo(GitUrl(package), '%(output)s',
111 patch_packages.append(package)
112 patch_commands.append(
113 command.GenerateGitPatches('%(' + package + ')s/.git', info))
115 sources['patches'] = {
117 'dependencies': patch_packages,
118 'commands': patch_commands,
121 # The gcc_libs component gets the whole GCC source tree.
122 sources['gcc_libs'] = sources['gcc']
124 # The gcc component omits all the source directories that are used solely
125 # for building target libraries. We don't want those included in the
126 # input hash calculation so that we don't rebuild the compiler when the
127 # the only things that have changed are target libraries.
130 'dependencies': ['gcc_libs'],
131 'commands': [command.CopyTree('%(gcc_libs)s', '%(output)s', [
151 # We have to populate the newlib source tree with the "exported" form of
152 # some headers from the native_client source tree. The newlib build
153 # needs these to be in the expected place. By doing this in the source
154 # target, these files will be part of the input hash and so we don't need
155 # to do anything else to keep track of when they might have changed in
156 # the native_client source tree.
157 newlib_sys_nacl = command.path.join('%(output)s',
158 'newlib', 'libc', 'sys', 'nacl')
159 newlib_unpack = [command.RemoveDirectory(command.path.join(newlib_sys_nacl,
161 for dirname in ['bits', 'sys', 'machine']]
162 newlib_unpack.append(command.Command([
164 command.path.join('%(top_srcdir)s', 'src',
165 'trusted', 'service_runtime', 'export_header.py'),
166 command.path.join('%(top_srcdir)s', 'src',
167 'trusted', 'service_runtime', 'include'),
170 sources['newlib']['commands'] += newlib_unpack
175 # Canonical tuples we use for hosts.
176 WINDOWS_HOST_TUPLE = pynacl.platform.PlatformTriple('win', 'x86-64')
177 MAC_HOST_TUPLE = pynacl.platform.PlatformTriple('darwin', 'x86-64')
178 ARM_HOST_TUPLE = pynacl.platform.PlatformTriple('linux', 'arm')
179 LINUX_X86_32_TUPLE = pynacl.platform.PlatformTriple('linux', 'x86-32')
180 LINUX_X86_64_TUPLE = pynacl.platform.PlatformTriple('linux', 'x86-64')
182 # Map of native host tuple to extra tuples that it cross-builds for.
184 LINUX_X86_64_TUPLE: [
191 # Map of native host tuple to host tuples that are "native enough".
192 # For these hosts, we will do a native-style build even though it's
193 # not the native tuple, just passing some extra compiler flags.
194 NATIVE_ENOUGH_MAP = {
195 LINUX_X86_64_TUPLE: {
196 LINUX_X86_32_TUPLE: ['-m32'],
201 # The list of targets to build toolchains for.
202 TARGET_LIST = ['arm', 'i686']
204 # These are extra arguments to pass gcc's configure that vary by target.
205 TARGET_GCC_CONFIG = {
206 # TODO(mcgrathr): Disabled tuning for now, tickling a constant-pool layout bug.
207 # 'arm': ['--with-tune=cortex-a15'],
210 PACKAGE_NAME = 'Native Client SDK [%(build_signature)s]'
211 BUG_URL = 'http://gonacl.com/reportissue'
213 TAR_XV = ['tar', '-x', '-v']
214 EXTRACT_STRIP_TGZ = TAR_XV + ['--gzip', '--strip-components=1', '-f']
215 EXTRACT_STRIP_TBZ2 = TAR_XV + ['--bzip2', '--strip-components=1', '-f']
216 CONFIGURE_CMD = ['sh', '%(src)s/configure']
217 MAKE_PARALLEL_CMD = ['make', '-j%(cores)s']
218 MAKE_CHECK_CMD = MAKE_PARALLEL_CMD + ['check']
219 MAKE_DESTDIR_CMD = ['make', 'DESTDIR=%(abs_output)s']
221 # This file gets installed by multiple packages' install steps, but it is
222 # never useful when installed in isolation. So we remove it from the
223 # installation directories before packaging up.
224 REMOVE_INFO_DIR = command.Remove(command.path.join('%(output)s',
225 'share', 'info', 'dir'))
227 def ConfigureHostArch(host):
230 is_cross = CrossCompiling(host)
234 configure_args.append('--host=' + host)
236 extra_cc_args = NATIVE_ENOUGH_MAP.get(NATIVE_TUPLE, {}).get(host, [])
238 # The host we've chosen is "native enough", such as x86-32 on x86-64.
239 # But it's not what config.guess will yield, so we need to supply
240 # a --build switch to ensure things build correctly.
241 configure_args.append('--build=' + host)
243 extra_cxx_args = list(extra_cc_args)
244 if fnmatch.fnmatch(host, '*-linux*'):
245 # Avoid shipping binaries with a runtime dependency on
246 # a particular version of the libstdc++ shared library.
247 # TODO(mcgrathr): Do we want this for MinGW and/or Mac too?
248 extra_cxx_args.append('-static-libstdc++')
251 # These are the defaults when there is no setting, but we will add
252 # additional switches, so we must supply the command name too.
257 configure_args.append('CC=' + ' '.join([cc] + extra_cc_args))
260 # These are the defaults when there is no setting, but we will add
261 # additional switches, so we must supply the command name too.
266 configure_args.append('CXX=' + ' '.join([cxx] + extra_cxx_args))
268 if HostIsWindows(host):
269 # The i18n support brings in runtime dependencies on MinGW DLLs
270 # that we don't want to have to distribute alongside our binaries.
271 # So just disable it, and compiler messages will always be in US English.
272 configure_args.append('--disable-nls')
274 return configure_args
277 def ConfigureHostCommon(host):
278 return ConfigureHostArch(host) + [
280 '--disable-silent-rules',
281 '--without-gcc-arch',
285 def ConfigureHostLib(host):
286 return ConfigureHostCommon(host) + [
291 def ConfigureHostTool(host):
292 return ConfigureHostCommon(host) + [
293 '--with-pkgversion=' + PACKAGE_NAME,
294 '--with-bugurl=' + BUG_URL,
299 def MakeCommand(host, extra_args=[]):
300 if HostIsWindows(host):
301 # There appears to be nothing we can pass at top-level configure time
302 # that will prevent the configure scripts from finding MinGW's libiconv
303 # and using it. We have to force this variable into the environment
304 # of the sub-configure runs, which are run via make.
305 make_command = MAKE_PARALLEL_CMD + ['HAVE_LIBICONV=no']
307 make_command = MAKE_PARALLEL_CMD
308 return make_command + extra_args
311 # Return the 'make check' command to run.
312 # When cross-compiling, don't try to run test suites.
313 def MakeCheckCommand(host):
314 if CrossCompiling(host):
316 return MAKE_CHECK_CMD
319 def InstallDocFiles(subdir, files):
320 doc_dir = command.path.join('%(output)s', 'share', 'doc', subdir)
321 dirs = sorted(set([command.path.dirname(command.path.join(doc_dir, file))
323 commands = ([command.Mkdir(dir, parents=True) for dir in dirs] +
324 [command.Copy(command.path.join('%(' + subdir + ')s', file),
325 command.path.join(doc_dir, file))
330 def NewlibLibcScript(arch):
332 * This is a linker script that gets installed as libc.a for the
333 * newlib-based NaCl toolchain. It brings in the constituent
334 * libraries that make up what -lc means semantically.
337 GROUP ( libnacl.a libcrt_common.a )
340 # Listing three formats instead of one makes -EL/-EB switches work
341 # for the endian-switchable ARM backend.
342 format_list = ['elf32-littlearm-nacl',
344 'elf32-littlearm-nacl']
346 format_list = 'elf32-i386-nacl'
347 elif arch == 'x86_64':
348 format_list = 'elf32-x86_64-nacl'
350 raise Exception('TODO(mcgrathr): OUTPUT_FORMAT for %s' % arch)
351 return template % ', '.join(['"' + fmt + '"' for fmt in format_list])
354 # The default strip behavior removes debugging and symbol table
355 # sections, but it leaves the .comment section. This contains the
356 # compiler version string, and so it changes when the compiler changes
357 # even if the actual machine code it produces is completely identical.
358 # Hence, the target library packages will always change when the
359 # compiler changes unless these sections are removed. Doing this
360 # requires somehow teaching the makefile rules to pass the
361 # --remove-section=.comment switch to TARGET-strip. For the GCC
362 # target libraries, setting STRIP_FOR_TARGET is sufficient. But
363 # quoting nightmares make it difficult to pass a command with a space
364 # in it as the STRIP_FOR_TARGET value. So the build writes a little
365 # script that can be invoked with a simple name.
367 # Though the gcc target libraries' makefiles are smart enough to obey
368 # STRIP_FOR_TARGET for library files, the newlib makefiles just
369 # blindly use $(INSTALL_DATA) for both header (text) files and library
370 # files. Hence it's necessary to override its INSTALL_DATA setting to
371 # one that will do stripping using this script, and thus the script
372 # must silently do nothing to non-binary files.
373 def ConfigureTargetPrep(arch):
374 script_file = 'strip_for_target'
376 config_target = arch + '-nacl'
377 script_contents = """\
384 type=`file --brief --mime-type "$arg"`
386 application/x-executable|application/x-sharedlib) ;;
387 application/x-archive|application/x-object) mode=--strip-debug ;;
393 exec %s-strip $mode --remove-section=.comment "$@"
397 command.WriteData(script_contents, script_file),
398 command.Command(['chmod', '+x', script_file]),
402 def ConfigureTargetArgs(arch):
403 config_target = arch + '-nacl'
405 '--target=' + config_target,
406 '--with-sysroot=/' + config_target,
407 'STRIP_FOR_TARGET=%(cwd)s/strip_for_target',
411 def CommandsInBuild(command_lines):
413 command.RemoveDirectory('build'),
414 command.Mkdir('build'),
415 ] + [command.Command(cmd, cwd='build')
416 for cmd in command_lines]
419 def PopulateDeps(dep_dirs):
420 commands = [command.RemoveDirectory('all_deps'),
421 command.Mkdir('all_deps')]
422 commands += [command.Command('cp -r "%s/"* all_deps' % dirname, shell=True)
423 for dirname in dep_dirs]
427 def WithDepsOptions(options, component=None):
428 if component is None:
429 directory = command.path.join('%(cwd)s', 'all_deps')
431 directory = '%(abs_' + component + ')s'
432 return ['--with-' + option + '=' + directory
433 for option in options]
436 # Return the component name we'll use for a base component name and
437 # a host tuple. The component names cannot contain dashes or other
438 # non-identifier characters, because the names of the files uploaded
439 # to Google Storage are constrained. GNU configuration tuples contain
440 # dashes, which we translate to underscores.
441 def ForHost(component_name, host):
442 return component_name + '_' + pynacl.gsd_storage.LegalizeName(host)
445 # These are libraries that go into building the compiler itself.
446 def HostGccLibs(host):
447 def H(component_name):
448 return ForHost(component_name, host)
452 'dependencies': ['gmp'],
454 command.Command(ConfigureCommand('gmp') +
455 ConfigureHostLib(host) + [
456 '--with-sysroot=%(abs_output)s',
458 # Without this, the built library will
459 # assume the instruction set details
460 # available on the build machine. With
461 # this, it dynamically chooses what code
462 # to use based on the details of the
463 # actual host CPU at runtime.
466 command.Command(MakeCommand(host)),
467 command.Command(MakeCheckCommand(host)),
468 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
473 'dependencies': ['mpfr', H('gmp')],
475 command.Command(ConfigureCommand('mpfr') +
476 ConfigureHostLib(host) +
477 WithDepsOptions(['sysroot', 'gmp'], H('gmp'))),
478 command.Command(MakeCommand(host)),
479 command.Command(MakeCheckCommand(host)),
480 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
485 'dependencies': ['mpc', H('gmp'), H('mpfr')],
486 'commands': PopulateDeps(['%(' + H('gmp') + ')s',
487 '%(' + H('mpfr') + ')s']) + [
488 command.Command(ConfigureCommand('mpc') +
489 ConfigureHostLib(host) +
490 WithDepsOptions(['sysroot', 'gmp', 'mpfr'])),
491 command.Command(MakeCommand(host)),
492 command.Command(MakeCheckCommand(host)),
493 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
498 'dependencies': ['isl', H('gmp')],
500 command.Command(ConfigureCommand('isl') +
501 ConfigureHostLib(host) +
502 WithDepsOptions(['sysroot', 'gmp-prefix'],
504 command.Command(MakeCommand(host)),
505 command.Command(MakeCheckCommand(host)),
506 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
507 # The .pc files wind up containing some absolute paths
508 # that make the output depend on the build directory name.
509 # The dependents' configure scripts don't need them anyway.
510 command.RemoveDirectory(command.path.join(
511 '%(output)s', 'lib', 'pkgconfig')),
516 'dependencies': ['cloog', H('gmp'), H('isl')],
517 'commands': PopulateDeps(['%(' + H('gmp') + ')s',
518 '%(' + H('isl') + ')s']) + [
519 command.Command(ConfigureCommand('cloog') +
520 ConfigureHostLib(host) + [
523 ] + WithDepsOptions(['sysroot',
526 command.Command(MakeCommand(host)),
527 command.Command(MakeCheckCommand(host)),
528 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
529 # The .pc files wind up containing some absolute paths
530 # that make the output depend on the build directory name.
531 # The dependents' configure scripts don't need them anyway.
532 command.RemoveDirectory(command.path.join(
533 '%(output)s', 'lib', 'pkgconfig')),
538 'dependencies': ['expat'],
540 command.Command(ConfigureCommand('expat') +
541 ConfigureHostLib(host)),
542 command.Command(MakeCommand(host)),
543 command.Command(MakeCheckCommand(host)),
544 command.Command(MAKE_DESTDIR_CMD + [
545 # expat does not support the install-strip target.
547 'INSTALL=%(expat)s/conftools/install-sh -c -s',
548 'INSTALL_DATA=%(expat)s/conftools/install-sh -c -m 644',
556 HOST_GCC_LIBS_DEPS = ['gmp', 'mpfr', 'mpc', 'isl', 'cloog']
558 def HostGccLibsDeps(host):
559 return [ForHost(package, host) for package in HOST_GCC_LIBS_DEPS]
562 def ConfigureCommand(source_component):
563 return [command % {'src': '%(' + source_component + ')s'}
564 for command in CONFIGURE_CMD]
567 # When doing a Canadian cross, we need native-hosted cross components
568 # to do the GCC build.
569 def GccDeps(host, target):
570 components = ['binutils_' + target]
571 if CrossCompiling(host):
572 components.append('gcc_' + target)
574 return [ForHost(component, host) for component in components]
577 def GccCommand(host, target, cmd):
578 components_for_path = GccDeps(host, target)
579 return command.Command(
580 cmd, path_dirs=[command.path.join('%(abs_' + component + ')s', 'bin')
581 for component in components_for_path])
584 def ConfigureGccCommand(source_component, host, target, extra_args=[]):
588 ConfigureCommand(source_component) +
589 ConfigureHostTool(host) +
590 ConfigureTargetArgs(target) +
591 TARGET_GCC_CONFIG.get(target, []) + [
592 '--with-gmp=%(abs_' + ForHost('gmp', host) + ')s',
593 '--with-mpfr=%(abs_' + ForHost('mpfr', host) + ')s',
594 '--with-mpc=%(abs_' + ForHost('mpc', host) + ')s',
595 '--with-isl=%(abs_' + ForHost('isl', host) + ')s',
596 '--with-cloog=%(abs_' + ForHost('cloog', host) + ')s',
597 '--enable-cloog-backend=isl',
601 '--with-linker-hash-style=gnu',
602 '--enable-linker-build-id',
603 '--enable-languages=c,c++,lto',
608 def HostTools(host, target):
609 def H(component_name):
610 return ForHost(component_name, host)
612 H('binutils_' + target): {
614 'dependencies': ['binutils'],
615 'commands': ConfigureTargetPrep(target) + [
617 ConfigureCommand('binutils') +
618 ConfigureHostTool(host) +
619 ConfigureTargetArgs(target) + [
620 '--enable-deterministic-archives',
622 ] + ([] if HostIsWindows(host) else [
625 command.Command(MakeCommand(host)),
626 command.Command(MakeCheckCommand(host)),
627 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
629 ] + InstallDocFiles('binutils',
631 [command.path.join(subdir, 'NEWS')
633 ['binutils', 'gas', 'ld', 'gold']]) +
634 # The top-level lib* directories contain host libraries
635 # that we don't want to include in the distribution.
636 [command.RemoveDirectory(command.path.join('%(output)s', name))
637 for name in ['lib', 'lib32', 'lib64']],
640 H('gcc_' + target): {
642 'dependencies': (['gcc'] + HostGccLibsDeps(host) +
643 GccDeps(host, target)),
644 'commands': ConfigureTargetPrep(target) + [
645 ConfigureGccCommand('gcc', host, target),
646 # GCC's configure step writes configargs.h with some strings
647 # including the configure command line, which get embedded
648 # into the gcc driver binary. The build only works if we use
649 # absolute paths in some of the configure switches, but
650 # embedding those paths makes the output differ in repeated
651 # builds done in different directories, which we do not want.
652 # So force the generation of that file early and then edit it
653 # in place to replace the absolute paths with something that
654 # never varies. Note that the 'configure-gcc' target will
655 # actually build some components before running gcc/configure.
656 GccCommand(host, target,
657 MakeCommand(host, ['configure-gcc'])),
658 command.Command(['sed', '-i', '-e',
659 ';'.join(['s@%%(abs_%s)s@.../%s_install@g' %
660 (component, component)
662 HostGccLibsDeps(host)] +
663 ['s@%(cwd)s@...@g']),
664 command.path.join('gcc', 'configargs.h')]),
665 # gcc/Makefile's install rules ordinarily look at the
666 # installed include directory for a limits.h to decide
667 # whether the lib/gcc/.../include-fixed/limits.h header
668 # should be made to expect a libc-supplied limits.h or not.
669 # Since we're doing this build in a clean environment without
670 # any libc installed, we need to force its hand here.
671 GccCommand(host, target,
672 MakeCommand(host, ['all-gcc', 'LIMITS_H_TEST=true'])),
673 # gcc/Makefile's install targets populate this directory
674 # only if it already exists.
675 command.Mkdir(command.path.join('%(output)s',
676 target + '-nacl', 'bin'),
678 GccCommand(host, target,
679 MAKE_DESTDIR_CMD + ['install-strip-gcc']),
681 # Note we include COPYING.RUNTIME here and not with gcc_libs.
682 ] + InstallDocFiles('gcc', ['COPYING3', 'COPYING.RUNTIME']),
685 # GDB can support all the targets in one host tool.
688 'dependencies': ['gdb', H('expat')],
691 ConfigureCommand('gdb') +
692 ConfigureHostTool(host) + [
693 '--target=x86_64-nacl',
694 '--enable-targets=arm-none-eabi-nacl',
696 'CPPFLAGS=-I%(abs_' + H('expat') + ')s/include',
697 'LDFLAGS=-L%(abs_' + H('expat') + ')s/lib',
699 (['--without-python'] if HostIsWindows(host) else []) +
700 # TODO(mcgrathr): The default -Werror only breaks because
701 # the OSX default compiler is an old front-end that does
702 # not understand all the GCC options. Maybe switch to
703 # using clang (system or Chromium-supplied) on Mac.
704 (['--disable-werror'] if HostIsMac(host) else [])),
705 command.Command(MakeCommand(host) + ['all-gdb']),
706 command.Command(MAKE_DESTDIR_CMD + [
707 '-C', 'gdb', 'install-strip',
710 ] + InstallDocFiles('gdb', [
712 command.path.join('gdb', 'NEWS'),
717 # TODO(mcgrathr): The ARM cross environment does not supply a termcap
718 # library, so it cannot build GDB.
719 if host.startswith('arm') and CrossCompiling(host):
724 def TargetCommands(host, target, command_list):
725 # First we have to copy the host tools into a common directory.
726 # We can't just have both directories in our PATH, because the
727 # compiler looks for the assembler and linker relative to itself.
728 commands = PopulateDeps(['%(' + ForHost('binutils_' + target, host) + ')s',
729 '%(' + ForHost('gcc_' + target, host) + ')s'])
730 bindir = command.path.join('%(cwd)s', 'all_deps', 'bin')
731 commands += [command.Command(cmd, path_dirs=[bindir])
732 for cmd in command_list]
736 def TargetLibs(host, target):
737 lib_deps = [ForHost(component + '_' + target, host)
738 for component in ['binutils', 'gcc']]
740 def NewlibFile(subdir, name):
741 return command.path.join('%(output)s', target + '-nacl', subdir, name)
743 newlib_sysroot = '%(abs_newlib_' + target + ')s'
744 newlib_tooldir = '%s/%s-nacl' % (newlib_sysroot, target)
746 # See the comment at ConfigureTargetPrep, above.
747 newlib_install_data = ' '.join(['STRIPPROG=%(cwd)s/strip_for_target',
748 '%(abs_newlib)s/install-sh',
749 '-c', '-s', '-m', '644'])
751 iconv_encodings = 'UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4'
752 newlib_configure_args = [
753 '--disable-libgloss',
754 '--enable-newlib-iconv',
755 '--enable-newlib-iconv-from-encodings=' + iconv_encodings,
756 '--enable-newlib-iconv-to-encodings=' + iconv_encodings,
757 '--enable-newlib-io-long-long',
758 '--enable-newlib-io-long-double',
759 '--enable-newlib-io-c99-formats',
760 '--enable-newlib-mb',
762 'INSTALL_DATA=' + newlib_install_data,
765 newlib_post_install = [
766 command.Rename(NewlibFile('lib', 'libc.a'),
767 NewlibFile('lib', 'libcrt_common.a')),
768 command.WriteData(NewlibLibcScript(target),
769 NewlibFile('lib', 'libc.a')),
772 command.path.join('%(pthread_headers)s', header),
773 NewlibFile('include', header))
774 for header in ('pthread.h', 'semaphore.h')
779 'newlib_' + target: {
781 'dependencies': ['newlib'] + lib_deps,
782 'inputs': { 'pthread_headers':
783 os.path.join(NACL_DIR, 'src', 'untrusted',
785 'commands': (ConfigureTargetPrep(target) +
786 TargetCommands(host, target, [
787 ConfigureCommand('newlib') +
788 ConfigureHostTool(host) +
789 ConfigureTargetArgs(target) +
790 newlib_configure_args,
792 MAKE_DESTDIR_CMD + ['install-strip'],
794 newlib_post_install +
795 InstallDocFiles('newlib', ['COPYING.NEWLIB'])),
798 'gcc_libs_' + target: {
800 'dependencies': (['gcc_libs'] + lib_deps + ['newlib_' + target] +
801 HostGccLibsDeps(host)),
802 # This actually builds the compiler again and uses that compiler
803 # to build the target libraries. That's by far the easiest thing
804 # to get going given the interdependencies of the target
805 # libraries (especially libgcc) on the gcc subdirectory, and
806 # building the compiler doesn't really take all that long in the
807 # grand scheme of things.
808 # TODO(mcgrathr): If upstream ever cleans up all their
809 # interdependencies better, unpack the compiler, configure with
810 # --disable-gcc, and just build all-target.
811 'commands': ConfigureTargetPrep(target) + [
812 ConfigureGccCommand('gcc_libs', host, target, [
813 '--with-build-sysroot=' + newlib_sysroot,
815 GccCommand(host, target,
816 MakeCommand(host) + [
817 'build_tooldir=' + newlib_tooldir,
820 GccCommand(host, target,
821 MAKE_DESTDIR_CMD + ['install-strip-target']),
829 NATIVE_TUPLE = pynacl.platform.PlatformTriple()
832 # For our purposes, "cross-compiling" means not literally that we are
833 # targetting a host that does not match NATIVE_TUPLE, but that we are
834 # targetting a host whose binaries we cannot run locally. So x86-32
835 # on x86-64 does not count as cross-compiling. See NATIVE_ENOUGH_MAP, above.
836 def CrossCompiling(host):
837 return (host != NATIVE_TUPLE and
838 host not in NATIVE_ENOUGH_MAP.get(NATIVE_TUPLE, {}))
841 def HostIsWindows(host):
842 return host == WINDOWS_HOST_TUPLE
846 return host == MAC_HOST_TUPLE
849 # We build target libraries only on Linux for two reasons:
850 # 1. We only need to build them once.
851 # 2. Linux is the fastest to build.
852 # TODO(mcgrathr): In future set up some scheme whereby non-Linux
853 # bots can build target libraries but not archive them, only verifying
854 # that the results came out the same as the ones archived by the
855 # official builder bot. That will serve as a test of the host tools
856 # on the other host platforms.
857 def BuildTargetLibsOn(host):
858 return host == LINUX_X86_64_TUPLE
861 def CollectPackagesForHost(host, targets):
862 packages = HostGccLibs(host).copy()
863 for target in targets:
864 packages.update(HostTools(host, target))
865 if BuildTargetLibsOn(host):
866 packages.update(TargetLibs(host, target))
870 def CollectPackages(targets):
871 packages = CollectSources()
873 packages.update(CollectPackagesForHost(NATIVE_TUPLE, targets))
875 for host in EXTRA_HOSTS_MAP.get(NATIVE_TUPLE, []):
876 packages.update(CollectPackagesForHost(host, targets))
881 PACKAGES = CollectPackages(TARGET_LIST)
884 if __name__ == '__main__':
885 tb = toolchain_main.PackageBuilder(PACKAGES, sys.argv[1:])
886 # TODO(mcgrathr): The bot ought to run some native_client tests
887 # using the new toolchain, like the old x86 toolchain bots do.