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': '5deb4793a5e3f2f48d7899f424bb4484686020f8',
58 'upstream-branch': 'upstream/gdb-7.7-branch',
59 'upstream-name': 'gdb-7.7.1',
60 # Upstream tag gdb-7.7-release:
61 'upstream-base': '4bd8fc3a1362970d9800a263987af8093798338b',
66 'gmp': command.path.join('gmp', 'gmp-6.0.0a.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.1.0.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_info = {'name': package}
113 patch_info.update(info)
114 patch_commands.append(
115 command.GenerateGitPatches('%(' + package + ')s/.git', patch_info))
117 sources['patches'] = {
119 'dependencies': patch_packages,
120 'commands': patch_commands,
123 # The gcc_libs component gets the whole GCC source tree.
124 sources['gcc_libs'] = sources['gcc']
126 # The gcc component omits all the source directories that are used solely
127 # for building target libraries. We don't want those included in the
128 # input hash calculation so that we don't rebuild the compiler when the
129 # the only things that have changed are target libraries.
132 'dependencies': ['gcc_libs'],
133 'commands': [command.CopyTree('%(gcc_libs)s', '%(output)s', [
153 # We have to populate the newlib source tree with the "exported" form of
154 # some headers from the native_client source tree. The newlib build
155 # needs these to be in the expected place. By doing this in the source
156 # target, these files will be part of the input hash and so we don't need
157 # to do anything else to keep track of when they might have changed in
158 # the native_client source tree.
159 newlib_sys_nacl = command.path.join('%(output)s',
160 'newlib', 'libc', 'sys', 'nacl')
161 newlib_unpack = [command.RemoveDirectory(command.path.join(newlib_sys_nacl,
163 for dirname in ['bits', 'sys', 'machine']]
164 newlib_unpack.append(command.Command([
166 command.path.join('%(top_srcdir)s', 'src',
167 'trusted', 'service_runtime', 'export_header.py'),
168 command.path.join('%(top_srcdir)s', 'src',
169 'trusted', 'service_runtime', 'include'),
172 sources['newlib']['commands'] += newlib_unpack
177 # List of all platform and architectures we target and will distribute for.
180 ('darwin', 'x86-64'),
185 # Canonical tuples we use for hosts.
186 WINDOWS_HOST_TUPLE = pynacl.platform.PlatformTriple('win', 'x86-64')
187 MAC_HOST_TUPLE = pynacl.platform.PlatformTriple('darwin', 'x86-64')
188 ARM_HOST_TUPLE = pynacl.platform.PlatformTriple('linux', 'arm')
189 LINUX_X86_32_TUPLE = pynacl.platform.PlatformTriple('linux', 'x86-32')
190 LINUX_X86_64_TUPLE = pynacl.platform.PlatformTriple('linux', 'x86-64')
192 # Map of native host tuple to extra tuples that it cross-builds for.
194 LINUX_X86_64_TUPLE: [
201 # Map of native host tuple to host tuples that are "native enough".
202 # For these hosts, we will do a native-style build even though it's
203 # not the native tuple, just passing some extra compiler flags.
204 NATIVE_ENOUGH_MAP = {
205 LINUX_X86_64_TUPLE: {
206 LINUX_X86_32_TUPLE: ['-m32'],
210 # The list of targets to build toolchains for.
211 TARGET_LIST = ['arm', 'i686']
212 UPLOAD_TARGETS = ['arm']
214 # GDB is built by toolchain_build but injected into package targets built by
215 # other means. List out what package targets, packages, and the tar file we are
216 # injecting on top of here.
219 ('darwin', 'x86-64'),
223 GDB_INJECT_PACKAGES = [
224 ('nacl_x86_newlib', ['naclsdk.tgz']),
225 ('nacl_x86_glibc', ['toolchain.tar.bz2']),
228 # These are extra arguments to pass gcc's configure that vary by target.
229 TARGET_GCC_CONFIG = {
230 # TODO(mcgrathr): Disabled tuning for now, tickling a constant-pool layout bug.
231 # 'arm': ['--with-tune=cortex-a15'],
234 PACKAGE_NAME = 'Native Client SDK [%(build_signature)s]'
235 BUG_URL = 'http://gonacl.com/reportissue'
237 TAR_XV = ['tar', '-x', '-v']
238 EXTRACT_STRIP_TGZ = TAR_XV + ['--gzip', '--strip-components=1', '-f']
239 EXTRACT_STRIP_TBZ2 = TAR_XV + ['--bzip2', '--strip-components=1', '-f']
240 CONFIGURE_CMD = ['sh', '%(src)s/configure']
241 MAKE_PARALLEL_CMD = ['make', '-j%(cores)s']
242 MAKE_CHECK_CMD = MAKE_PARALLEL_CMD + ['check']
243 MAKE_DESTDIR_CMD = ['make', 'DESTDIR=%(abs_output)s']
245 # This file gets installed by multiple packages' install steps, but it is
246 # never useful when installed in isolation. So we remove it from the
247 # installation directories before packaging up.
248 REMOVE_INFO_DIR = command.Remove(command.path.join('%(output)s',
249 'share', 'info', 'dir'))
251 def ConfigureHostArch(host):
254 is_cross = CrossCompiling(host)
258 configure_args.append('--host=' + host)
260 extra_cc_args = NATIVE_ENOUGH_MAP.get(NATIVE_TUPLE, {}).get(host, [])
262 # The host we've chosen is "native enough", such as x86-32 on x86-64.
263 # But it's not what config.guess will yield, so we need to supply
264 # a --build switch to ensure things build correctly.
265 configure_args.append('--build=' + host)
267 extra_cxx_args = list(extra_cc_args)
268 if fnmatch.fnmatch(host, '*-linux*'):
269 # Avoid shipping binaries with a runtime dependency on
270 # a particular version of the libstdc++ shared library.
271 # TODO(mcgrathr): Do we want this for MinGW and/or Mac too?
272 extra_cxx_args.append('-static-libstdc++')
275 # These are the defaults when there is no setting, but we will add
276 # additional switches, so we must supply the command name too.
281 configure_args.append('CC=' + ' '.join([cc] + extra_cc_args))
284 # These are the defaults when there is no setting, but we will add
285 # additional switches, so we must supply the command name too.
290 configure_args.append('CXX=' + ' '.join([cxx] + extra_cxx_args))
292 if HostIsWindows(host):
293 # The i18n support brings in runtime dependencies on MinGW DLLs
294 # that we don't want to have to distribute alongside our binaries.
295 # So just disable it, and compiler messages will always be in US English.
296 configure_args.append('--disable-nls')
298 return configure_args
301 def ConfigureHostCommon(host):
302 return ConfigureHostArch(host) + [
304 '--disable-silent-rules',
305 '--without-gcc-arch',
309 def ConfigureHostLib(host):
310 return ConfigureHostCommon(host) + [
315 def ConfigureHostTool(host):
316 return ConfigureHostCommon(host) + [
317 '--with-pkgversion=' + PACKAGE_NAME,
318 '--with-bugurl=' + BUG_URL,
323 def MakeCommand(host, extra_args=[]):
324 if HostIsWindows(host):
325 # There appears to be nothing we can pass at top-level configure time
326 # that will prevent the configure scripts from finding MinGW's libiconv
327 # and using it. We have to force this variable into the environment
328 # of the sub-configure runs, which are run via make.
329 make_command = MAKE_PARALLEL_CMD + ['HAVE_LIBICONV=no']
331 make_command = MAKE_PARALLEL_CMD
332 return make_command + extra_args
335 # Return the 'make check' command to run.
336 # When cross-compiling, don't try to run test suites.
337 def MakeCheckCommand(host):
338 if CrossCompiling(host):
340 return MAKE_CHECK_CMD
343 def InstallDocFiles(subdir, files):
344 doc_dir = command.path.join('%(output)s', 'share', 'doc', subdir)
345 dirs = sorted(set([command.path.dirname(command.path.join(doc_dir, file))
347 commands = ([command.Mkdir(dir, parents=True) for dir in dirs] +
348 [command.Copy(command.path.join('%(' + subdir + ')s', file),
349 command.path.join(doc_dir, file))
354 def NewlibLibcScript(arch):
356 * This is a linker script that gets installed as libc.a for the
357 * newlib-based NaCl toolchain. It brings in the constituent
358 * libraries that make up what -lc means semantically.
361 GROUP ( libnacl.a libcrt_common.a )
364 # Listing three formats instead of one makes -EL/-EB switches work
365 # for the endian-switchable ARM backend.
366 format_list = ['elf32-littlearm-nacl',
368 'elf32-littlearm-nacl']
370 format_list = 'elf32-i386-nacl'
371 elif arch == 'x86_64':
372 format_list = 'elf32-x86_64-nacl'
374 raise Exception('TODO(mcgrathr): OUTPUT_FORMAT for %s' % arch)
375 return template % ', '.join(['"' + fmt + '"' for fmt in format_list])
378 # The default strip behavior removes debugging and symbol table
379 # sections, but it leaves the .comment section. This contains the
380 # compiler version string, and so it changes when the compiler changes
381 # even if the actual machine code it produces is completely identical.
382 # Hence, the target library packages will always change when the
383 # compiler changes unless these sections are removed. Doing this
384 # requires somehow teaching the makefile rules to pass the
385 # --remove-section=.comment switch to TARGET-strip. For the GCC
386 # target libraries, setting STRIP_FOR_TARGET is sufficient. But
387 # quoting nightmares make it difficult to pass a command with a space
388 # in it as the STRIP_FOR_TARGET value. So the build writes a little
389 # script that can be invoked with a simple name.
391 # Though the gcc target libraries' makefiles are smart enough to obey
392 # STRIP_FOR_TARGET for library files, the newlib makefiles just
393 # blindly use $(INSTALL_DATA) for both header (text) files and library
394 # files. Hence it's necessary to override its INSTALL_DATA setting to
395 # one that will do stripping using this script, and thus the script
396 # must silently do nothing to non-binary files.
397 def ConfigureTargetPrep(arch):
398 script_file = 'strip_for_target'
400 config_target = arch + '-nacl'
401 script_contents = """\
408 type=`file --brief --mime-type "$arg"`
410 application/x-executable|application/x-sharedlib) ;;
411 application/x-archive|application/x-object) mode=--strip-debug ;;
417 exec %s-strip $mode --remove-section=.comment "$@"
421 command.WriteData(script_contents, script_file),
422 command.Command(['chmod', '+x', script_file]),
426 def ConfigureTargetArgs(arch):
427 config_target = arch + '-nacl'
429 '--target=' + config_target,
430 '--with-sysroot=/' + config_target,
431 'STRIP_FOR_TARGET=%(cwd)s/strip_for_target',
435 def CommandsInBuild(command_lines):
437 command.RemoveDirectory('build'),
438 command.Mkdir('build'),
439 ] + [command.Command(cmd, cwd='build')
440 for cmd in command_lines]
443 def PopulateDeps(dep_dirs):
444 commands = [command.RemoveDirectory('all_deps'),
445 command.Mkdir('all_deps')]
446 commands += [command.Command('cp -r "%s/"* all_deps' % dirname, shell=True)
447 for dirname in dep_dirs]
451 def WithDepsOptions(options, component=None):
452 if component is None:
453 directory = command.path.join('%(cwd)s', 'all_deps')
455 directory = '%(abs_' + component + ')s'
456 return ['--with-' + option + '=' + directory
457 for option in options]
460 # Return the component name we'll use for a base component name and
461 # a host tuple. The component names cannot contain dashes or other
462 # non-identifier characters, because the names of the files uploaded
463 # to Google Storage are constrained. GNU configuration tuples contain
464 # dashes, which we translate to underscores.
465 def ForHost(component_name, host):
466 return component_name + '_' + pynacl.gsd_storage.LegalizeName(host)
469 # These are libraries that go into building the compiler itself.
470 def HostGccLibs(host):
471 def H(component_name):
472 return ForHost(component_name, host)
476 'dependencies': ['gmp'],
478 command.Command(ConfigureCommand('gmp') +
479 ConfigureHostLib(host) + [
480 '--with-sysroot=%(abs_output)s',
482 # Without this, the built library will
483 # assume the instruction set details
484 # available on the build machine. With
485 # this, it dynamically chooses what code
486 # to use based on the details of the
487 # actual host CPU at runtime.
490 command.Command(MakeCommand(host)),
491 command.Command(MakeCheckCommand(host)),
492 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
497 'dependencies': ['mpfr', H('gmp')],
499 command.Command(ConfigureCommand('mpfr') +
500 ConfigureHostLib(host) +
501 WithDepsOptions(['sysroot', 'gmp'], H('gmp'))),
502 command.Command(MakeCommand(host)),
503 command.Command(MakeCheckCommand(host)),
504 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
509 'dependencies': ['mpc', H('gmp'), H('mpfr')],
510 'commands': PopulateDeps(['%(' + H('gmp') + ')s',
511 '%(' + H('mpfr') + ')s']) + [
512 command.Command(ConfigureCommand('mpc') +
513 ConfigureHostLib(host) +
514 WithDepsOptions(['sysroot', 'gmp', 'mpfr'])),
515 command.Command(MakeCommand(host)),
516 command.Command(MakeCheckCommand(host)),
517 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
522 'dependencies': ['isl', H('gmp')],
524 command.Command(ConfigureCommand('isl') +
525 ConfigureHostLib(host) +
526 WithDepsOptions(['sysroot', 'gmp-prefix'],
528 command.Command(MakeCommand(host)),
529 command.Command(MakeCheckCommand(host)),
530 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
531 # The .pc files wind up containing some absolute paths
532 # that make the output depend on the build directory name.
533 # The dependents' configure scripts don't need them anyway.
534 command.RemoveDirectory(command.path.join(
535 '%(output)s', 'lib', 'pkgconfig')),
540 'dependencies': ['cloog', H('gmp'), H('isl')],
541 'commands': PopulateDeps(['%(' + H('gmp') + ')s',
542 '%(' + H('isl') + ')s']) + [
543 command.Command(ConfigureCommand('cloog') +
544 ConfigureHostLib(host) + [
547 ] + WithDepsOptions(['sysroot',
550 command.Command(MakeCommand(host)),
551 command.Command(MakeCheckCommand(host)),
552 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
553 # The .pc files wind up containing some absolute paths
554 # that make the output depend on the build directory name.
555 # The dependents' configure scripts don't need them anyway.
556 command.RemoveDirectory(command.path.join(
557 '%(output)s', 'lib', 'pkgconfig')),
562 'dependencies': ['expat'],
564 command.Command(ConfigureCommand('expat') +
565 ConfigureHostLib(host)),
566 command.Command(MakeCommand(host)),
567 command.Command(MakeCheckCommand(host)),
568 command.Command(MAKE_DESTDIR_CMD + [
569 # expat does not support the install-strip target.
571 'INSTALL=%(expat)s/conftools/install-sh -c -s',
572 'INSTALL_DATA=%(expat)s/conftools/install-sh -c -m 644',
580 HOST_GCC_LIBS_DEPS = ['gmp', 'mpfr', 'mpc', 'isl', 'cloog']
582 def HostGccLibsDeps(host):
583 return [ForHost(package, host) for package in HOST_GCC_LIBS_DEPS]
586 def ConfigureCommand(source_component):
587 return [command % {'src': '%(' + source_component + ')s'}
588 for command in CONFIGURE_CMD]
591 # When doing a Canadian cross, we need native-hosted cross components
592 # to do the GCC build.
593 def GccDeps(host, target):
594 components = ['binutils_' + target]
595 if CrossCompiling(host):
596 components.append('gcc_' + target)
598 return [ForHost(component, host) for component in components]
601 def GccCommand(host, target, cmd):
602 components_for_path = GccDeps(host, target)
603 return command.Command(
604 cmd, path_dirs=[command.path.join('%(abs_' + component + ')s', 'bin')
605 for component in components_for_path])
608 def ConfigureGccCommand(source_component, host, target, extra_args=[]):
612 ConfigureCommand(source_component) +
613 ConfigureHostTool(host) +
614 ConfigureTargetArgs(target) +
615 TARGET_GCC_CONFIG.get(target, []) + [
616 '--with-gmp=%(abs_' + ForHost('gmp', host) + ')s',
617 '--with-mpfr=%(abs_' + ForHost('mpfr', host) + ')s',
618 '--with-mpc=%(abs_' + ForHost('mpc', host) + ')s',
619 '--with-isl=%(abs_' + ForHost('isl', host) + ')s',
620 '--with-cloog=%(abs_' + ForHost('cloog', host) + ')s',
621 '--enable-cloog-backend=isl',
625 '--with-linker-hash-style=gnu',
626 '--enable-linker-build-id',
627 '--enable-languages=c,c++,lto',
632 def HostTools(host, target):
633 def H(component_name):
634 return ForHost(component_name, host)
636 # Return the file name with the appropriate suffix for an executable file.
638 if HostIsWindows(host):
644 H('binutils_' + target): {
646 'dependencies': ['binutils'],
647 'commands': ConfigureTargetPrep(target) + [
649 ConfigureCommand('binutils') +
650 ConfigureHostTool(host) +
651 ConfigureTargetArgs(target) + [
652 '--enable-deterministic-archives',
654 ] + ([] if HostIsWindows(host) else [
657 command.Command(MakeCommand(host)),
658 command.Command(MakeCheckCommand(host)),
659 command.Command(MAKE_DESTDIR_CMD + ['install-strip']),
661 ] + InstallDocFiles('binutils',
663 [command.path.join(subdir, 'NEWS')
665 ['binutils', 'gas', 'ld', 'gold']]) +
666 # The top-level lib* directories contain host libraries
667 # that we don't want to include in the distribution.
668 [command.RemoveDirectory(command.path.join('%(output)s', name))
669 for name in ['lib', 'lib32', 'lib64']],
672 H('gcc_' + target): {
674 'dependencies': (['gcc'] + HostGccLibsDeps(host) +
675 GccDeps(host, target)),
676 'commands': ConfigureTargetPrep(target) + [
677 ConfigureGccCommand('gcc', host, target),
678 # GCC's configure step writes configargs.h with some strings
679 # including the configure command line, which get embedded
680 # into the gcc driver binary. The build only works if we use
681 # absolute paths in some of the configure switches, but
682 # embedding those paths makes the output differ in repeated
683 # builds done in different directories, which we do not want.
684 # So force the generation of that file early and then edit it
685 # in place to replace the absolute paths with something that
686 # never varies. Note that the 'configure-gcc' target will
687 # actually build some components before running gcc/configure.
688 GccCommand(host, target,
689 MakeCommand(host, ['configure-gcc'])),
690 command.Command(['sed', '-i', '-e',
691 ';'.join(['s@%%(abs_%s)s@.../%s_install@g' %
692 (component, component)
694 HostGccLibsDeps(host)] +
695 ['s@%(cwd)s@...@g']),
696 command.path.join('gcc', 'configargs.h')]),
697 # gcc/Makefile's install rules ordinarily look at the
698 # installed include directory for a limits.h to decide
699 # whether the lib/gcc/.../include-fixed/limits.h header
700 # should be made to expect a libc-supplied limits.h or not.
701 # Since we're doing this build in a clean environment without
702 # any libc installed, we need to force its hand here.
703 GccCommand(host, target,
704 MakeCommand(host, ['all-gcc', 'LIMITS_H_TEST=true'])),
705 # gcc/Makefile's install targets populate this directory
706 # only if it already exists.
707 command.Mkdir(command.path.join('%(output)s',
708 target + '-nacl', 'bin'),
710 GccCommand(host, target,
711 MAKE_DESTDIR_CMD + ['install-strip-gcc']),
713 # Note we include COPYING.RUNTIME here and not with gcc_libs.
714 ] + InstallDocFiles('gcc', ['COPYING3', 'COPYING.RUNTIME']),
717 # GDB can support all the targets in one host tool.
720 'dependencies': ['gdb', H('expat')],
723 ConfigureCommand('gdb') +
724 ConfigureHostTool(host) + [
725 '--target=x86_64-nacl',
726 '--enable-targets=arm-none-eabi-nacl',
728 'CPPFLAGS=-I%(abs_' + H('expat') + ')s/include',
729 'LDFLAGS=-L%(abs_' + H('expat') + ')s/lib',
731 (['--without-python'] if HostIsWindows(host) else []) +
732 # TODO(mcgrathr): The default -Werror only breaks because
733 # the OSX default compiler is an old front-end that does
734 # not understand all the GCC options. Maybe switch to
735 # using clang (system or Chromium-supplied) on Mac.
736 (['--disable-werror'] if HostIsMac(host) else [])),
737 command.Command(MakeCommand(host) + ['all-gdb']),
738 command.Command(MAKE_DESTDIR_CMD + [
739 '-C', 'gdb', 'install-strip',
742 ] + [command.Command(['ln', '-f',
743 command.path.join('%(abs_output)s',
745 Exe('x86_64-nacl-gdb')),
746 command.path.join('%(abs_output)s',
748 Exe(arch + '-nacl-gdb'))])
749 for arch in ['i686', 'arm']] + InstallDocFiles('gdb', [
751 command.path.join('gdb', 'NEWS'),
756 # TODO(mcgrathr): The ARM cross environment does not supply a termcap
757 # library, so it cannot build GDB.
758 if host.startswith('arm') and CrossCompiling(host):
763 def TargetCommands(host, target, command_list):
764 # First we have to copy the host tools into a common directory.
765 # We can't just have both directories in our PATH, because the
766 # compiler looks for the assembler and linker relative to itself.
767 commands = PopulateDeps(['%(' + ForHost('binutils_' + target, host) + ')s',
768 '%(' + ForHost('gcc_' + target, host) + ')s'])
769 bindir = command.path.join('%(cwd)s', 'all_deps', 'bin')
770 commands += [command.Command(cmd, path_dirs=[bindir])
771 for cmd in command_list]
775 def TargetLibs(host, target):
776 lib_deps = [ForHost(component + '_' + target, host)
777 for component in ['binutils', 'gcc']]
779 def NewlibFile(subdir, name):
780 return command.path.join('%(output)s', target + '-nacl', subdir, name)
782 newlib_sysroot = '%(abs_newlib_' + target + ')s'
783 newlib_tooldir = '%s/%s-nacl' % (newlib_sysroot, target)
785 # See the comment at ConfigureTargetPrep, above.
786 newlib_install_data = ' '.join(['STRIPPROG=%(cwd)s/strip_for_target',
787 '%(abs_newlib)s/install-sh',
788 '-c', '-s', '-m', '644'])
790 iconv_encodings = 'UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4'
791 newlib_configure_args = [
792 '--disable-libgloss',
793 '--enable-newlib-iconv',
794 '--enable-newlib-iconv-from-encodings=' + iconv_encodings,
795 '--enable-newlib-iconv-to-encodings=' + iconv_encodings,
796 '--enable-newlib-io-long-long',
797 '--enable-newlib-io-long-double',
798 '--enable-newlib-io-c99-formats',
799 '--enable-newlib-mb',
801 'INSTALL_DATA=' + newlib_install_data,
804 newlib_post_install = [
805 command.Rename(NewlibFile('lib', 'libc.a'),
806 NewlibFile('lib', 'libcrt_common.a')),
807 command.WriteData(NewlibLibcScript(target),
808 NewlibFile('lib', 'libc.a')),
811 command.path.join('%(pthread_headers)s', header),
812 NewlibFile('include', header))
813 for header in ('pthread.h', 'semaphore.h')
818 'newlib_' + target: {
820 'dependencies': ['newlib'] + lib_deps,
821 'inputs': { 'pthread_headers':
822 os.path.join(NACL_DIR, 'src', 'untrusted',
824 'commands': (ConfigureTargetPrep(target) +
825 TargetCommands(host, target, [
826 ConfigureCommand('newlib') +
827 ConfigureHostTool(host) +
828 ConfigureTargetArgs(target) +
829 newlib_configure_args,
831 MAKE_DESTDIR_CMD + ['install-strip'],
833 newlib_post_install +
834 InstallDocFiles('newlib', ['COPYING.NEWLIB'])),
837 'gcc_libs_' + target: {
839 'dependencies': (['gcc_libs'] + lib_deps + ['newlib_' + target] +
840 HostGccLibsDeps(host)),
841 # This actually builds the compiler again and uses that compiler
842 # to build the target libraries. That's by far the easiest thing
843 # to get going given the interdependencies of the target
844 # libraries (especially libgcc) on the gcc subdirectory, and
845 # building the compiler doesn't really take all that long in the
846 # grand scheme of things.
847 # TODO(mcgrathr): If upstream ever cleans up all their
848 # interdependencies better, unpack the compiler, configure with
849 # --disable-gcc, and just build all-target.
850 'commands': ConfigureTargetPrep(target) + [
851 ConfigureGccCommand('gcc_libs', host, target, [
852 '--with-build-sysroot=' + newlib_sysroot,
854 GccCommand(host, target,
855 MakeCommand(host) + [
856 'build_tooldir=' + newlib_tooldir,
859 GccCommand(host, target,
860 MAKE_DESTDIR_CMD + ['install-strip-target']),
868 NATIVE_TUPLE = pynacl.platform.PlatformTriple()
871 # For our purposes, "cross-compiling" means not literally that we are
872 # targetting a host that does not match NATIVE_TUPLE, but that we are
873 # targetting a host whose binaries we cannot run locally. So x86-32
874 # on x86-64 does not count as cross-compiling. See NATIVE_ENOUGH_MAP, above.
875 def CrossCompiling(host):
876 return (host != NATIVE_TUPLE and
877 host not in NATIVE_ENOUGH_MAP.get(NATIVE_TUPLE, {}))
880 def HostIsWindows(host):
881 return host == WINDOWS_HOST_TUPLE
885 return host == MAC_HOST_TUPLE
888 # We build target libraries only on Linux for two reasons:
889 # 1. We only need to build them once.
890 # 2. Linux is the fastest to build.
891 # TODO(mcgrathr): In future set up some scheme whereby non-Linux
892 # bots can build target libraries but not archive them, only verifying
893 # that the results came out the same as the ones archived by the
894 # official builder bot. That will serve as a test of the host tools
895 # on the other host platforms.
896 def BuildTargetLibsOn(host):
897 return host == LINUX_X86_64_TUPLE
899 def GetPackageTargets():
900 """Package Targets describes all the final package targets.
902 This build can be built among many build bots, but eventually all things
903 will be combined together. This package target dictionary describes the final
904 output of the entire build.
908 for target_arch in UPLOAD_TARGETS:
909 # Each package target contains non-platform specific newlib and gcc libs.
910 # These packages are added inside of TargetLibs(host, target).
911 newlib_package = 'newlib_%s' % target_arch
912 gcc_lib_package = 'gcc_libs_%s' % target_arch
913 shared_packages = [newlib_package, gcc_lib_package]
915 for platform, arch in HOSTS:
916 # Each package target contains arm binutils and gcc.
917 # These packages are added inside of HostTools(host, target).
918 platform_triple = pynacl.platform.PlatformTriple(platform, arch)
919 binutils_package = ForHost('binutils_%s' % target_arch, platform_triple)
920 gcc_package = ForHost('gcc_%s' % target_arch, platform_triple)
921 gdb_package = ForHost('gdb', platform_triple)
923 # Create a list of packages for a target.
924 platform_packages = [binutils_package, gcc_package, gdb_package]
925 combined_packages = shared_packages + platform_packages
927 os_name = pynacl.platform.GetOS(platform)
928 arch_name = pynacl.platform.GetArch(arch)
929 package_target = '%s_%s' % (os_name, arch_name)
930 package_name = 'nacl_%s_newlib' % (pynacl.platform.GetArch(target_arch))
932 package_target_dict = package_targets.setdefault(package_target, {})
933 package_target_dict.setdefault(package_name, []).extend(combined_packages)
935 # GDB is a special and shared, we will inject it into various other packages.
936 for platform, arch in GDB_INJECT_HOSTS:
937 platform_triple = pynacl.platform.PlatformTriple(platform, arch)
938 os_name = pynacl.platform.GetOS(platform)
939 arch_name = pynacl.platform.GetArch(arch)
941 gdb_packages = [ForHost('gdb', platform_triple)]
942 package_target = '%s_%s' % (os_name, arch_name)
944 for package_name, package_archives in GDB_INJECT_PACKAGES:
945 combined_packages = package_archives + gdb_packages
946 package_target_dict = package_targets.setdefault(package_target, {})
947 package_target_dict.setdefault(package_name, []).extend(combined_packages)
949 return dict(package_targets)
951 def CollectPackagesForHost(host, targets):
952 packages = HostGccLibs(host).copy()
953 for target in targets:
954 packages.update(HostTools(host, target))
955 if BuildTargetLibsOn(host):
956 packages.update(TargetLibs(host, target))
960 def CollectPackages(targets):
961 packages = CollectSources()
963 packages.update(CollectPackagesForHost(NATIVE_TUPLE, targets))
965 for host in EXTRA_HOSTS_MAP.get(NATIVE_TUPLE, []):
966 packages.update(CollectPackagesForHost(host, targets))
971 PACKAGES = CollectPackages(TARGET_LIST)
972 PACKAGE_TARGETS = GetPackageTargets()
975 if __name__ == '__main__':
976 tb = toolchain_main.PackageBuilder(PACKAGES, PACKAGE_TARGETS, sys.argv[1:])
977 # TODO(mcgrathr): The bot ought to run some native_client tests
978 # using the new toolchain, like the old x86 toolchain bots do.