Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / toolchain_build / toolchain_build_bionic.py
1 #!/usr/bin/python
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.
5
6 """Recipes for NativeClient toolchain packages.
7
8 The real entry plumbing is in toolchain_main.py.
9 """
10
11 import argparse
12 import fnmatch
13 import os
14 import process
15 import stat
16 import shutil
17 import StringIO
18 import sys
19
20 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
21 import pynacl.gsd_storage
22 import pynacl.hashing_tools
23 import pynacl.platform
24 import pynacl.repo_tools
25
26 BUILD_SCRIPT = os.path.abspath(__file__)
27 TOOLCHAIN_BUILD = os.path.dirname(BUILD_SCRIPT)
28 NATIVE_CLIENT = os.path.dirname(TOOLCHAIN_BUILD)
29 PKG_VERSION = os.path.join(NATIVE_CLIENT, 'build', 'package_version')
30 sys.path.append(PKG_VERSION)
31 import archive_info
32 import package_info
33
34 import toolchain_build
35 import toolchain_main
36
37 from file_update import Mkdir, Rmdir, Symlink
38 from file_update import NeedsUpdate, UpdateFromTo, UpdateText
39
40
41 BIONIC_VERSION = '17f8f59d2fbdcd72a57e94ffaeff465601d68450'
42 ARCHES = ['arm']
43 TOOLCHAIN_BUILD_SRC = os.path.join(TOOLCHAIN_BUILD, 'src')
44 TOOLCHAIN_BUILD_OUT = os.path.join(TOOLCHAIN_BUILD, 'out')
45
46 BIONIC_SRC = os.path.join(TOOLCHAIN_BUILD_SRC, 'bionic')
47 TOOLCHAIN = os.path.join(NATIVE_CLIENT, 'toolchain')
48
49
50 def GetToolchainPath(target_arch, libc, *extra_paths):
51   os_name = pynacl.platform.GetOS()
52   host_arch = pynacl.platform.GetArch()
53   return os.path.join(TOOLCHAIN,
54                       '%s_%s' % (os_name, host_arch),
55                       'nacl_%s_%s' % (target_arch, libc),
56                       *extra_paths)
57
58
59 def GetBionicBuildPath(target_arch, *extra_paths):
60   os_name = pynacl.platform.GetOS()
61   return os.path.join(TOOLCHAIN_BUILD_OUT,
62                       "%s_%s_bionic" % (os_name, target_arch),
63                       *extra_paths)
64
65
66 def ReplaceText(text, maplist):
67   for m in maplist:
68     for key in m:
69       text = text.replace(key, m[key])
70   return text
71
72
73 def ReplaceArch(text, arch, subarch=None):
74   NACL_ARCHES = {
75     'arm': 'arm',
76     'x86': 'x86_64',
77     'pnacl': 'pnacl'
78   }
79   GCC_ARCHES = {
80     'arm': 'arm',
81     'x86': 'i686',
82     'pnacl': 'pnacl'
83   }
84   CPU_ARCHES = {
85     'arm': 'arm',
86     'x86': 'amd64',
87     'pnacl': 'pnacl'
88   }
89   VERSION_MAP = {
90     'arm': '4.8.2',
91     'x86': '4.4.3',
92   }
93   REPLACE_MAP = {
94     '$NACL': NACL_ARCHES[arch],
95     '$GCC': GCC_ARCHES[arch],
96     '$CPU': CPU_ARCHES[arch],
97     '$SUB': subarch or '',
98     '$ARCH': arch,
99     '$VER': VERSION_MAP[arch]
100   }
101   return ReplaceText(text, [REPLACE_MAP])
102
103
104 def Clobber(fast=False):
105   if not fast:
106     Rmdir(os.path.join(TOOLCHAIN_BUILD, 'cache'))
107     Rmdir(os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_arm_work'))
108
109   BUILD_DIRS = [
110     'linux_%s_bionic',
111     'bionic_%s_work',
112   ]
113
114   for arch in ARCHES:
115     Rmdir(GetToolchainPath(arch, 'bionic'))
116     for workdir in BUILD_DIRS:
117       Rmdir(os.path.join(TOOLCHAIN_BUILD_OUT, workdir % arch))
118
119
120 def FetchAndBuild_gcc_libs():
121   tc_args = ['-y', '--no-use-remote-cache', 'gcc_libs_arm']
122   # Call toolchain_build to build the gcc libs. We do not need to fill in
123   # any package targets since we are using toolchain_build as an
124   # intermediate step.
125   toolchain_main.PackageBuilder(toolchain_build.PACKAGES, {}, tc_args).Main()
126
127
128 def FetchBionicSources():
129   project = 'bionic'
130   url = '%s/nacl-%s.git' % (toolchain_build.GIT_BASE_URL, project)
131   pynacl.repo_tools.SyncGitRepo(url,
132                                 os.path.join(TOOLCHAIN_BUILD_SRC, project),
133                                 BIONIC_VERSION)
134
135
136 def MungeIRT(src, dst):
137   replace_map = {
138     'off_t': 'int64_t',
139     'native_client/src/untrusted/irt/' : '',
140   }
141
142   with open(src, 'r') as srcf:
143     text = srcf.read()
144     text = ReplaceText(text, [replace_map])
145     with open(dst, 'w') as dstf:
146       dstf.write(text)
147
148
149 def CreateBasicToolchain():
150   # Create a toolchain directory containing only the toolchain binaries and
151   # basic files line nacl_arm_macros.s.
152   arch = 'arm'
153   UpdateFromTo(GetToolchainPath(arch, 'newlib'),
154                GetBionicBuildPath(arch),
155                filters=['*arm-nacl/include*', '*arm-nacl/lib*','*.a', '*.o'])
156   UpdateFromTo(GetToolchainPath(arch, 'newlib'),
157                GetBionicBuildPath(arch),
158                paterns=['*.s'])
159
160   #  Static build uses:
161   #     crt1.o crti.o 4.8.2/crtbeginT.o ... 4.8.2/crtend.o crtn.o
162   # -shared build uses:
163   #     crti.o 4.8.2/crtbeginS.o ... 4.8.2/crtendS.o crtn.o crtn.o
164   # However we only provide a crtbegin(S) and crtend(S)
165   EMPTY = """/*
166  * This is a dummy linker script.
167  * libnacl.a, libcrt_common.a, crt0.o crt1.o crti.o and crtn.o are all
168  * empty.  Instead all the work is done by crtbegin(S).o and crtend(S).o and
169  * the bionic libc.  These are provided for compatability with the newlib
170  * toolchain binaries.
171  */"""
172   EMPTY_FILES = ['crt0.o', 'crt1.o', 'crti.o', 'crtn.o',
173                  'libnacl.a', 'libcrt_common.a', 'libpthread.a']
174
175   # Bionic uses the following include paths
176   BIONIC_PAIRS = [
177     ('bionic/libc/arch-nacl/syscalls/irt_poll.h',
178         '$NACL-nacl/include/irt_poll.h'),
179     ('bionic/libc/arch-nacl/syscalls/irt_socket.h',
180         '$NACL-nacl/include/irt_socket.h'),
181     ('bionic/libc/include', '$NACL-nacl/include'),
182     ('bionic/libc/arch-nacl/syscalls/nacl_socket.h',
183         '$NACL-nacl/include/nacl_socket.h'),
184     ('bionic/libc/arch-nacl/syscalls/nacl_stat.h',
185         '$NACL-nacl/include/nacl_stat.h'),
186     ('bionic/libc/arch-$ARCH/include/machine',
187         '$NACL-nacl/include/machine'),
188     ('bionic/libc/kernel/common', '$NACL-nacl/include'),
189     ('bionic/libc/kernel/arch-$ARCH/asm', '$NACL-nacl/include/asm'),
190     ('bionic/libm/include', '$NACL-nacl/include'),
191     ('bionic/libm/$CPU', '$NACL-nacl/include'),
192     ('bionic/safe-iop/include', '$NACL-nacl/include'),
193     ('bionic/libstdc++/nacl',
194         '$NACL-nacl/include/c++/4.8.2/$NACL-nacl'),
195     ('bionic/nacl/$ARCH', '.'),
196   ]
197
198
199   for arch in ARCHES:
200     for name in ['irt.h', 'irt_dev.h']:
201       src = os.path.join(NATIVE_CLIENT, 'src', 'untrusted', 'irt', name)
202       dst = GetBionicBuildPath(arch, '$NACL-nacl', 'include', name)
203       MungeIRT(src, ReplaceArch(dst, arch))
204
205     inspath = GetBionicBuildPath(arch)
206
207     # Create empty objects and libraries
208     libpath = ReplaceArch(os.path.join(inspath, '$NACL-nacl', 'lib'), arch)
209     for name in EMPTY_FILES:
210       UpdateText(os.path.join(libpath, name), EMPTY)
211
212     # Copy BIONIC files to toolchain
213     for src, dst in BIONIC_PAIRS:
214       srcpath = ReplaceArch(os.path.join(TOOLCHAIN_BUILD_SRC, src), arch)
215       dstpath = ReplaceArch(os.path.join(inspath, dst), arch)
216       UpdateFromTo(srcpath, dstpath)
217
218     # Build specs file
219     gcc = ReplaceArch(os.path.join(inspath, 'bin', '$NACL-nacl-gcc'), arch)
220     lib = ReplaceArch(os.path.join(inspath, 'lib/gcc/$NACL-nacl/$VER'), arch)
221     specs = os.path.join(lib, 'specs')
222     with open(specs, 'w') as specfile:
223       process.Run([gcc, '-dumpspecs'], cwd=None, shell=False,
224                   outfile=specfile, verbose=False)
225     text = open(specs, 'r').read()
226
227     # Replace items in the spec file
228     text = ReplaceText(text, [{
229       '-lgcc': '-lgcc --as-needed %{!static: -lgcc_s} --no-as-needed %{!shared: -lgcc_eh}',
230       '--hash-style=gnu': '--hash-style=sysv',
231     }])
232     open(specs, 'w').write(text)
233
234
235 def ConfigureAndBuild_libc():
236   for arch in ARCHES:
237     inspath = GetBionicBuildPath(arch)
238     workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
239     workpath = ReplaceArch(workpath, arch)
240     ConfigureAndBuild(arch, 'bionic/libc', workpath, inspath, )
241
242
243 def ConfigureAndBuild_libc():
244   for arch in ARCHES:
245     inspath = GetBionicBuildPath(arch)
246     workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
247     workpath = ReplaceArch(workpath, arch)
248     ConfigureAndBuild(arch, 'bionic/libc', workpath, inspath)
249     ConfigureAndBuild(arch, 'bionic/libm', workpath, inspath)
250
251
252 def ConfigureAndBuildLinker():
253   for arch in ARCHES:
254     inspath = GetBionicBuildPath(arch)
255     workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
256     workpath = ReplaceArch(workpath, arch)
257     ConfigureAndBuild(arch, 'bionic/linker', workpath, inspath)
258
259
260 def ConfigureGCCProject(arch, project, cfg, workpath, inspath):
261   # configure does not always have +x
262   filepath = os.path.abspath(os.path.join(workpath, cfg[0]))
263   st_info  = os.stat(filepath)
264   os.chmod(filepath, st_info.st_mode | stat.S_IEXEC)
265
266   env = os.environ
267   newpath = GetBionicBuildPath(arch, 'bin')  + ':' + env['PATH']
268
269   proj = '%s %s' % (project, arch)
270   setpath = ['/usr/bin/env', 'PATH=' + newpath]
271
272   # Check if config changed or script is new
273   config_path = os.path.join(workpath, 'config.info')
274   updated = UpdateText(config_path, ' '.join(cfg))
275   updated |= NeedsUpdate(config_path, BUILD_SCRIPT)
276
277   if updated:
278     print 'Configure ' + proj
279     if process.Run(setpath + cfg, cwd=workpath, env=env, outfile=sys.stdout):
280       raise RuntimeError('Failed to configure %s.\n' % proj)
281   else:
282     print 'Reusing config for %s.' % proj
283
284
285 def MakeGCCProject(arch, project, workpath, targets=[]):
286   env = os.environ
287   newpath = GetBionicBuildPath(arch, 'bin')  + ':' + env['PATH']
288   proj = '%s %s' % (project, arch)
289   setpath = ['/usr/bin/env', 'PATH=' + newpath]
290
291   if targets:
292     proj = project = ': ' + ' '.join(targets)
293   else:
294     proj = project
295
296   print 'Make ' + proj
297   if process.Run(setpath + ['make', '-j16', 'V=1'] + targets,
298                   cwd=workpath, outfile=sys.stdout):
299     raise RuntimeError('Failed to build %s.\n' % proj)
300   print 'Done ' + proj
301
302
303 def ConfigureAndBuild_libgcc(skip_build=False):
304   arch = 'arm'
305   project = 'libgcc'
306   tcpath = GetBionicBuildPath(arch)
307
308   # Prep work path
309   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
310   workpath = ReplaceArch(workpath, arch)
311
312   if not skip_build:
313     Mkdir(workpath)
314     Symlink('../gcc_libs_arm_work/gcc' , os.path.join(workpath, 'gcc'))
315
316   # Prep install path
317   inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
318   inspath = ReplaceArch(inspath, arch)
319
320   dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libgcc'), arch)
321   cfg = [
322     '../../../../src/gcc_libs/libgcc/configure',
323     '--host=arm-nacl',
324     '--build=i686-linux',
325     '--target=arm-nacl',
326     '--enable-shared',
327     '--enable-shared-libgcc',
328     '--with-dwarf3',
329     '--with-newlib',
330     '--prefix=' + inspath,
331     'CFLAGS=-I../../../gcc_lib_arm_work'
332   ]
333
334   if not skip_build:
335     ConfigureGCCProject(arch, project, cfg, dstpath, inspath)
336     MakeGCCProject(arch, project, dstpath, ['libgcc.a'])
337
338   # Copy temp version of libgcc.a for linking libc.so
339   UpdateFromTo(os.path.join(dstpath, 'libgcc.a'),
340                os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc.a'))
341
342
343 def BuildAndInstall_libgcc_s(skip_build=False):
344   arch = 'arm'
345   project = 'libgcc'
346   tcpath = GetBionicBuildPath(arch)
347
348   # Remove temp copy of libgcc.a, it get's installed at the end
349   os.remove(os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc.a'))
350
351   # Prep work path
352   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
353   workpath = ReplaceArch(workpath, arch)
354   dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libgcc'), arch)
355
356   # Prep install path
357   inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
358   inspath = ReplaceArch(inspath, arch)
359
360   if not skip_build:
361     MakeGCCProject(arch, project, dstpath)
362     MakeGCCProject(arch, project, dstpath, ['install'])
363
364   UpdateFromTo(os.path.join(inspath, 'lib', 'gcc'),
365                os.path.join(tcpath, 'lib', 'gcc'),
366                filters=['*.o'])
367   UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so.1'),
368                os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so.1'))
369   UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so'),
370                os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so'))
371
372
373 def ConfigureAndBuild_libstdcpp():
374   arch = 'arm'
375   project = 'libstdc++'
376   tcpath = GetBionicBuildPath(arch)
377
378   # Prep work path
379   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
380   workpath = ReplaceArch(workpath, arch)
381
382   # Prep install path
383   inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
384   inspath = ReplaceArch(inspath, arch)
385
386   dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libstdc++-v3'), arch)
387   Mkdir(dstpath)
388   cfg = [
389     '../../../../src/gcc_libs/libstdc++-v3/configure',
390     '--host=arm-nacl',
391     '--build=i686-linux',
392     '--target=arm-nacl',
393     '--enable-shared',
394     '--with-newlib',
395     '--disable-libstdcxx-pch',
396     '--enable-shared-libgcc',
397     '--with-dwarf3',
398     '--prefix=' + inspath,
399     'CFLAGS=-I../../../gcc_lib_arm_work'
400   ]
401
402   ConfigureGCCProject(arch, project, cfg, dstpath, inspath)
403   MakeGCCProject(arch, project, dstpath)
404   MakeGCCProject(arch, project, dstpath, ['install'])
405
406   filelist = [
407     'libstdc++.a',
408     'libstdc++.la',
409     'libstdc++.so',
410     'libstdc++.so.6',
411     'libstdc++.so.6.0.18',
412     'libstdc++.so.6.0.18-gdb.py',
413     'libsupc++.a',
414     'libsupc++.la'
415   ]
416   for filename in filelist:
417     UpdateFromTo(os.path.join(inspath, 'lib', filename),
418                 os.path.join(tcpath, 'arm-nacl', 'lib', filename))
419
420   UpdateFromTo(os.path.join(inspath, 'include'),
421                os.path.join(tcpath, 'arm-nacl', 'include'))
422
423
424 def GetProjectPaths(arch, project):
425   srcpath = os.path.join(BIONIC_SRC, project)
426   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
427   instpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_install')
428
429   toolpath = GetBionicBuildPath(arch)
430   workpath = ReplaceArch(os.path.join(workpath, 'bionic', project), arch)
431   instpath = ReplaceArch(os.path.join(toolpath, '$NACL-nacl', 'lib'), arch)
432   out = {
433     'src': srcpath,
434     'work': workpath,
435     'ins': instpath,
436     'tc': toolpath,
437   }
438   return out
439
440
441 def CreateProject(arch, project, clobber=False):
442   paths = GetProjectPaths(arch, project)
443
444   MAKEFILE_TEMPLATE = """
445 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
446 # Use of this source code is governed by a BSD-style license that can be
447 # found in the LICENSE file.
448
449 # GNU Makefile based on shared rules provided by the Native Client SDK.
450 # See README.Makefiles for more details.
451
452 NATIVE_CLIENT_PATH?=$(nacl_path)
453 TOOLCHAIN_PATH?=$(tc_path)
454 TOOLCHAIN_PREFIX:=$(TOOLCHAIN_PATH)/bin/$GCC-nacl-
455
456 CC:=$(TOOLCHAIN_PREFIX)gcc
457 CXX:=$(TOOLCHAIN_PREFIX)g++
458 AR:=$(TOOLCHAIN_PREFIX)ar
459
460 SRC_ROOT=$(src_path)
461 DST_ROOT=$(dst_path)
462 INS_ROOT=$(ins_path)
463
464 NACL_ARCH=$NACL
465 GCC_ARCH=$GCC
466
467 MAKEFILE_DEPS:=$(build_tc_path)/tc_bionic.mk
468 MAKEFILE_DEPS+=$(src_path)/Makefile
469
470 include $(build_tc_path)/tc_bionic.mk
471 include $(src_path)/Makefile
472 """
473   remap = {
474     '$(src_path)': paths['src'],
475     '$(dst_path)': paths['work'],
476     '$(ins_path)': paths['ins'],
477     '$(tc_path)':  GetBionicBuildPath(arch),
478     '$(build_tc_path)': TOOLCHAIN_BUILD,
479     '$(nacl_path)': NATIVE_CLIENT,
480   }
481   text = ReplaceText(MAKEFILE_TEMPLATE, [remap])
482   text = ReplaceArch(text, arch)
483
484   if clobber:
485     print 'Clobbering Bionic project directory: ' + paths['work']
486     Rmdir(paths['work'])
487
488   Mkdir(paths['work'])
489   Mkdir(paths['ins'])
490   UpdateText(os.path.join(paths['work'], 'Makefile'), text)
491
492
493 def ConfigureBionicProjects(clobber=False):
494   PROJECTS = ['libc', 'libm', 'linker', 'tests', 'newlinker', 'newtests']
495   arch = 'arm'
496   for project in PROJECTS:
497     print 'Configure %s for %s.' % (project, arch)
498     CreateProject(arch, project, clobber)
499
500
501 def MakeBionicProject(project, targets=[], clobber=False):
502   arch = 'arm'
503   paths = GetProjectPaths(arch, project)
504   workpath = paths['work']
505   inspath = paths['ins']
506   targetlist = ' '.join(targets)
507
508   print 'Building %s for %s at %s %s.' % (project, arch, workpath, targetlist)
509   if clobber:
510     args = ['make', '-j12', 'V=1', 'clean']
511     if process.Run(args, cwd=workpath, outfile=sys.stdout):
512       raise RuntimeError('Failed to clean %s for %s.\n' % (project, arch))
513
514   args = ['make', '-j12', 'V=1'] + targets
515   if process.Run(args, cwd=workpath, outfile=sys.stdout):
516     raise RuntimeError('Failed to build %s for %s.\n' % (project, arch))
517
518   print 'Done with %s for %s.\n' % (project, arch)
519
520
521 def ArchiveAndUpload(version, zipname, zippath, packages_file):
522   sys.stdout.flush()
523   print >>sys.stderr, '@@@BUILD_STEP archive_and_upload@@@'
524
525   bucket_path = 'nativeclient-archive2/toolchain/%s' % version
526   gsd_store = pynacl.gsd_storage.GSDStorage(bucket_path, [bucket_path])
527
528   zipname = os.path.join(TOOLCHAIN_BUILD_OUT, zipname)
529   try:
530     os.remove(zipname)
531   except:
532     pass
533
534   # Archive the zippath to the zipname.
535   if process.Run(['tar', '-czf', zipname, zippath],
536                  cwd=TOOLCHAIN_BUILD_OUT,
537                  outfile=sys.stdout):
538       raise RuntimeError('Failed to zip %s from %s.\n' % (zipname, zippath))
539
540   # Create Zip Hash file using the hash of the zip file.
541   hashzipname = zipname + '.sha1hash'
542   hashval = pynacl.hashing_tools.HashFileContents(zipname)
543   with open(hashzipname, 'w') as f:
544     f.write(hashval)
545
546   # Upload the Zip file.
547   zipurl = gsd_store.PutFile(zipname, os.path.basename(zipname))
548   sys.stdout.flush()
549   print >>sys.stderr, ('@@@STEP_LINK@download (%s)@%s@@@' %
550                        (os.path.basename(zipname), zipurl))
551
552   # Upload the Zip Hash file.
553   hashurl = gsd_store.PutFile(hashzipname, os.path.basename(hashzipname))
554   sys.stdout.flush()
555   print >>sys.stderr, ('@@@STEP_LINK@download (%s)@%s@@@' %
556                        (os.path.basename(hashzipname), hashurl))
557
558   # Create a package info file for the nacl_arm_bionic package.
559   archive_desc = archive_info.ArchiveInfo(name=os.path.basename(zipname),
560                                           archive_hash=hashval,
561                                           tar_src_dir='linux_arm_bionic',
562                                           url=zipurl)
563   package_desc = package_info.PackageInfo()
564   package_desc.AppendArchive(archive_desc)
565
566   os_name = pynacl.platform.GetOS()
567   arch_name = pynacl.platform.GetArch()
568   package_info_file = os.path.join(TOOLCHAIN_BUILD_OUT,
569                                    'packages',
570                                    '%s_%s' % (os_name, arch_name),
571                                    'nacl_arm_bionic.json')
572   package_desc.SavePackageFile(package_info_file)
573
574   # If packages_file is specified, write out our packages file of 1 package.
575   if packages_file:
576     with open(packages_file, 'wt') as f:
577       f.write(package_info_file)
578
579
580 def main(argv):
581   parser = argparse.ArgumentParser(add_help=False)
582   parser.add_argument(
583       '-v', '--verbose', dest='verbose',
584       default=False, action='store_true',
585       help='Produce more output.')
586
587   parser.add_argument(
588       '-c', '--clobber', dest='clobber',
589       default=False, action='store_true',
590       help='Clobber working directories before building.')
591
592   parser.add_argument(
593       '-f', '--fast-clobber', dest='fast_clobber',
594       default=False, action='store_true',
595       help='Clobber bionic working directories before building.')
596
597   parser.add_argument(
598       '-s', '--sync', dest='sync',
599       default=False, action='store_true',
600       help='Sync sources first.')
601
602   parser.add_argument(
603       '-b', '--buildbot', dest='buildbot',
604       default=False, action='store_true',
605       help='Running on the buildbot.')
606
607   parser.add_argument(
608       '-l', '--llvm', dest='llvm',
609       default=False, action='store_true',
610       help='Enable building via llvm.')
611
612   parser.add_argument(
613       '-u', '--upload', dest='upload',
614       default=False, action='store_true',
615       help='Upload build artifacts.')
616
617   parser.add_argument(
618         '--packages-file', dest='packages_file',
619         default=None,
620         help='Output packages file describing list of package files built.')
621
622   parser.add_argument(
623       '--skip-gcc', dest='skip_gcc',
624       default=False, action='store_true',
625       help='Skip building GCC components.')
626
627   options, leftover_args = parser.parse_known_args()
628   if '-h' in leftover_args or '--help' in leftover_args:
629     print 'The following arguments are specific to toolchain_build_bionic.py:'
630     parser.print_help()
631     print 'The rest of the arguments are generic, in toolchain_main.py'
632     return 1
633
634   if options.llvm:
635     ARCHES.append('pnacl')
636
637   if options.buildbot or options.upload:
638     version = os.environ['BUILDBOT_REVISION']
639
640   if options.clobber or options.fast_clobber:
641     Clobber(fast=options.fast_clobber)
642
643   if options.sync or options.buildbot:
644     FetchBionicSources()
645
646   # Copy headers and compiler tools
647   CreateBasicToolchain()
648
649   # Configure Bionic Projects, libc, libm, linker, tests, ...
650   ConfigureBionicProjects(clobber=options.buildbot)
651
652   # Build and install IRT header before building GCC
653   MakeBionicProject('libc', ['irt'])
654
655   if not options.skip_gcc:
656     # Build newlib gcc_libs for use by bionic
657     FetchAndBuild_gcc_libs()
658
659   # Configure and build libgcc.a
660   ConfigureAndBuild_libgcc(skip_build=options.skip_gcc)
661
662   # With libgcc.a, we can now build libc.so
663   MakeBionicProject('libc')
664
665   # With libc.so, we can build libgcc_s.so
666   BuildAndInstall_libgcc_s(skip_build=options.skip_gcc)
667
668   # With libc and libgcc_s, we can now build libm
669   MakeBionicProject('libm')
670
671   # With libc, libgcc, and libm, we can now build libstdc++
672   ConfigureAndBuild_libstdcpp()
673
674   # Now we can build the linker
675   #MakeBionicProject('linker')
676   MakeBionicProject('newlinker')
677
678   # Now we have a full toolchain, so test it
679   #MakeBionicProject('tests')
680   MakeBionicProject('newtests')
681
682   # We can run only off buildbots
683   if not options.buildbot:
684     process.Run(['./scons', 'platform=arm', '--mode=nacl,dbg-linux', '-j20'],
685                 cwd=NATIVE_CLIENT)
686     MakeBionicProject('tests', ['run'])
687     MakeBionicProject('newtests', ['run'])
688
689   dst = os.path.join(TOOLCHAIN_BUILD_OUT, 'linux_arm_bionic', 'log.txt')
690   with open(dst, 'w') as dstf:
691     process.Run(['git', 'log', '-n', '1'],
692                 cwd=os.path.join(TOOLCHAIN_BUILD_SRC, 'bionic'),
693                 outfile=dstf,
694                 verbose=False)
695
696   if options.buildbot or options.upload:
697     zipname = 'naclsdk_linux_arm_bionic.tgz'
698     ArchiveAndUpload(version, zipname, 'linux_arm_bionic',
699                      options.packages_file)
700
701
702 if __name__ == '__main__':
703   sys.exit(main(sys.argv))