Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / toolchain_build / toolchain_build_pnacl.py
1 #!/usr/bin/python
2 # Copyright (c) 2013 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.
5
6 """Recipes for PNaCl toolchain packages.
7
8    Recipes consist of specially-structured dictionaries, with keys for package
9    name, type, commands to execute, etc. The structure is documented in the
10    PackageBuilder docstring in toolchain_main.py.
11
12    The real entry plumbing and CLI flags are also in toolchain_main.py.
13 """
14
15 # Done first to set up python module path
16 import toolchain_env
17
18 import base64
19 import fnmatch
20 import logging
21 import os
22 import re
23 import shutil
24 import stat
25 import subprocess
26 import sys
27 import zipfile
28
29 import command
30 import file_tools
31 import gsd_storage
32 import pnacl_commands
33 import pnacl_targetlibs
34 import repo_tools
35 import toolchain_main
36
37 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
38 import pynacl.platform
39
40 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
41 NACL_DIR = os.path.dirname(SCRIPT_DIR)
42 # Use the argparse from third_party to ensure it's the same on all platorms
43 python_lib_dir = os.path.join(os.path.dirname(NACL_DIR), 'third_party',
44                               'python_libs', 'argparse')
45 sys.path.insert(0, python_lib_dir)
46 import argparse
47
48 # Scons tests can check this version number to decide whether to enable tests
49 # for toolchain bug fixes or new features.  This allows tests to be enabled on
50 # the toolchain buildbots/trybots before the new toolchain version is rolled
51 # into TOOL_REVISIONS (i.e. before the tests would pass on the main NaCl
52 # buildbots/trybots).  If you are adding a test that depends on a toolchain
53 # change, you can increment this version number manually.
54 FEATURE_VERSION = 4
55
56 # For backward compatibility, these key names match the directory names
57 # previously used with gclient
58 GIT_REPOS = {
59     'binutils': 'nacl-binutils.git',
60     'clang': 'pnacl-clang.git',
61     'llvm': 'pnacl-llvm.git',
62     'gcc': 'pnacl-gcc.git',
63     'libcxx': 'pnacl-libcxx.git',
64     'libcxxabi': 'pnacl-libcxxabi.git',
65     'nacl-newlib': 'nacl-newlib.git',
66     'llvm-test-suite': 'pnacl-llvm-testsuite.git',
67     'compiler-rt': 'pnacl-compiler-rt.git',
68     }
69
70 GIT_BASE_URL = 'https://chromium.googlesource.com/native_client/'
71 GIT_DEPS_FILE = os.path.join(NACL_DIR, 'pnacl', 'COMPONENT_REVISIONS')
72
73 # TODO(dschuff): Some of this cygwin/mingw logic duplicates stuff in command.py
74 # and the mechanism for switching between cygwin and mingw is bad.
75 # Path to the hermetic cygwin
76 BUILD_CROSS_MINGW = False
77 CYGWIN_PATH = os.path.join(NACL_DIR, 'cygwin')
78 # Path to the mingw cross-compiler libs on Ubuntu
79 CROSS_MINGW_LIBPATH = '/usr/lib/gcc/i686-w64-mingw32/4.6'
80 # Path and version of the native mingw compiler to be installed on Windows hosts
81 MINGW_PATH = os.path.join(NACL_DIR, 'mingw32')
82 MINGW_VERSION = 'i686-w64-mingw32-4.8.1'
83
84 ALL_ARCHES = ('x86-32', 'x86-64', 'arm', 'mips32')
85 BITCODE_BIASES = ('portable', 'x86-64')
86
87 MAKE_DESTDIR_CMD = ['make', 'DESTDIR=%(abs_output)s']
88
89 def NativeTriple():
90   if pynacl.platform.IsWindows():
91     if command.Runnable.use_cygwin:
92       return 'i686-pc-cygwin'
93     else:
94       return 'i686-w64-mingw32'
95   elif pynacl.platform.IsMacOS():
96     return 'x86_64-apple-darwin'
97   elif pynacl.platform.IsLinux():
98     if pynacl.platform.Is64BitLinux():
99       return 'x86_64-linux'
100     else:
101       return 'i686-linux'
102   else:
103     raise Exception('Unknown build architecture %s' % sys.platform)
104
105
106 def TripleIsWindows(t):
107   return fnmatch.fnmatch(t, '*-mingw32*') or fnmatch.fnmatch(t, '*cygwin*')
108
109
110 def CompilersForHost(host):
111   compiler = {
112       # For now we only do native builds for linux and mac
113       'i686-linux': ('gcc', 'g++'), # treat 32-bit linux like a native build
114       'x86_64-linux': ('gcc', 'g++'),
115       # TODO(dschuff): switch to clang on mac
116       'x86_64-apple-darwin': ('gcc', 'g++'),
117       # Windows build should work for native and cross
118       'i686-w64-mingw32': ('i686-w64-mingw32-gcc', 'i686-w64-mingw32-g++'),
119       # TODO: add arm-hosted support
120   }
121   return compiler[host]
122
123
124 def ConfigureHostArchFlags(host):
125   configure_args = []
126   extra_cc_args = []
127
128   native = NativeTriple()
129   is_cross = host != native
130   if is_cross:
131     if (pynacl.platform.Is64BitLinux() and
132         fnmatch.fnmatch(host, '*-linux*')):
133       # 64 bit linux can build 32 bit linux binaries while still being a native
134       # build for our purposes. But it's not what config.guess will yield, so
135       # use --build to force it and make sure things build correctly.
136       configure_args.append('--build=' + host)
137       extra_cc_args = ['-m32']
138     else:
139       configure_args.append('--host=' + host)
140
141   extra_cxx_args = list(extra_cc_args)
142
143   cc, cxx = CompilersForHost(host)
144
145   if is_cross:
146     # LLVM's linux->mingw cross build needs this
147     configure_args.append('CC_FOR_BUILD=gcc')
148
149   configure_args.append('CC=' + ' '.join([cc] + extra_cc_args))
150   configure_args.append('CXX=' + ' '.join([cxx] + extra_cxx_args))
151
152   if TripleIsWindows(host):
153     # The i18n support brings in runtime dependencies on MinGW DLLs
154     # that we don't want to have to distribute alongside our binaries.
155     # So just disable it, and compiler messages will always be in US English.
156     configure_args.append('--disable-nls')
157     if not command.Runnable.use_cygwin:
158       configure_args.extend(['LDFLAGS=-L%(abs_libdl)s',
159                              'CFLAGS=-isystem %(abs_libdl)s',
160                              'CXXFLAGS=-isystem %(abs_libdl)s'])
161   return configure_args
162
163
164 def CmakeHostArchFlags(host, options):
165   cmake_flags = []
166   if options.clang:
167     cc ='%(abs_top_srcdir)s/../third_party/llvm-build/Release+Asserts/bin/clang'
168     cxx = cc + '++'
169   else:
170     cc, cxx = CompilersForHost(host)
171   cmake_flags.extend(['-DCMAKE_C_COMPILER='+cc, '-DCMAKE_CXX_COMPILER='+cxx])
172
173   if NativeTriple() != host and pynacl.platform.Is64BitLinux():
174     # Currently the only supported "cross" build is 64-bit Linux to 32-bit
175     # Linux. Enable it, and disable libxml because Ubuntu doesn't have a
176     # 32-bit libxml build.
177     cmake_flags.extend(['-DLLVM_BUILD_32_BITS=ON',
178                         '-DLLVM_ENABLE_LIBXML=OFF'])
179
180   if options.sanitize:
181     cmake_flags.extend(['-DCMAKE_%s_FLAGS=-fsanitize=%s' % (c, options.sanitize)
182                         for c in ('C', 'CXX')])
183     cmake_flags.append('-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=%s' %
184                        options.sanitize)
185   return cmake_flags
186
187
188 def MakeCommand(host):
189   make_command = ['make']
190   if (not pynacl.platform.IsWindows() or
191       command.Runnable.use_cygwin):
192     # The make that ships with msys sometimes hangs when run with -j.
193     # The ming32-make that comes with the compiler itself reportedly doesn't
194     # have this problem, but it has issues with pathnames with LLVM's build.
195     make_command.append('-j%(cores)s')
196
197   if TripleIsWindows(host):
198     # There appears to be nothing we can pass at top-level configure time
199     # that will prevent the configure scripts from finding MinGW's libiconv
200     # and using it.  We have to force this variable into the environment
201     # of the sub-configure runs, which are run via make.
202     make_command.append('HAVE_LIBICONV=no')
203   return make_command
204
205
206 def CopyWindowsHostLibs(host):
207   if not TripleIsWindows(host):
208     return []
209   if command.Runnable.use_cygwin:
210     libs = ('cyggcc_s-1.dll', 'cygiconv-2.dll', 'cygwin1.dll', 'cygintl-8.dll',
211             'cygstdc++-6.dll', 'cygz.dll')
212     return [command.Copy(
213                     os.path.join(CYGWIN_PATH, 'bin', lib),
214                     os.path.join('%(output)s', 'bin', lib))
215                 for lib in libs]
216   if pynacl.platform.IsWindows():
217     lib_path = os.path.join(MINGW_PATH, 'bin')
218     # The native minGW compiler uses winpthread, but the Ubuntu cross compiler
219     # does not.
220     libs = ('libgcc_s_sjlj-1.dll', 'libstdc++-6.dll', 'libwinpthread-1.dll')
221   else:
222     lib_path = os.path.join(CROSS_MINGW_LIBPATH)
223     libs = ('libgcc_s_sjlj-1.dll', 'libstdc++-6.dll')
224   return [command.Copy(
225                   os.path.join(lib_path, lib),
226                   os.path.join('%(output)s', 'bin', lib))
227                for lib in libs]
228
229 def GetGitSyncCmdCallback(revisions):
230   """Return a callback which returns the git sync command for a component.
231
232      This allows all the revision information to be processed here while giving
233      other modules like pnacl_targetlibs.py the ability to define their own
234      source targets with minimal boilerplate.
235   """
236   def GetGitSyncCmd(component):
237     return command.SyncGitRepo(GIT_BASE_URL + GIT_REPOS[component],
238                              '%(output)s',
239                              revisions[component])
240   return GetGitSyncCmd
241
242 def HostToolsSources(GetGitSyncCmd):
243   sources = {
244       'binutils_pnacl_src': {
245           'type': 'source',
246           'output_dirname': 'binutils',
247           'commands': [
248               GetGitSyncCmd('binutils'),
249           ],
250       },
251       # For some reason, the llvm build using --with-clang-srcdir chokes if the
252       # clang source directory is named something other than 'clang', so don't
253       # change output_dirname for clang.
254       'clang_src': {
255           'type': 'source',
256           'output_dirname': 'clang',
257           'commands': [
258               GetGitSyncCmd('clang'),
259           ],
260       },
261       'llvm_src': {
262           'type': 'source',
263           'output_dirname': 'llvm',
264           'commands': [
265               GetGitSyncCmd('llvm'),
266           ],
267       },
268   }
269   return sources
270
271
272 def HostLibs(host):
273   libs = {}
274   if TripleIsWindows(host) and not command.Runnable.use_cygwin:
275     if pynacl.platform.IsWindows():
276       ar = 'ar'
277     else:
278       ar = 'i686-w64-mingw32-ar'
279
280     libs.update({
281       'libdl': {
282           'type': 'build',
283           'inputs' : { 'src' : os.path.join(NACL_DIR, '..', 'third_party',
284                                             'dlfcn-win32') },
285           'commands': [
286               command.CopyTree('%(src)s', '.'),
287               command.Command(['i686-w64-mingw32-gcc',
288                                '-o', 'dlfcn.o', '-c', 'dlfcn.c',
289                                '-Wall', '-O3', '-fomit-frame-pointer']),
290               command.Command([ar, 'cru',
291                                'libdl.a', 'dlfcn.o']),
292               command.Copy('libdl.a',
293                            os.path.join('%(output)s', 'libdl.a')),
294               command.Copy('dlfcn.h',
295                            os.path.join('%(output)s', 'dlfcn.h')),
296           ],
297       },
298     })
299   return libs
300
301
302 def HostTools(host, options):
303   def H(component_name):
304     # Return a package name for a component name with a host triple.
305     return component_name + '_' + gsd_storage.LegalizeName(host)
306   def IsHost64(host):
307     return fnmatch.fnmatch(host, 'x86_64*')
308   def HostSubdir(host):
309     return 'host_x86_64' if IsHost64(host) else 'host_x86_32'
310   def BinSubdir(host):
311     return 'bin64' if host == 'x86_64-linux' else 'bin'
312   tools = {
313       H('binutils_pnacl'): {
314           'dependencies': ['binutils_pnacl_src'],
315           'type': 'build',
316           'output_subdir': HostSubdir(host),
317           'commands': [
318               command.SkipForIncrementalCommand([
319                   'sh',
320                   '%(binutils_pnacl_src)s/configure'] +
321                   ConfigureHostArchFlags(host) +
322                   ['--prefix=',
323                   '--disable-silent-rules',
324                   '--target=arm-pc-nacl',
325                   '--program-prefix=le32-nacl-',
326                   '--enable-targets=arm-pc-nacl,i686-pc-nacl,x86_64-pc-nacl,' +
327                   'mipsel-pc-nacl',
328                   '--enable-deterministic-archives',
329                   '--enable-shared=no',
330                   '--enable-gold=default',
331                   '--enable-ld=no',
332                   '--enable-plugins',
333                   '--without-gas',
334                   '--without-zlib',
335                   '--with-sysroot=/arm-pc-nacl']),
336               command.Command(MakeCommand(host)),
337               command.Command(MAKE_DESTDIR_CMD + ['install-strip'])] +
338               [command.RemoveDirectory(os.path.join('%(output)s', dir))
339                for dir in ('arm-pc-nacl', 'lib', 'lib32')]
340       },
341       H('driver'): {
342         'type': 'build',
343         'output_subdir': BinSubdir(host),
344         'inputs': { 'src': os.path.join(NACL_DIR, 'pnacl', 'driver')},
345         'commands': [
346             command.Runnable(pnacl_commands.InstallDriverScripts,
347                              '%(src)s', '%(output)s',
348                              host_windows=TripleIsWindows(host),
349                              host_64bit=IsHost64(host))
350         ],
351       },
352   }
353   llvm_cmake = {
354       H('llvm'): {
355           'dependencies': ['clang_src', 'llvm_src', 'binutils_pnacl_src'],
356           'type': 'build',
357           'output_subdir': HostSubdir(host),
358           'commands': [
359               command.SkipForIncrementalCommand([
360                   'cmake', '-G', 'Ninja'] +
361                   CmakeHostArchFlags(host, options) +
362                   ['-DCMAKE_BUILD_TYPE=RelWithDebInfo',
363                   '-DCMAKE_INSTALL_PREFIX=%(output)s',
364                   '-DCMAKE_INSTALL_RPATH=$ORIGIN/../lib',
365                   '-DBUILD_SHARED_LIBS=ON',
366                   '-DLLVM_ENABLE_ASSERTIONS=ON',
367                   '-DLLVM_ENABLE_ZLIB=OFF',
368                   '-DLLVM_BUILD_TESTS=ON',
369                   '-DLLVM_APPEND_VC_REV=ON',
370                   '-DLLVM_BINUTILS_INCDIR=%(abs_binutils_pnacl_src)s/include',
371                   '-DLLVM_EXTERNAL_CLANG_SOURCE_DIR=%(clang_src)s',
372                   '%(llvm_src)s']),
373               command.Command(['ninja', '-v']),
374               command.Command(['ninja', 'install']),
375         ],
376       },
377   }
378   llvm_autoconf = {
379       H('llvm'): {
380           'dependencies': ['clang_src', 'llvm_src', 'binutils_pnacl_src'],
381           'type': 'build',
382           'output_subdir': HostSubdir(host),
383           'commands': [
384               command.SkipForIncrementalCommand([
385                   'sh',
386                   '%(llvm_src)s/configure'] +
387                   ConfigureHostArchFlags(host) +
388                   ['--prefix=/',
389                    '--enable-shared',
390                    '--disable-zlib',
391                    '--disable-jit',
392                    '--disable-bindings', # ocaml is currently the only binding.
393                    '--with-binutils-include=%(abs_binutils_pnacl_src)s/include',
394                    '--enable-targets=x86,arm,mips',
395                    '--program-prefix=',
396                    '--enable-optimized',
397                    '--with-clang-srcdir=%(abs_clang_src)s']),
398               command.Command(MakeCommand(host) + [
399                   'VERBOSE=1',
400                   'NACL_SANDBOX=0',
401                   'all']),
402               command.Command(MAKE_DESTDIR_CMD + ['install'])] +
403               CopyWindowsHostLibs(host),
404       },
405   }
406   if options.cmake:
407     tools.update(llvm_cmake)
408   else:
409     tools.update(llvm_autoconf)
410   if TripleIsWindows(host) and not command.Runnable.use_cygwin:
411     tools[H('binutils_pnacl')]['dependencies'].append('libdl')
412     tools[H('llvm')]['dependencies'].append('libdl')
413   return tools
414
415 # TODO(dschuff): The REV file should probably go here rather than in the driver
416 # dir
417 def Metadata():
418   data = {
419       'metadata': {
420           'type': 'build',
421           'inputs': { 'readme': os.path.join(NACL_DIR, 'pnacl', 'README') },
422           'commands': [
423               command.Copy('%(readme)s', os.path.join('%(output)s', 'README')),
424               command.WriteData(str(FEATURE_VERSION),
425                                 os.path.join('%(output)s', 'FEATURE_VERSION')),
426           ],
427       }
428   }
429   return data
430
431 def ParseComponentRevisionsFile(filename):
432   ''' Parse a simple-format deps file, with fields of the form:
433 key=value
434 Keys should match the keys in GIT_REPOS above, which match the previous
435 directory names used by gclient (with the exception that '_' in the file is
436 replaced by '-' in the returned key name).
437 Values are the git hashes for each repo.
438 Empty lines or lines beginning with '#' are ignored.
439 This function returns a dictionary mapping the keys found in the file to their
440 values.
441 '''
442   with open(filename) as f:
443     deps = {}
444     for line in f:
445       stripped = line.strip()
446       if stripped.startswith('#') or len(stripped) == 0:
447         continue
448       tokens = stripped.split('=')
449       if len(tokens) != 2:
450         raise Exception('Malformed component revisions file: ' + filename)
451       deps[tokens[0].replace('_', '-')] = tokens[1]
452   return deps
453
454 # This is to replace build.sh's use of gclient, which will eliminate the issues
455 # with msys vs cygwin git checkouts, and make testing easier. Note that the new
456 # build scripts will not share source directories with build.sh.
457 def SyncPNaClRepos(revisions):
458   sys.stdout.flush()
459   for repo, revision in revisions.iteritems():
460     destination = os.path.join(NACL_DIR, 'pnacl', 'git', repo)
461     # This replaces build.sh's newlib-nacl-headers-clean step by cleaning the
462     # the newlib repo on checkout (while silently blowing away any local
463     # changes). TODO(dschuff): find a better way to handle nacl newlib headers.
464     is_newlib = repo == 'nacl-newlib'
465     repo_tools.SyncGitRepo(
466         GIT_BASE_URL + GIT_REPOS[repo],
467         destination,
468         revision,
469         clean=is_newlib)
470
471     # For testing LLVM, Clang, etc. changes on the trybots, look for a
472     # Git bundle file created by llvm_change_try_helper.sh.
473     bundle_file = os.path.join(NACL_DIR, 'pnacl', 'not_for_commit',
474                                '%s_bundle' % repo)
475     base64_file = '%s.b64' % bundle_file
476     if os.path.exists(base64_file):
477       input_fh = open(base64_file, 'r')
478       output_fh = open(bundle_file, 'wb')
479       base64.decode(input_fh, output_fh)
480       input_fh.close()
481       output_fh.close()
482       subprocess.check_call(repo_tools.GitCmd() + ['fetch'], cwd=destination)
483       subprocess.check_call(repo_tools.GitCmd() + ['bundle', 'unbundle',
484                                                    bundle_file],
485                             cwd=destination)
486       commit_id_file = os.path.join(NACL_DIR, 'pnacl', 'not_for_commit',
487                                     '%s_commit_id' % repo)
488       commit_id = open(commit_id_file, 'r').readline().strip()
489       subprocess.check_call(repo_tools.GitCmd() + ['checkout', commit_id],
490                             cwd=destination)
491
492
493 def InstallMinGWHostCompiler():
494   """Install the MinGW host compiler used to build the host tools on Windows.
495
496   We could use an ordinary source rule for this, but that would require hashing
497   hundreds of MB of toolchain files on every build. Instead, check for the
498   presence of the specially-named file <version>.installed in the install
499   directory. If it is absent, check for the presence of the zip file
500   <version>.zip. If it is absent, attempt to download it from Google Storage.
501   Then extract the zip file and create the install file.
502   """
503   if not os.path.isfile(os.path.join(MINGW_PATH, MINGW_VERSION + '.installed')):
504     downloader = gsd_storage.GSDStorage([], ['nativeclient-mingw'])
505     zipfilename = MINGW_VERSION + '.zip'
506     zipfilepath = os.path.join(NACL_DIR, zipfilename)
507     # If the zip file is not present, try to download it from Google Storage.
508     # If that fails, bail out.
509     if (not os.path.isfile(zipfilepath) and
510         not downloader.GetSecureFile(zipfilename, zipfilepath)):
511         print >>sys.stderr, 'Failed to install MinGW tools:'
512         print >>sys.stderr, 'could not find or download', zipfilename
513         sys.exit(1)
514     logging.info('Extracting %s' % zipfilename)
515     zf = zipfile.ZipFile(zipfilepath)
516     if os.path.exists(MINGW_PATH):
517       shutil.rmtree(MINGW_PATH)
518     zf.extractall(NACL_DIR)
519     with open(os.path.join(MINGW_PATH, MINGW_VERSION + '.installed'), 'w') as _:
520       pass
521   os.environ['MINGW'] = MINGW_PATH
522
523 if __name__ == '__main__':
524   # This sets the logging for gclient-alike repo sync. It will be overridden
525   # by the package builder based on the command-line flags.
526   logging.getLogger().setLevel(logging.DEBUG)
527   parser = argparse.ArgumentParser(add_help=False)
528   parser.add_argument('--legacy-repo-sync', action='store_true',
529                       dest='legacy_repo_sync', default=False,
530                       help='Sync the git repo directories used by build.sh')
531   parser.add_argument('--build-64bit-host', action='store_true',
532                       dest='build_64bit_host', default=False,
533                       help='Build 64-bit Linux host binaries in addition to 32')
534   parser.add_argument('--cmake', action='store_true', default=False,
535                       help="Use LLVM's cmake ninja build instead of autoconf")
536   parser.add_argument('--clang', action='store_true', default=False,
537                       help="Use clang instead of gcc with LLVM's cmake build")
538   parser.add_argument('--sanitize', choices=['address', 'thread', 'undefined'],
539                       help="Use a sanitizer with LLVM's clang cmake build")
540   args, leftover_args = parser.parse_known_args()
541   if '-h' in leftover_args or '--help' in leftover_args:
542     print 'The following arguments are specific to toolchain_build_pnacl.py:'
543     parser.print_help()
544     print 'The rest of the arguments are generic, in toolchain_main.py'
545
546   if args.sanitize and not args.cmake:
547     print 'Use of sanitizers requires a cmake build'
548     sys.exit(1)
549   if args.clang and not args.cmake:
550     print 'Use of clang is currently only supported with cmake/ninja'
551     sys.exit(1)
552
553   revisions = ParseComponentRevisionsFile(GIT_DEPS_FILE)
554   if args.legacy_repo_sync:
555     SyncPNaClRepos(revisions)
556     sys.exit(0)
557
558   if (pynacl.platform.IsWindows() and
559       not command.Runnable.use_cygwin):
560     InstallMinGWHostCompiler()
561
562   packages = {}
563   packages.update(HostToolsSources(GetGitSyncCmdCallback(revisions)))
564
565   if pynacl.platform.Is64BitLinux():
566     hosts = ['i686-linux']
567     if args.build_64bit_host:
568       hosts.append(NativeTriple())
569   else:
570     hosts = [NativeTriple()]
571   if pynacl.platform.IsLinux() and BUILD_CROSS_MINGW:
572     hosts.append('i686-w64-mingw32')
573   for host in hosts:
574     packages.update(HostLibs(host))
575     packages.update(HostTools(host, args))
576   # Don't build the target libs on Windows because of pathname issues.
577   # Don't build the target libs on Mac because the gold plugin's rpaths
578   # aren't right.
579   # On linux use the 32-bit compiler to build the target libs since that's what
580   # most developers will be using.
581   if pynacl.platform.IsLinux():
582     packages.update(pnacl_targetlibs.TargetLibsSrc(
583       GetGitSyncCmdCallback(revisions)))
584     for bias in BITCODE_BIASES:
585       packages.update(pnacl_targetlibs.BitcodeLibs(hosts[0], bias))
586     for arch in ALL_ARCHES:
587       packages.update(pnacl_targetlibs.NativeLibs(hosts[0], arch))
588     packages.update(pnacl_targetlibs.NativeLibsUnsandboxed('linux-x86-32'))
589   packages.update(Metadata())
590
591   tb = toolchain_main.PackageBuilder(packages,
592                                      leftover_args)
593   tb.Main()