| #!/usr/bin/python |
| # Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Native Client SDK with Bionic |
| """ |
| |
| import argparse |
| import fnmatch |
| import os |
| import stat |
| import shutil |
| import StringIO |
| import sys |
| |
| sys.path.append('tools') |
| |
| import process |
| from bionic_dirs import * |
| from cmake_tools import ConfigureCMake |
| from file_update import Mkdir, Rmdir, Symlink |
| from file_update import NeedsUpdate, UpdateFromTo, UpdateText |
| from make_tools import ConfigureProject, ConfigureThirdParty, MakeProject |
| from replace import ReplaceArch, ReplaceText, ReplaceList |
| |
| DEFAULT_CPU_TYPES = ['arm', 'x86_64'] |
| DEFAULT_ARCH_TYPES = ['arm', 'i686', 'x86_64'] |
| |
| def BuildPNaCl(options): |
| tc_args = ['python', 'toolchain_build_pnacl.py', |
| '--install', os.path.join(OUTPUT_ROOT, 'bionic_work')] |
| |
| #if options.no_cache: |
| tc_args += ['--no-use-cached-results', '--no-use-remote-cache'] |
| |
| print 'Building PNaCl: ' + ' '.join(tc_args) |
| process.Run(tc_args, cwd=TOOLCHAIN_BUILD_DIR, outfile=sys.stdout) |
| |
| |
| def BuildSCons(options): |
| scons_args = ['./scons', '--mode=nacl,dbg-linux', '-j20'] |
| for arch in ['arm', 'x86_64', 'x86_32']: |
| platform = 'platform=' + arch |
| irt = 'scons-out/nacl_irt-%s/staging/irt_core.nexe' % arch.replace('_', '-') |
| bootstrap = 'nacl_helper_bootstrap' |
| print 'Building SCons: ' + arch |
| process.Run(scons_args + [platform, 'sel_ldr', irt, bootstrap], |
| cwd=NATIVE_CLIENT_DIR, outfile=sys.stdout) |
| |
| |
| def UpdateSCons(options): |
| print 'Updating SCons components.' |
| for arch in ['arm', 'i686', 'x86_64']: |
| scons_path = os.path.join(NATIVE_CLIENT_DIR, 'scons-out', 'dbg-linux-$SCON', |
| 'staging') |
| scons_path = ReplaceArch(scons_path, arch) |
| |
| for exe in ['nacl_helper_bootstrap', 'sel_ldr']: |
| src = os.path.join(scons_path, exe) |
| dst = os.path.join(OUTPUT_ROOT, 'tools', arch, exe) |
| UpdateFromTo(src,dst) |
| |
| src = os.path.join(NATIVE_CLIENT_DIR, 'scons-out', 'nacl_irt-$SCON', |
| 'staging', 'irt_core.nexe') |
| src = ReplaceArch(src, arch) |
| dst = os.path.join(OUTPUT_ROOT, 'tools', arch, 'irt_core.nexe') |
| UpdateFromTo(src, dst) |
| |
| |
| def ReplaceArmTool(tool): |
| EXEC= '#!/bin/sh\nexec `dirname $0`/' + tool |
| EXEC+=' --target=armv7a-none-nacl-gnueabihf"$@"' |
| dst = os.path.join(OUTPUT_ROOT, 'bionic_install', 'bin', 'arm-nacl-' + tool) |
| with open(dst, 'w') as dstf: |
| dstf.write(EXEC) |
| mod = stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH |
| os.chmod(dst, mod) |
| |
| # Shared = *.xsc |
| # Dynamic = *.xs --Ttext-sections=0x100000 |
| # Static = *.xs |
| def UpdateBionicToolchain(arches): |
| print 'Updating Bionic Toolchain.' |
| COPY_FULL = [ |
| 'arm_bc-nacl', 'bin', 'docs', |
| 'i686_bc-nacl', 'include', 'le32-nacl', |
| 'share', 'target_lib_compiler', |
| 'translator', 'x86_64_bc-nacl', |
| 'FEATURE_VERSION', 'README', 'REV', |
| 'lib', |
| 'arm-nacl/bin', |
| 'arm-nacl/lib/ldscripts', |
| 'arm-nacl/include/c++', |
| 'x86_64-nacl/bin', |
| 'x86_64-nacl/lib/ldscripts', |
| 'x86_64-nacl/include/c++', |
| ] |
| BOGUS = [ |
| 'lib/clang/3.4/include', |
| 'lib/clang/3.4/lib/arm_bc-nacl', |
| 'lib/clang/3.4/lib/i686_bc-nacl', |
| 'lib/clang/3.4/lib/le32-nacl', |
| 'lib/clang/3.4/lib/x86_64-nacl', |
| ] |
| |
| srcpath = os.path.join(OUTPUT_ROOT, 'bionic_work') |
| dstpath = os.path.join(OUTPUT_ROOT, 'bionic_install') |
| for dirpath in COPY_FULL: |
| UpdateFromTo(os.path.join(srcpath, dirpath), os.path.join(dstpath, dirpath)) |
| |
| EMPTY = """/* |
| * This is a dummy linker script. |
| * libnacl.a, libcrt_common.a, crt0.o crt1.o crti.o and crtn.o are all |
| * empty. Instead all the work is done by crtbegin(S).o and crtend(S).o and |
| * the bionic libc. These are provided for compatability with the newlib |
| * toolchain binaries. |
| */""" |
| EMPTY_FILES = ['crt0.o', 'crt1.o', 'crti.o', 'crtn.o', |
| 'libnacl.a', 'libcrt_common.a', 'libpthread.a'] |
| |
| for arch in arches: |
| # Create empty objects and libraries |
| libpath = ReplaceArch(os.path.join(dstpath, '$LIB'), arch) |
| for name in EMPTY_FILES: |
| UpdateText(os.path.join(libpath, name), EMPTY) |
| |
| # Copy Assembly Macro Files |
| src = os.path.join(NATIVE_CLIENT_DIR, 'pnacl', 'support', 'clang_direct', |
| 'nacl-arm-macros.s') |
| dst = os.path.join(OUTPUT_ROOT, 'bionic_install', 'arm-nacl', 'lib', |
| 'nacl-arm-macros.s') |
| UpdateFromTo(src, dst) |
| |
| |
| def MungeIRT(src, dst): |
| replace_map = { |
| 'off_t': 'int64_t', |
| 'native_client/src/untrusted/irt/' : '', |
| } |
| |
| if not NeedsUpdate(src,dst): |
| return |
| |
| print 'Munging IRT %s -> %s.' % (src,dst) |
| with open(src, 'r') as srcf: |
| text = srcf.read() |
| text = ReplaceText(text, [replace_map]) |
| with open(dst, 'w') as dstf: |
| dstf.write(text) |
| |
| |
| def UpdateBionicHeaders(cpus): |
| BIONIC_PAIRS = [ |
| ('libc/arch-nacl/syscalls/irt_poll.h', '$INC/irt_poll.h'), |
| ('libc/arch-nacl/syscalls/irt_socket.h', '$INC/irt_socket.h'), |
| ('libc/include', '$INC'), |
| ('libc/arch-nacl/syscalls/nacl_socket.h', '$INC/nacl_socket.h'), |
| ('libc/arch-nacl/syscalls/nacl_stat.h', '$INC/nacl_stat.h'), |
| ('libc/arch-pnacl/include/machine', |
| '$INC/machine'), |
| ('libc/arch-$MACH/include/machine', |
| '$INC/machine'), |
| ('libc/kernel/common', '$INC'), |
| ('libc/kernel/arch-$CPU/asm', '$INC/asm'), |
| # Math Includes |
| ('libm/include', '$INC'), |
| ('libm/$MATH', '$INC'), |
| # Misc |
| ('safe-iop/include', '$INC'), |
| ('nacl/$INC', '$INC'), |
| ] |
| GCC_PAIRS = [ |
| # ('ucontext.h', '$INC/ucontext.h'), |
| # ('sys/ucontext.h', '$INC/sys/ucontext.h'), |
| # ('bits/sigcontext.h', '$INC/bits/sigcontext.h'), |
| # ('bits/wordsize.h', '$INC/bits/wordsize.h') |
| ] |
| for arch in cpus: |
| install_path = os.path.join(OUTPUT_ROOT, 'bionic_install') |
| |
| Mkdir(install_path) |
| for src, dst in BIONIC_PAIRS: |
| srcpath = ReplaceArch(os.path.join(BIONIC_SRC, src), arch) |
| dstpath = ReplaceArch(os.path.join(install_path, dst), arch) |
| UpdateFromTo(srcpath, dstpath, filters=['*.S', '*.inc']) |
| |
| for name in ['irt.h', 'irt_dev.h']: |
| src = os.path.join(NATIVE_CLIENT_DIR, 'src', 'untrusted', 'irt', name) |
| dst = os.path.join(install_path, '$INC') |
| dst = ReplaceArch(dst, arch) |
| MungeIRT(src, os.path.join(dst, name)) |
| |
| for src, dst in GCC_PAIRS: |
| srcpath = ReplaceArch(os.path.join(TOOLCHAIN_DIR, 'linux_$CPU', |
| 'nacl_$CPU_glibc', '$NACL', |
| 'include', src), arch) |
| dstpath = ReplaceArch(os.path.join(install_path, dst), arch) |
| UpdateFromTo(srcpath, dstpath) |
| |
| |
| def main(argv): |
| parser = argparse.ArgumentParser(add_help=False) |
| parser.add_argument( |
| '-v', '--verbose', dest='verbose', |
| default=False, action='store_true', |
| help='Produce more output.') |
| |
| parser.add_argument( |
| '-a', '--arch', dest='arches', |
| default=[], action='append', |
| help='Add arch to buildset (non means build all).') |
| |
| parser.add_argument( |
| '-b', '--rebuild-bionic', dest='rebuild_bionic', |
| default=False, action='store_true', |
| help='Produce more output.') |
| |
| parser.add_argument( |
| '-c', '--clobber', dest='clobber', |
| default=False, action='store_true', |
| help='Clobber working directories before building.') |
| |
| parser.add_argument( |
| '-p', '--rebuild-pnacl', dest='rebuild_pnacl', |
| default=False, action='store_true', |
| help='Rebuild pnacl step.') |
| |
| parser.add_argument( |
| '-s', '--rebuild-scons', dest='rebuild_scons', |
| default=False, action='store_true', |
| help='Rebuild sel_ldr, irt, and bootstrap.') |
| |
| parser.add_argument( |
| '-t', '--clobber-toolchain', dest='clobber_toolchain', |
| default=False, action='store_true', |
| help='Clobber toolchain directory.') |
| |
| parser.add_argument( |
| '--update-only', dest='update_only', |
| default=False, action='store_true', |
| help='Only update files.') |
| |
| options, leftover_args = parser.parse_known_args(argv) |
| if '-h' in leftover_args or '--help' in leftover_args: |
| parser.print_help() |
| return 1 |
| |
| if not options.arches: |
| options.arches = DEFAULT_ARCH_TYPES |
| |
| for arch in options.arches: |
| if arch not in DEFAULT_ARCH_TYPES: |
| print 'ARCH %s unrecognized.' % arch |
| print 'Expecting: ' + ' '.join(DEFAULT_ARCH_TYPES) |
| return 1 |
| |
| if options.clobber: |
| print 'Re-prep this checkout.' |
| process.Run(['python', 'prep.py', '-c']) |
| |
| # No need to rebuild after we already built during prep |
| options.rebuild_pnacl = False |
| options.rebuild_scons = False |
| |
| if options.rebuild_pnacl: |
| BuildPNaCl(options) |
| |
| if options.rebuild_scons: |
| BuildSCons(options) |
| UpdateSCons(options) |
| |
| if options.clobber_toolchain: |
| Rmdir(os.path.join(OUTPUT_ROOT, 'bionic_install')) |
| |
| UpdateBionicToolchain(options.arches) |
| UpdateBionicHeaders(DEFAULT_CPU_TYPES) |
| |
| if options.update_only: |
| return 0 |
| |
| for arch in options.arches: |
| ConfigureProject(arch, 'irt', options.rebuild_bionic) |
| ConfigureProject(arch, 'libc', options.rebuild_bionic) |
| ConfigureProject(arch, 'libgcc_eh', options.rebuild_bionic) |
| ConfigureProject(arch, 'libm', options.rebuild_bionic) |
| ConfigureProject(arch, 'linker', options.rebuild_bionic) |
| ConfigureProject(arch, 'tests', options.rebuild_bionic) |
| |
| for arch in options.arches: |
| MakeProject(arch, 'irt', jobs=1) |
| MakeProject(arch, 'libc') |
| MakeProject(arch, 'libgcc_eh') |
| MakeProject(arch, 'libm') |
| MakeProject(arch, 'linker') |
| |
| host = arch + '-nacl' |
| libunwind_args = ['--enable-setjmp', '--disable-cxx-exceptions', |
| '--enable-static', '--enable-shared', |
| '--disable-coredump', '--disable-ptrace', |
| '--disable-debug', |
| '--disable-debug-frame', '--disable-block-signales', |
| '--disable-conservative-checks', '--disable-msabi-support', |
| '--disable-minidebuginfo', |
| 'ac_cv_func_dl_iterate_phdr=yes', |
| '--host=' + host, '--target=' + host, '--build=i686'] |
| # ConfigureThirdParty(arch, 'libunwind', libunwind_args) |
| # MakeProject(arch, 'libunwind') |
| |
| |
| for arch in options.arches: |
| MakeProject(arch, 'tests') |
| MakeProject(arch, 'tests', ['static_tests']) |
| MakeProject(arch, 'tests', ['dynamic_tests']) |
| # MakeProject(arch, 'libunwind', ['src/.libs/libunwind.a']) |
| |
| return 0 |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv)) |
| |