Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / toolchain_build / toolchain_build_bionic.py
index 829ed64..234b54a 100755 (executable)
@@ -8,50 +8,59 @@
 The real entry plumbing is in toolchain_main.py.
 """
 
-# Done first to setup python module path.
-import toolchain_env
-
+import argparse
 import fnmatch
-import hashing_tools
 import os
-import optparse
 import process
-import repo_tools
 import stat
 import shutil
 import StringIO
 import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+import pynacl.gsd_storage
+import pynacl.hashing_tools
+import pynacl.platform
+import pynacl.repo_tools
+
+BUILD_SCRIPT = os.path.abspath(__file__)
+TOOLCHAIN_BUILD = os.path.dirname(BUILD_SCRIPT)
+NATIVE_CLIENT = os.path.dirname(TOOLCHAIN_BUILD)
+PKG_VERSION = os.path.join(NATIVE_CLIENT, 'build', 'package_version')
+sys.path.append(PKG_VERSION)
+import archive_info
+import package_info
+
 import toolchain_build
 import toolchain_main
 
 from file_update import Mkdir, Rmdir, Symlink
 from file_update import NeedsUpdate, UpdateFromTo, UpdateText
 
-BIONIC_VERSION = '171e152bc66aec14029e90edc69d94af4f289bab'
 
+BIONIC_VERSION = '17f8f59d2fbdcd72a57e94ffaeff465601d68450'
 ARCHES = ['arm']
-
-BUILD_SCRIPT = os.path.abspath(__file__)
-TOOLCHAIN_BUILD = os.path.dirname(BUILD_SCRIPT)
 TOOLCHAIN_BUILD_SRC = os.path.join(TOOLCHAIN_BUILD, 'src')
 TOOLCHAIN_BUILD_OUT = os.path.join(TOOLCHAIN_BUILD, 'out')
 
 BIONIC_SRC = os.path.join(TOOLCHAIN_BUILD_SRC, 'bionic')
-
-NATIVE_CLIENT = os.path.dirname(TOOLCHAIN_BUILD)
 TOOLCHAIN = os.path.join(NATIVE_CLIENT, 'toolchain')
 
-ARM_NEWLIB = os.path.join(TOOLCHAIN, 'linux_arm_newlib')
-ARM_BIONIC = os.path.join(TOOLCHAIN, 'linux_arm_bionic')
-X86_NEWLIB = os.path.join(TOOLCHAIN, 'linux_x86_newlib')
-X86_BIONIC = os.path.join(TOOLCHAIN, 'linux_x86_bionic')
 
+def GetToolchainPath(target_arch, libc, *extra_paths):
+  os_name = pynacl.platform.GetOS()
+  host_arch = pynacl.platform.GetArch()
+  return os.path.join(TOOLCHAIN,
+                      '%s_%s' % (os_name, host_arch),
+                      'nacl_%s_%s' % (target_arch, libc),
+                      *extra_paths)
 
-PROJECTS = [
-  'bionic_%s_work',
-  'gcc_%s_work',
-  'test_%s_work',
-]
+
+def GetBionicBuildPath(target_arch, *extra_paths):
+  os_name = pynacl.platform.GetOS()
+  return os.path.join(TOOLCHAIN_BUILD_OUT,
+                      "%s_%s_bionic" % (os_name, target_arch),
+                      *extra_paths)
 
 
 def ReplaceText(text, maplist):
@@ -64,15 +73,18 @@ def ReplaceText(text, maplist):
 def ReplaceArch(text, arch, subarch=None):
   NACL_ARCHES = {
     'arm': 'arm',
-    'x86': 'x86_64'
+    'x86': 'x86_64',
+    'pnacl': 'pnacl'
   }
   GCC_ARCHES = {
     'arm': 'arm',
-    'x86': 'i686'
+    'x86': 'i686',
+    'pnacl': 'pnacl'
   }
   CPU_ARCHES = {
     'arm': 'arm',
-    'x86': 'amd64'
+    'x86': 'amd64',
+    'pnacl': 'pnacl'
   }
   VERSION_MAP = {
     'arm': '4.8.2',
@@ -89,42 +101,61 @@ def ReplaceArch(text, arch, subarch=None):
   return ReplaceText(text, [REPLACE_MAP])
 
 
-def Clobber():
-  Rmdir(os.path.join(TOOLCHAIN_BUILD, 'cache'))
+def Clobber(fast=False):
+  if not fast:
+    Rmdir(os.path.join(TOOLCHAIN_BUILD, 'cache'))
+    Rmdir(os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_arm_work'))
+
+  BUILD_DIRS = [
+    'linux_%s_bionic',
+    'bionic_%s_work',
+  ]
+
   for arch in ARCHES:
-    Rmdir(os.path.join(TOOLCHAIN, 'linux_%s_bionic' % arch))
-    for workdir in PROJECTS:
+    Rmdir(GetToolchainPath(arch, 'bionic'))
+    for workdir in BUILD_DIRS:
       Rmdir(os.path.join(TOOLCHAIN_BUILD_OUT, workdir % arch))
 
 
-def FetchAndBuildGCC():
-  if 'arm' in ARCHES:
-    tc_args = ['-y', '--no-use-remote-cache', 'gcc_libs_arm']
-    toolchain_main.PackageBuilder(toolchain_build.PACKAGES, tc_args).Main()
-
-  if 'x86' in ARCHES:
-    process.Run(['make', 'sync'], cwd=os.path.join(NATIVE_CLIENT, 'tools'))
+def FetchAndBuild_gcc_libs():
+  tc_args = ['-y', '--no-use-remote-cache', 'gcc_libs_arm']
+  # Call toolchain_build to build the gcc libs. We do not need to fill in
+  # any package targets since we are using toolchain_build as an
+  # intermediate step.
+  toolchain_main.PackageBuilder(toolchain_build.PACKAGES, {}, tc_args).Main()
 
 
 def FetchBionicSources():
   project = 'bionic'
   url = '%s/nacl-%s.git' % (toolchain_build.GIT_BASE_URL, project)
-  repo_tools.SyncGitRepo(url,
-                         os.path.join(TOOLCHAIN_BUILD_SRC, project),
-                         BIONIC_VERSION)
+  pynacl.repo_tools.SyncGitRepo(url,
+                                os.path.join(TOOLCHAIN_BUILD_SRC, project),
+                                BIONIC_VERSION)
+
+
+def MungeIRT(src, dst):
+  replace_map = {
+    'off_t': 'int64_t',
+    'native_client/src/untrusted/irt/' : '',
+  }
+
+  with open(src, 'r') as srcf:
+    text = srcf.read()
+    text = ReplaceText(text, [replace_map])
+    with open(dst, 'w') as dstf:
+      dstf.write(text)
 
 
 def CreateBasicToolchain():
   # Create a toolchain directory containing only the toolchain binaries and
   # basic files line nacl_arm_macros.s.
-
-  UpdateFromTo(ARM_NEWLIB, ARM_BIONIC,
+  arch = 'arm'
+  UpdateFromTo(GetToolchainPath(arch, 'newlib'),
+               GetBionicBuildPath(arch),
                filters=['*arm-nacl/include*', '*arm-nacl/lib*','*.a', '*.o'])
-  UpdateFromTo(ARM_NEWLIB, ARM_BIONIC, paterns=['*.s'])
-
-  UpdateFromTo(X86_NEWLIB, X86_BIONIC,
-               filters=['*x86_64-nacl/include*', '*x86_64-nacl/lib*','*.o'])
-  UpdateFromTo(X86_NEWLIB, X86_BIONIC, paterns=['*.s'])
+  UpdateFromTo(GetToolchainPath(arch, 'newlib'),
+               GetBionicBuildPath(arch),
+               paterns=['*.s'])
 
   #  Static build uses:
   #     crt1.o crti.o 4.8.2/crtbeginT.o ... 4.8.2/crtend.o crtn.o
@@ -143,13 +174,15 @@ def CreateBasicToolchain():
 
   # Bionic uses the following include paths
   BIONIC_PAIRS = [
+    ('bionic/libc/arch-nacl/syscalls/irt_poll.h',
+        '$NACL-nacl/include/irt_poll.h'),
+    ('bionic/libc/arch-nacl/syscalls/irt_socket.h',
+        '$NACL-nacl/include/irt_socket.h'),
     ('bionic/libc/include', '$NACL-nacl/include'),
-    ('bionic/libc/arch-nacl/syscalls/irt.h', '$NACL-nacl/include/irt.h'),
-    ('bionic/libc/arch-nacl/syscalls/irt_syscalls.h',
-        '$NACL-nacl/include/irt_syscalls.h'),
+    ('bionic/libc/arch-nacl/syscalls/nacl_socket.h',
+        '$NACL-nacl/include/nacl_socket.h'),
     ('bionic/libc/arch-nacl/syscalls/nacl_stat.h',
         '$NACL-nacl/include/nacl_stat.h'),
-    ('../../src/untrusted/irt/irt_dev.h', '$NACL-nacl/include/irt_dev.h'),
     ('bionic/libc/arch-$ARCH/include/machine',
         '$NACL-nacl/include/machine'),
     ('bionic/libc/kernel/common', '$NACL-nacl/include'),
@@ -162,9 +195,14 @@ def CreateBasicToolchain():
     ('bionic/nacl/$ARCH', '.'),
   ]
 
+
   for arch in ARCHES:
-    inspath = os.path.join(TOOLCHAIN, 'linux_$ARCH_bionic')
-    inspath = ReplaceArch(inspath, arch)
+    for name in ['irt.h', 'irt_dev.h']:
+      src = os.path.join(NATIVE_CLIENT, 'src', 'untrusted', 'irt', name)
+      dst = GetBionicBuildPath(arch, '$NACL-nacl', 'include', name)
+      MungeIRT(src, ReplaceArch(dst, arch))
+
+    inspath = GetBionicBuildPath(arch)
 
     # Create empty objects and libraries
     libpath = ReplaceArch(os.path.join(inspath, '$NACL-nacl', 'lib'), arch)
@@ -177,11 +215,6 @@ def CreateBasicToolchain():
       dstpath = ReplaceArch(os.path.join(inspath, dst), arch)
       UpdateFromTo(srcpath, dstpath)
 
-    workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
-    workpath = ReplaceArch(workpath, arch)
-    ConfigureAndBuild(arch, 'bionic/libc', workpath, inspath,
-                      target='bootstrap')
-
     # Build specs file
     gcc = ReplaceArch(os.path.join(inspath, 'bin', '$NACL-nacl-gcc'), arch)
     lib = ReplaceArch(os.path.join(inspath, 'lib/gcc/$NACL-nacl/$VER'), arch)
@@ -193,36 +226,46 @@ def CreateBasicToolchain():
 
     # Replace items in the spec file
     text = ReplaceText(text, [{
-      '-lgcc': '-lgcc %{!shared: -lgcc_eh}',
+      '-lgcc': '-lgcc --as-needed %{!static: -lgcc_s} --no-as-needed %{!shared: -lgcc_eh}',
       '--hash-style=gnu': '--hash-style=sysv',
     }])
-
     open(specs, 'w').write(text)
 
 
-def ConfigureAndBuildBionic():
+def ConfigureAndBuild_libc():
   for arch in ARCHES:
-    inspath = os.path.join(TOOLCHAIN, 'linux_$ARCH_bionic')
-    inspath = ReplaceArch(inspath, arch)
+    inspath = GetBionicBuildPath(arch)
+    workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
+    workpath = ReplaceArch(workpath, arch)
+    ConfigureAndBuild(arch, 'bionic/libc', workpath, inspath, )
+
 
+def ConfigureAndBuild_libc():
+  for arch in ARCHES:
+    inspath = GetBionicBuildPath(arch)
     workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
     workpath = ReplaceArch(workpath, arch)
     ConfigureAndBuild(arch, 'bionic/libc', workpath, inspath)
     ConfigureAndBuild(arch, 'bionic/libm', workpath, inspath)
+
+
+def ConfigureAndBuildLinker():
+  for arch in ARCHES:
+    inspath = GetBionicBuildPath(arch)
+    workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
+    workpath = ReplaceArch(workpath, arch)
     ConfigureAndBuild(arch, 'bionic/linker', workpath, inspath)
 
 
-def ConfigureAndInstallForGCC(arch, project, cfg, workpath, inspath):
+def ConfigureGCCProject(arch, project, cfg, workpath, inspath):
   # configure does not always have +x
   filepath = os.path.abspath(os.path.join(workpath, cfg[0]))
   st_info  = os.stat(filepath)
   os.chmod(filepath, st_info.st_mode | stat.S_IEXEC)
 
   env = os.environ
-  if arch == 'arm':
-    newpath = os.path.join(ARM_BIONIC, 'bin') + ':' + env['PATH']
-  else:
-    newpath = os.path.join(X86_BIONIC, 'bin') + ':' + env['PATH']
+  newpath = GetBionicBuildPath(arch, 'bin')  + ':' + env['PATH']
+
   proj = '%s %s' % (project, arch)
   setpath = ['/usr/bin/env', 'PATH=' + newpath]
 
@@ -238,28 +281,37 @@ def ConfigureAndInstallForGCC(arch, project, cfg, workpath, inspath):
   else:
     print 'Reusing config for %s.' % proj
 
+
+def MakeGCCProject(arch, project, workpath, targets=[]):
+  env = os.environ
+  newpath = GetBionicBuildPath(arch, 'bin')  + ':' + env['PATH']
+  proj = '%s %s' % (project, arch)
+  setpath = ['/usr/bin/env', 'PATH=' + newpath]
+
+  if targets:
+    proj = project = ': ' + ' '.join(targets)
+  else:
+    proj = project
+
   print 'Make ' + proj
-  if process.Run(setpath + ['make', '-j16', 'V=1'],
+  if process.Run(setpath + ['make', '-j16', 'V=1'] + targets,
                   cwd=workpath, outfile=sys.stdout):
     raise RuntimeError('Failed to build %s.\n' % proj)
-  print 'Install ' + proj
-  if process.Run(setpath + ['make', '-j16', 'install', 'V=1'],
-                 cwd=workpath, outfile=sys.stdout):
-    raise RuntimeError('Failed to install %s.\n' % proj)
   print 'Done ' + proj
 
 
-def ConfigureAndBuildArmGCC(config=False):
+def ConfigureAndBuild_libgcc(skip_build=False):
   arch = 'arm'
   project = 'libgcc'
-  tcpath = os.path.join(TOOLCHAIN, 'linux_$ARCH_bionic')
-  tcpath = ReplaceArch(tcpath, arch)
+  tcpath = GetBionicBuildPath(arch)
 
   # Prep work path
   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
   workpath = ReplaceArch(workpath, arch)
-  Mkdir(workpath)
-  Symlink('../gcc_libs_arm_work/gcc' , os.path.join(workpath, 'gcc'))
+
+  if not skip_build:
+    Mkdir(workpath)
+    Symlink('../gcc_libs_arm_work/gcc' , os.path.join(workpath, 'gcc'))
 
   # Prep install path
   inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
@@ -278,57 +330,57 @@ def ConfigureAndBuildArmGCC(config=False):
     '--prefix=' + inspath,
     'CFLAGS=-I../../../gcc_lib_arm_work'
   ]
-  ConfigureAndInstallForGCC(arch, project, cfg, dstpath, inspath)
-  UpdateFromTo(os.path.join(inspath, 'lib', 'gcc'),
-               os.path.join(tcpath, 'lib', 'gcc'),
-               filters=['*.o'])
-  UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so.1'),
-               os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so.1'))
-  UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so'),
-               os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so'))
 
+  if not skip_build:
+    ConfigureGCCProject(arch, project, cfg, dstpath, inspath)
+    MakeGCCProject(arch, project, dstpath, ['libgcc.a'])
+
+  # Copy temp version of libgcc.a for linking libc.so
+  UpdateFromTo(os.path.join(dstpath, 'libgcc.a'),
+               os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc.a'))
 
-def ConfigureAndBuildX86GCC(config=False):
-  arch = 'x86'
+
+def BuildAndInstall_libgcc_s(skip_build=False):
+  arch = 'arm'
   project = 'libgcc'
+  tcpath = GetBionicBuildPath(arch)
 
-  tcpath = os.path.join(TOOLCHAIN, 'linux_$ARCH_bionic')
-  tcpath = ReplaceArch(tcpath, arch)
+  # Remove temp copy of libgcc.a, it get's installed at the end
+  os.remove(os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc.a'))
 
   # Prep work path
   workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
   workpath = ReplaceArch(workpath, arch)
-  Mkdir(workpath)
-  Symlink('../gcc_libs_arm_work/gcc' , os.path.join(workpath, 'gcc'))
+  dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libgcc'), arch)
 
   # Prep install path
   inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
   inspath = ReplaceArch(inspath, arch)
 
-  dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libgcc'), arch)
-  cfg = [
-    '../../../../SRC/gcc/libgcc/configure',
-    '--target=x86_64-nacl',
-    '--enable-shared',
-    '--enable-shared-libgcc',
-    '--host=x86_64-nacl',
-    ',--build=i686-linux'
-  ]
+  if not skip_build:
+    MakeGCCProject(arch, project, dstpath)
+    MakeGCCProject(arch, project, dstpath, ['install'])
 
-def ConfigureAndBuildArmCXX(config=False):
+  UpdateFromTo(os.path.join(inspath, 'lib', 'gcc'),
+               os.path.join(tcpath, 'lib', 'gcc'),
+               filters=['*.o'])
+  UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so.1'),
+               os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so.1'))
+  UpdateFromTo(os.path.join(inspath, 'lib', 'libgcc_s.so'),
+               os.path.join(tcpath, 'arm-nacl', 'lib', 'libgcc_s.so'))
+
+
+def ConfigureAndBuild_libstdcpp():
   arch = 'arm'
   project = 'libstdc++'
-  tcpath = os.path.join(TOOLCHAIN, 'linux_$ARCH_bionic')
-  tcpath = ReplaceArch(tcpath, arch)
+  tcpath = GetBionicBuildPath(arch)
 
   # Prep work path
-  workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'cxx_$GCC_bionic_work')
+  workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_work')
   workpath = ReplaceArch(workpath, arch)
-  Mkdir(workpath)
-  Symlink('../gcc_libs_arm_work/gcc' , os.path.join(workpath, 'gcc'))
 
   # Prep install path
-  inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'cxx_$GCC_bionic_install')
+  inspath = os.path.join(TOOLCHAIN_BUILD_OUT, 'gcc_$GCC_bionic_install')
   inspath = ReplaceArch(inspath, arch)
 
   dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl/libstdc++-v3'), arch)
@@ -346,24 +398,59 @@ def ConfigureAndBuildArmCXX(config=False):
     '--prefix=' + inspath,
     'CFLAGS=-I../../../gcc_lib_arm_work'
   ]
-  ConfigureAndInstallForGCC(arch, project, cfg, dstpath, inspath)
-  UpdateFromTo(os.path.join(inspath, 'lib'),
-               os.path.join(tcpath, 'arm-nacl', 'lib'))
+
+  ConfigureGCCProject(arch, project, cfg, dstpath, inspath)
+  MakeGCCProject(arch, project, dstpath)
+  MakeGCCProject(arch, project, dstpath, ['install'])
+
+  filelist = [
+    'libstdc++.a',
+    'libstdc++.la',
+    'libstdc++.so',
+    'libstdc++.so.6',
+    'libstdc++.so.6.0.18',
+    'libstdc++.so.6.0.18-gdb.py',
+    'libsupc++.a',
+    'libsupc++.la'
+  ]
+  for filename in filelist:
+    UpdateFromTo(os.path.join(inspath, 'lib', filename),
+                os.path.join(tcpath, 'arm-nacl', 'lib', filename))
+
   UpdateFromTo(os.path.join(inspath, 'include'),
                os.path.join(tcpath, 'arm-nacl', 'include'))
 
 
+def GetProjectPaths(arch, project):
+  srcpath = os.path.join(BIONIC_SRC, project)
+  workpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_work')
+  instpath = os.path.join(TOOLCHAIN_BUILD_OUT, 'bionic_$ARCH_install')
+
+  toolpath = GetBionicBuildPath(arch)
+  workpath = ReplaceArch(os.path.join(workpath, 'bionic', project), arch)
+  instpath = ReplaceArch(os.path.join(toolpath, '$NACL-nacl', 'lib'), arch)
+  out = {
+    'src': srcpath,
+    'work': workpath,
+    'ins': instpath,
+    'tc': toolpath,
+  }
+  return out
+
+
+def CreateProject(arch, project, clobber=False):
+  paths = GetProjectPaths(arch, project)
 
-def CreateProject(arch, src, dst, ins=None):
   MAKEFILE_TEMPLATE = """
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 # GNU Makefile based on shared rules provided by the Native Client SDK.
 # See README.Makefiles for more details.
 
