blob: 4f34aa5d832a58109d766a1af65c196603ce2670 [file] [log] [blame]
#!/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))