-TOOLCHAIN_PATH?=$(tc_path)/linux_$ARCH_bionic
+NATIVE_CLIENT_PATH?=$(nacl_path)
+TOOLCHAIN_PATH?=$(tc_path)
 TOOLCHAIN_PREFIX:=$(TOOLCHAIN_PATH)/bin/$GCC-nacl-
 
 CC:=$(TOOLCHAIN_PREFIX)gcc
@@ -377,177 +464,239 @@ INS_ROOT=$(ins_path)
 NACL_ARCH=$NACL
 GCC_ARCH=$GCC
 
+MAKEFILE_DEPS:=$(build_tc_path)/tc_bionic.mk
+MAKEFILE_DEPS+=$(src_path)/Makefile
+
 include $(build_tc_path)/tc_bionic.mk
 include $(src_path)/Makefile
 """
   remap = {
-    '$(src_path)': src,
-    '$(dst_path)': dst,
-    '$(ins_path)': ins or dst,
-    '$(tc_path)': TOOLCHAIN,
-    '$(build_tc_path)': TOOLCHAIN_BUILD
+    '$(src_path)': paths['src'],
+    '$(dst_path)': paths['work'],
+    '$(ins_path)': paths['ins'],
+    '$(tc_path)':  GetBionicBuildPath(arch),
+    '$(build_tc_path)': TOOLCHAIN_BUILD,
+    '$(nacl_path)': NATIVE_CLIENT,
   }
   text = ReplaceText(MAKEFILE_TEMPLATE, [remap])
   text = ReplaceArch(text, arch)
 
-  print 'Create dst dir: ' + dst
-  Mkdir(dst)
-  if ins:
-    print 'Create ins dir: ' + ins
-    Mkdir(ins)
+  if clobber:
+    print 'Clobbering Bionic project directory: ' + paths['work']
+    Rmdir(paths['work'])
 
-  UpdateText(os.path.join(dst, 'Makefile'), text)
+  Mkdir(paths['work'])
+  Mkdir(paths['ins'])
+  UpdateText(os.path.join(paths['work'], 'Makefile'), text)
 
 
-def ConfigureAndBuild(arch, project, workpath, inspath,
-                      tcpath=None, target=None):
+def ConfigureBionicProjects(clobber=False):
+  PROJECTS = ['libc', 'libm', 'linker', 'tests', 'newlinker', 'newtests']
+  arch = 'arm'
+  for project in PROJECTS:
+    print 'Configure %s for %s.' % (project, arch)
+    CreateProject(arch, project, clobber)
 
-  # Create project for CRTx and LIBC files
-  print 'Configure %s for %s.\n' % (project, arch)
-  srcpath = os.path.join(TOOLCHAIN_BUILD_SRC, project)
-  dstpath = ReplaceArch(os.path.join(workpath, '$NACL-nacl', project), arch)
-  libpath = ReplaceArch(os.path.join(inspath, '$NACL-nacl', 'lib'), arch)
-  CreateProject(arch, srcpath, dstpath, libpath)
-  print 'Building %s for %s at %s.' % (project, arch, dstpath)
 
-  args = ['make', '-j12', 'V=1']
-  if target:
-    args.append(target)
-  if process.Run(args, cwd=dstpath, outfile=sys.stdout):
+def MakeBionicProject(project, targets=[], clobber=False):
+  arch = 'arm'
+  paths = GetProjectPaths(arch, project)
+  workpath = paths['work']
+  inspath = paths['ins']
+  targetlist = ' '.join(targets)
+
+  print 'Building %s for %s at %s %s.' % (project, arch, workpath, targetlist)
+  if clobber:
+    args = ['make', '-j12', 'V=1', 'clean']
+    if process.Run(args, cwd=workpath, outfile=sys.stdout):
+      raise RuntimeError('Failed to clean %s for %s.\n' % (project, arch))
+
+  args = ['make', '-j12', 'V=1'] + targets
+  if process.Run(args, cwd=workpath, outfile=sys.stdout):
     raise RuntimeError('Failed to build %s for %s.\n' % (project, arch))
-  if tcpath:
-    UpdateFromTo(inspath, tcpath)
-  print 'Done with %s for %s.\n' % (project, arch)
-
-
-def ConfigureAndBuildGCC(clobber=False):
-  ConfigureAndBuildArmGCC(clobber)
-
-
-def ConfigureAndBuildCXX(clobber=False):
-  ConfigureAndBuildArmCXX(clobber)
 
+  print 'Done with %s for %s.\n' % (project, arch)
 
-def ConfigureAndBuildTests(clobber=False):
-  for arch in ARCHES:
-    workpath = os.path.join(TOOLCHAIN_BUILD_OUT,
-                            ReplaceArch('bionic_$GCC_test_work', arch))
-    inspath = os.path.join(TOOLCHAIN_BUILD_OUT,
-                           ReplaceArch('bionic_$GCC_test_install', arch))
-    if clobber:
-      print 'Clobbering'
-      Rmdir(workpath)
-      Rmdir(inspath)
-    Mkdir(workpath)
-    Mkdir(inspath)
-    ConfigureAndBuild(arch, 'bionic/tests', workpath, inspath)
 
+def ArchiveAndUpload(version, zipname, zippath, packages_file):
+  sys.stdout.flush()
+  print >>sys.stderr, '@@@BUILD_STEP archive_and_upload@@@'
 
-def ArchiveAndUpload(version, zipname, zippath):
-  if 'BUILDBOT_BUILDERNAME' in os.environ:
-    GSUTIL = '../buildbot/gsutil.sh'
-  else:
-    GSUTIL = 'gsutil'
-  GSUTIL_ARGS = [GSUTIL, 'cp', '-a', 'public-read']
-  GSUTIL_PATH = 'gs://nativeclient-archive2/toolchain'
+  bucket_path = 'nativeclient-archive2/toolchain/%s' % version
+  gsd_store = pynacl.gsd_storage.GSDStorage(bucket_path, [bucket_path])
 
-  urldir = os.path.join(GSUTIL_PATH, version)
-  zipurl = os.path.join(urldir, zipname)
   zipname = os.path.join(TOOLCHAIN_BUILD_OUT, zipname)
-
   try:
     os.remove(zipname)
   except:
     pass
 
-  sys.stdout.flush()
-  print >>sys.stderr, '@@@STEP_LINK@download@%s@@@' % urldir
-
+  # Archive the zippath to the zipname.
   if process.Run(['tar', '-czf', zipname, zippath],
-                 cwd=TOOLCHAIN,
+                 cwd=TOOLCHAIN_BUILD_OUT,
                  outfile=sys.stdout):
       raise RuntimeError('Failed to zip %s from %s.\n' % (zipname, zippath))
 
+  # Create Zip Hash file using the hash of the zip file.
   hashzipname = zipname + '.sha1hash'
-  hashzipurl = zipurl + '.sha1hash'
-  hashval = hashing_tools.HashFileContents(zipname)
-
+  hashval = pynacl.hashing_tools.HashFileContents(zipname)
   with open(hashzipname, 'w') as f:
     f.write(hashval)
 
-  if process.Run(GSUTIL_ARGS + [zipname, zipurl],
-                 cwd=TOOLCHAIN_BUILD,
-                 outfile=sys.stdout):
-    err = 'Failed to upload zip %s to %s.\n' % (zipname, zipurl)
-    raise RuntimeError(err)
+  # Upload the Zip file.
+  zipurl = gsd_store.PutFile(zipname, os.path.basename(zipname))
+  sys.stdout.flush()
+  print >>sys.stderr, ('@@@STEP_LINK@download (%s)@%s@@@' %
+                       (os.path.basename(zipname), zipurl))
 
-  if process.Run(GSUTIL_ARGS + [hashzipname, hashzipurl],
-                 cwd=TOOLCHAIN_BUILD,
-                 outfile=sys.stdout):
-    err = 'Failed to upload hash %s to %s.\n' % (hashzipname, hashzipurl)
-    raise RuntimeError(err)
+  # Upload the Zip Hash file.
+  hashurl = gsd_store.PutFile(hashzipname, os.path.basename(hashzipname))
+  sys.stdout.flush()
+  print >>sys.stderr, ('@@@STEP_LINK@download (%s)@%s@@@' %
+                       (os.path.basename(hashzipname), hashurl))
+
+  # Create a package info file for the nacl_arm_bionic package.
+  archive_desc = archive_info.ArchiveInfo(name=os.path.basename(zipname),
+                                          archive_hash=hashval,
+                                          tar_src_dir='linux_arm_bionic',
+                                          url=zipurl)
+  package_desc = package_info.PackageInfo()
+  package_desc.AppendArchive(archive_desc)
+
+  os_name = pynacl.platform.GetOS()
+  arch_name = pynacl.platform.GetArch()
+  package_info_file = os.path.join(TOOLCHAIN_BUILD_OUT,
+                                   'packages',
+                                   '%s_%s' % (os_name, arch_name),
+                                   'nacl_arm_bionic.json')
+  package_desc.SavePackageFile(package_info_file)
+
+  # If packages_file is specified, write out our packages file of 1 package.
+  if packages_file:
+    with open(packages_file, 'wt') as f:
+      f.write(package_info_file)
 
 
 def main(argv):
-  parser = optparse.OptionParser()
-  parser.add_option(
+  parser = argparse.ArgumentParser(add_help=False)
+  parser.add_argument(
       '-v', '--verbose', dest='verbose',
       default=False, action='store_true',
       help='Produce more output.')
-  parser.add_option(
+
+  parser.add_argument(
       '-c', '--clobber', dest='clobber',
       default=False, action='store_true',
       help='Clobber working directories before building.')
-  parser.add_option(
+
+  parser.add_argument(
+      '-f', '--fast-clobber', dest='fast_clobber',
+      default=False, action='store_true',
+      help='Clobber bionic working directories before building.')
+
+  parser.add_argument(
       '-s', '--sync', dest='sync',
       default=False, action='store_true',
       help='Sync sources first.')
 
-  parser.add_option(
+  parser.add_argument(
       '-b', '--buildbot', dest='buildbot',
       default=False, action='store_true',
       help='Running on the buildbot.')
 
-  parser.add_option(
-      '-e', '--empty', dest='empty',
+  parser.add_argument(
+      '-l', '--llvm', dest='llvm',
       default=False, action='store_true',
-      help='Only create empty toolchain')
+      help='Enable building via llvm.')
 
-  parser.add_option(
+  parser.add_argument(
       '-u', '--upload', dest='upload',
       default=False, action='store_true',
       help='Upload build artifacts.')
 
-  parser.add_option(
+  parser.add_argument(
+        '--packages-file', dest='packages_file',
+        default=None,
+        help='Output packages file describing list of package files built.')
+
+  parser.add_argument(
       '--skip-gcc', dest='skip_gcc',
       default=False, action='store_true',
       help='Skip building GCC components.')
 
-  options, args = parser.parse_args(argv)
+  options, leftover_args = parser.parse_known_args()
+  if '-h' in leftover_args or '--help' in leftover_args:
+    print 'The following arguments are specific to toolchain_build_bionic.py:'
+    parser.print_help()
+    print 'The rest of the arguments are generic, in toolchain_main.py'
+    return 1
+
+  if options.llvm:
+    ARCHES.append('pnacl')
+
   if options.buildbot or options.upload:
     version = os.environ['BUILDBOT_REVISION']
 
-  if options.clobber or options.empty:
-    Clobber()
+  if options.clobber or options.fast_clobber:
+    Clobber(fast=options.fast_clobber)
 
   if options.sync or options.buildbot:
     FetchBionicSources()
 
+  # Copy headers and compiler tools
   CreateBasicToolchain()
-  if not options.empty and not options.skip_gcc:
-    FetchAndBuildGCC()
-    ConfigureAndBuildGCC(options.clobber)
-    ConfigureAndBuildCXX(options.clobber)
 
-  ConfigureAndBuildBionic()
+  # Configure Bionic Projects, libc, libm, linker, tests, ...
+  ConfigureBionicProjects(clobber=options.buildbot)
+
+  # Build and install IRT header before building GCC
+  MakeBionicProject('libc', ['irt'])
+
+  if not options.skip_gcc:
+    # Build newlib gcc_libs for use by bionic
+    FetchAndBuild_gcc_libs()
+
+  # Configure and build libgcc.a
+  ConfigureAndBuild_libgcc(skip_build=options.skip_gcc)
+
+  # With libgcc.a, we can now build libc.so
+  MakeBionicProject('libc')
+
+  # With libc.so, we can build libgcc_s.so
+  BuildAndInstall_libgcc_s(skip_build=options.skip_gcc)
+
+  # With libc and libgcc_s, we can now build libm
+  MakeBionicProject('libm')
+
+  # With libc, libgcc, and libm, we can now build libstdc++
+  ConfigureAndBuild_libstdcpp()
+
+  # Now we can build the linker
+  #MakeBionicProject('linker')
+  MakeBionicProject('newlinker')
+
+  # Now we have a full toolchain, so test it
+  #MakeBionicProject('tests')
+  MakeBionicProject('newtests')
 
-  # Can not test on buildot until sel_ldr, irt, etc.. are built
+  # We can run only off buildbots
   if not options.buildbot:
-    ConfigureAndBuildTests(clobber=False)
+    process.Run(['./scons', 'platform=arm', '--mode=nacl,dbg-linux', '-j20'],
+                cwd=NATIVE_CLIENT)
+    MakeBionicProject('tests', ['run'])
+    MakeBionicProject('newtests', ['run'])
+
+  dst = os.path.join(TOOLCHAIN_BUILD_OUT, 'linux_arm_bionic', 'log.txt')
+  with open(dst, 'w') as dstf:
+    process.Run(['git', 'log', '-n', '1'],
+                cwd=os.path.join(TOOLCHAIN_BUILD_SRC, 'bionic'),
+                outfile=dstf,
+                verbose=False)
 
   if options.buildbot or options.upload:
     zipname = 'naclsdk_linux_arm_bionic.tgz'
-    ArchiveAndUpload(version, zipname, 'linux_x86_bionic')
+    ArchiveAndUpload(version, zipname, 'linux_arm_bionic',
+                     options.packages_file)
 
 
 if __name__ == '__main__':