| #!/usr/bin/python |
| # Copyright (c) 2013 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. |
| |
| """Recipes for PNaCl target libs.""" |
| |
| import fnmatch |
| import os |
| import sys |
| |
| sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
| import pynacl.gsd_storage |
| import pynacl.platform |
| |
| import command |
| import pnacl_commands |
| |
| SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| NACL_DIR = os.path.dirname(SCRIPT_DIR) |
| |
| CLANG_VER = '3.7.0' |
| |
| def ToolName(name): |
| return 'pnacl-' + name |
| |
| # Return the path to a tool to build target libraries |
| # msys should be false if the path will be called directly rather than passed to |
| # an msys or cygwin tool such as sh or make. |
| def PnaclTool(toolname, arch='le32', msys=True): |
| if not msys and pynacl.platform.IsWindows(): |
| ext = '.bat' |
| else: |
| ext = '' |
| if toolname in ['llvm-mc']: |
| # Some tools, like llvm-mc, don't need or have a special pnacl- prefix |
| # binary. |
| base = toolname |
| elif IsBCArch(arch): |
| base = ToolName(toolname) |
| else: |
| base = '-'.join([TargetArch(arch), 'nacl', toolname]) |
| return command.path.join('%(abs_target_lib_compiler)s', |
| 'bin', base + ext) |
| |
| # PNaCl tools for newlib's environment, e.g. CC_FOR_TARGET=/path/to/pnacl-clang |
| TOOL_ENV_NAMES = { 'CC': 'clang', 'CXX': 'clang++', 'AR': 'ar', 'NM': 'nm', |
| 'RANLIB': 'ranlib', 'READELF': 'readelf', 'AS': 'as' } |
| |
| def TargetTools(arch): |
| return [ tool + '_FOR_TARGET=' + PnaclTool(name, arch=arch, msys=True) |
| for tool, name in TOOL_ENV_NAMES.iteritems() ] |
| |
| |
| def MakeCommand(): |
| make_command = ['make'] |
| if not pynacl.platform.IsWindows(): |
| # The make that ships with msys sometimes hangs when run with -j. |
| # The ming32-make that comes with the compiler itself reportedly doesn't |
| # have this problem, but it has issues with pathnames with LLVM's build. |
| make_command.append('-j%(cores)s') |
| return make_command |
| |
| # Return the component name to use for a component name with |
| # a host triple. GNU configuration triples contain dashes, which are converted |
| # to underscores so the names are legal for Google Storage. |
| def GSDJoin(*args): |
| return '_'.join([pynacl.gsd_storage.LegalizeName(arg) for arg in args]) |
| |
| |
| def TripleFromArch(bias_arch): |
| return bias_arch + '-nacl' |
| |
| |
| def IsBiasedBCArch(arch): |
| return arch.endswith('_bc') |
| |
| |
| def IsBCArch(arch): |
| return IsBiasedBCArch(arch) or arch == 'le32' |
| |
| |
| def IsNonSFIArch(arch): |
| return arch.endswith('-nonsfi') |
| |
| |
| # Return the target arch recognized by the compiler (e.g. i686) from an arch |
| # string which might be a biased-bitcode-style arch (e.g. i686_bc) |
| def TargetArch(bias_arch): |
| if IsBiasedBCArch(bias_arch): |
| return bias_arch[:bias_arch.index('_bc')] |
| return bias_arch |
| |
| |
| def MultilibArch(bias_arch): |
| return 'x86_64' if bias_arch == 'i686' else bias_arch |
| |
| |
| def MultilibLibDir(bias_arch): |
| suffix = '32' if bias_arch == 'i686' else '' |
| return os.path.join(TripleFromArch(MultilibArch(bias_arch)), 'lib' + suffix) |
| |
| |
| def BiasedBitcodeTargetFlag(bias_arch): |
| arch = TargetArch(bias_arch) |
| flagmap = { |
| # Arch Target Extra flags. |
| 'x86_64': ('x86_64-unknown-nacl', []), |
| 'i686': ('i686-unknown-nacl', []), |
| 'arm': ('armv7-unknown-nacl-gnueabihf', ['-mfloat-abi=hard']), |
| 'mipsel': ('mipsel-unknown-nacl', []), |
| } |
| # The -emit-llvm flag is only needed for native Clang drivers since |
| # pnacl-clang already passes that option to every Clang invocation. |
| # TODO(phosek): Refactor the per-toolchain options into a separate class. |
| return ['--target=%s' % flagmap[arch][0], '-emit-llvm'] + flagmap[arch][1] |
| |
| |
| def TranslatorArchToBiasArch(arch): |
| archmap = {'x86-32': 'i686', |
| 'x86-32-nonsfi': 'i686', |
| 'x86-64': 'x86_64', |
| 'arm': 'arm', |
| 'arm-nonsfi': 'arm', |
| 'mips32': 'mipsel'} |
| return archmap[arch] |
| |
| def TargetLibCflags(bias_arch): |
| flags = '-g -O2' |
| if IsBCArch(bias_arch): |
| flags += ' -mllvm -inline-threshold=5' |
| else: |
| # Use sections for the library builds to allow better GC for the IRT. |
| flags += ' -ffunction-sections -fdata-sections' |
| if bias_arch != 'arm': |
| # Newlib target libs need to be build with the LLVM assembler on x86-64 |
| # because it uses the sandbox base address-hiding form of calls, which |
| # we need in the IRT. On x86-32 that doesn't matter but the LLVM assembler |
| # sometimes generates slightly better code and it's good to be consistent. |
| flags += ' -integrated-as' |
| if IsBiasedBCArch(bias_arch): |
| flags += ' ' + ' '.join(BiasedBitcodeTargetFlag(bias_arch)) |
| return flags |
| |
| |
| def NewlibIsystemCflags(bias_arch): |
| include_arch = MultilibArch(bias_arch) |
| return ' '.join([ |
| '-isystem', |
| command.path.join('%(' + GSDJoin('abs_newlib', include_arch) +')s', |
| TripleFromArch(include_arch), 'include')]) |
| |
| |
| def LibCxxCflags(bias_arch): |
| # HAS_THREAD_LOCAL is used by libc++abi's exception storage, the fallback is |
| # pthread otherwise. |
| return ' '.join([TargetLibCflags(bias_arch), NewlibIsystemCflags(bias_arch), |
| '-fexceptions', '-DHAS_THREAD_LOCAL=1', |
| '-D__ARM_DWARF_EH__']) |
| |
| |
| def NativeTargetFlag(bias_arch): |
| arch = TargetArch(bias_arch) |
| flagmap = { |
| # Arch Target Extra flags. |
| 'x86_64': ('x86_64-linux-gnu', []), |
| 'i686': ('i686-linux-gnu', []), |
| 'arm': ('armv7a-linux-gnueabihf', []), |
| 'mipsel': ('mipsel-linux-gnu', []), |
| } |
| return ['--target=%s' % flagmap[arch][0]] + flagmap[arch][1] |
| |
| |
| def NonSFITargetLibCflags(bias_arch): |
| flags = '-D__native_client_nonsfi__ -fPIC -nostdinc ' |
| flags += ' '.join([ |
| '-isystem', |
| command.path.join('%(abs_target_lib_compiler)s', |
| 'lib', 'clang', CLANG_VER, 'include')]) |
| if bias_arch == 'i686': |
| flags += ' -malign-double -mllvm -mtls-use-call' |
| flags += ' ' + ' '.join(NativeTargetFlag(bias_arch)) |
| return flags |
| |
| |
| # Build a single object file for the target. |
| def BuildTargetObjectCmd(source, output, bias_arch, output_dir='%(cwd)s', |
| extra_flags=[]): |
| flags = ['-Wall', '-Werror', '-O2', '-c'] + extra_flags |
| if IsBiasedBCArch(bias_arch): |
| flags.extend(BiasedBitcodeTargetFlag(bias_arch)) |
| flags.extend(NewlibIsystemCflags(bias_arch).split()) |
| return command.Command( |
| [PnaclTool('clang', arch=bias_arch, msys=False)] + flags + [ |
| command.path.join('%(src)s', source), |
| '-o', command.path.join(output_dir, output)]) |
| |
| |
| # Build a single object file as native code for the translator. |
| def BuildTargetTranslatorCmd(sourcefile, output, arch, extra_flags=[], |
| source_dir='%(src)s', output_dir='%(cwd)s'): |
| bias_arch = TranslatorArchToBiasArch(arch) |
| flags = ['-Wall', '-Werror', '-O3', '-integrated-as', '-c'] + extra_flags |
| if IsNonSFIArch(arch): |
| flags.extend(NonSFITargetLibCflags(bias_arch).split()) |
| return command.Command( |
| [PnaclTool('clang', arch=bias_arch, msys=False)] + flags + |
| # TODO(dschuff): this include breaks the input encapsulation for build |
| # rules. |
| ['-I%(top_srcdir)s/..'] + |
| NewlibIsystemCflags('le32').split() + |
| [command.path.join(source_dir, sourcefile), |
| '-o', command.path.join(output_dir, output)]) |
| |
| |
| def BuildLibgccEhCmd(sourcefile, output, arch, no_nacl_gcc): |
| # Return a command to compile a file from libgcc_eh (see comments in at the |
| # rule definition below). |
| flags_common = ['-DENABLE_RUNTIME_CHECKING', '-g', '-O2', '-W', '-Wall', |
| '-Wwrite-strings', '-Wcast-qual', '-Wstrict-prototypes', |
| '-Wmissing-prototypes', '-Wold-style-definition', |
| '-DIN_GCC', '-DCROSS_DIRECTORY_STRUCTURE', '-DIN_LIBGCC2', |
| '-D__GCC_FLOAT_NOT_NEEDED', '-Dinhibit_libc', |
| '-DHAVE_CC_TLS', '-DHIDE_EXPORTS', |
| '-fno-stack-protector', '-fexceptions', |
| '-fvisibility=hidden', |
| '-I.', '-I../.././gcc', '-I%(abs_gcc_src)s/gcc/libgcc', |
| '-I%(abs_gcc_src)s/gcc', '-I%(abs_gcc_src)s/include', |
| '-isystem', './include'] |
| # For x86 we use nacl-gcc to build libgcc_eh because of some issues with |
| # LLVM's handling of the gcc intrinsics used in the library. See |
| # https://code.google.com/p/nativeclient/issues/detail?id=1933 |
| # and http://llvm.org/bugs/show_bug.cgi?id=8541 |
| # For ARM, LLVM does work and we use it to avoid dealing with the fact that |
| # arm-nacl-gcc uses different libgcc support functions than PNaCl. |
| if arch in ('arm', 'mips32'): |
| cc = PnaclTool('clang', arch=TranslatorArchToBiasArch(arch), msys=False) |
| flags_naclcc = [] |
| else: |
| if no_nacl_gcc: |
| return command.WriteData('', output) |
| os_name = pynacl.platform.GetOS() |
| arch_name = pynacl.platform.GetArch() |
| platform_dir = '%s_%s' % (os_name, arch_name) |
| newlib_dir = 'nacl_x86_newlib_raw' |
| |
| nnacl_dir = os.path.join(NACL_DIR, 'toolchain', platform_dir, |
| newlib_dir, 'bin') |
| gcc_binaries = { |
| 'x86-32': 'i686-nacl-gcc', |
| 'x86-64': 'x86_64-nacl-gcc', |
| } |
| |
| cc = os.path.join(nnacl_dir, gcc_binaries[arch]) |
| flags_naclcc = [] |
| return command.Command([cc] + flags_naclcc + flags_common + |
| ['-c', |
| command.path.join('%(gcc_src)s', 'gcc', sourcefile), |
| '-o', output]) |
| |
| |
| |
| def TargetLibsSrc(GitSyncCmds): |
| newlib_sys_nacl = command.path.join('%(output)s', |
| 'newlib', 'libc', 'sys', 'nacl') |
| source = { |
| 'newlib_src': { |
| 'type': 'source', |
| 'output_dirname': 'pnacl-newlib', |
| 'commands': [ |
| # Clean any headers exported from the NaCl tree before syncing. |
| command.CleanGitWorkingDir( |
| '%(output)s', |
| reset=False, |
| path=os.path.join('newlib', 'libc', 'include'))] + |
| GitSyncCmds('nacl-newlib') + |
| # Remove newlib versions of headers that will be replaced by |
| # headers from the NaCl tree. |
| [command.RemoveDirectory(command.path.join(newlib_sys_nacl, |
| dirname)) |
| for dirname in ['bits', 'sys', 'machine']] + [ |
| command.Command([ |
| sys.executable, |
| command.path.join('%(top_srcdir)s', 'src', 'trusted', |
| 'service_runtime', 'export_header.py'), |
| command.path.join('%(top_srcdir)s', 'src', 'trusted', |
| 'service_runtime', 'include'), |
| newlib_sys_nacl], |
| cwd='%(abs_output)s', |
| )] + [ |
| command.Copy( |
| os.path.join('%(top_srcdir)s', 'src', 'untrusted', 'pthread', |
| header), |
| os.path.join('%(output)s', 'newlib', 'libc', 'include', |
| header)) |
| for header in ('pthread.h', 'semaphore.h') |
| ] |
| }, |
| 'compiler_rt_src': { |
| 'type': 'source', |
| 'output_dirname': 'compiler-rt', |
| 'commands': GitSyncCmds('compiler-rt'), |
| }, |
| 'gcc_src': { |
| 'type': 'source', |
| 'output_dirname': 'pnacl-gcc', |
| 'commands': GitSyncCmds('gcc'), |
| }, |
| } |
| return source |
| |
| |
| def NewlibLibcScript(arch, elfclass_x86_64='elf32'): |
| template = """/* |
| * This is a linker script that gets installed as libc.a for the |
| * newlib-based NaCl toolchain. It brings in the constituent |
| * libraries that make up what -lc means semantically. |
| */ |
| OUTPUT_FORMAT(%s) |
| GROUP ( libnacl.a libcrt_common.a ) |
| """ |
| if arch == 'arm': |
| # Listing three formats instead of one makes -EL/-EB switches work |
| # for the endian-switchable ARM backend. |
| format_list = ['elf32-littlearm-nacl', |
| 'elf32-bigarm-nacl', |
| 'elf32-littlearm-nacl'] |
| elif arch == 'i686': |
| format_list = ['elf32-i386-nacl'] |
| elif arch == 'x86_64': |
| format_list = ['%s-x86-64-nacl' % elfclass_x86_64] |
| elif arch == 'mipsel' : |
| format_list = ['elf32-tradlittlemips-nacl'] |
| else: |
| raise Exception('TODO(mcgrathr): OUTPUT_FORMAT for %s' % arch) |
| return template % ', '.join(['"' + fmt + '"' for fmt in format_list]) |
| |
| |
| def NewlibDirectoryCmds(bias_arch, newlib_triple): |
| commands = [] |
| def NewlibLib(name): |
| return os.path.join('%(output)s', newlib_triple, 'lib', name) |
| if not IsBCArch(bias_arch): |
| commands.extend([ |
| command.Rename(NewlibLib('libc.a'), NewlibLib('libcrt_common.a')), |
| command.WriteData(NewlibLibcScript(bias_arch, 'elf64'), |
| NewlibLib('libc.a'))]) |
| target_triple = TripleFromArch(bias_arch) |
| if bias_arch != 'i686': |
| commands.extend([ |
| # For biased bitcode builds, we configured newlib with target=le32-nacl |
| # to get its pure C implementation, so rename its output dir (which |
| # matches the target to the output dir for the package we are building) |
| command.Rename(os.path.join('%(output)s', newlib_triple), |
| os.path.join('%(output)s', target_triple)), |
| # Copy nacl_random.h, used by libc++. It uses the IRT, so should |
| # be safe to include in the toolchain. |
| command.Mkdir( |
| os.path.join('%(output)s', target_triple, 'include', 'nacl')), |
| command.Copy(os.path.join('%(top_srcdir)s', 'src', 'untrusted', |
| 'nacl', 'nacl_random.h'), |
| os.path.join('%(output)s', target_triple, 'include', |
| 'nacl', 'nacl_random.h')) |
| ]) |
| else: |
| # Use multilib-style directories for i686 |
| multilib_triple = TripleFromArch(MultilibArch(bias_arch)) |
| commands.extend([ |
| command.Rename(os.path.join('%(output)s', newlib_triple), |
| os.path.join('%(output)s', multilib_triple)), |
| command.RemoveDirectory( |
| os.path.join('%(output)s', multilib_triple, 'include')), |
| command.Rename( |
| os.path.join('%(output)s', multilib_triple, 'lib'), |
| os.path.join('%(output)s', multilib_triple, 'lib32')), |
| ]) |
| # Remove the 'share' directory from the biased builds; the data is |
| # duplicated exactly and takes up 2MB per package. |
| if bias_arch != 'le32': |
| commands.append(command.RemoveDirectory(os.path.join('%(output)s','share'))) |
| return commands |
| |
| |
| def LibcxxDirectoryCmds(bias_arch): |
| if bias_arch != 'i686': |
| return [] |
| lib_dir = os.path.join('%(output)s', MultilibLibDir(bias_arch)) |
| return [ |
| # Use the multlib-style lib dir and shared headers for i686 |
| command.Mkdir(os.path.dirname(lib_dir)), |
| command.Rename(os.path.join('%(output)s', 'i686-nacl', 'lib'), |
| lib_dir), |
| # The only thing left in i686-nacl is the headers |
| command.RemoveDirectory(os.path.join('%(output)s', 'i686-nacl')), |
| ] |
| |
| def D2NLibsSupportCommands(bias_arch, clang_libdir): |
| def TL(lib): |
| return GSDJoin(lib, pynacl.platform.GetArch3264(bias_arch)) |
| def TranslatorFile(lib, filename): |
| return os.path.join('%(' + TL(lib) + ')s', filename) |
| commands = [ |
| # Build compiler_rt which is now also used for the PNaCl |
| # translator. |
| command.Command(MakeCommand() + [ |
| '-C', '%(abs_compiler_rt_src)s', 'ProjObjRoot=%(cwd)s', |
| 'VERBOSE=1', |
| 'AR=' + PnaclTool('ar', arch=bias_arch), |
| 'RANLIB=' + PnaclTool('ranlib', arch=bias_arch), |
| 'CC=' + PnaclTool('clang', arch=bias_arch), 'clang_nacl', |
| 'EXTRA_CFLAGS=' + NewlibIsystemCflags(bias_arch)]), |
| command.Mkdir(clang_libdir, parents=True), |
| command.Copy(os.path.join( |
| 'clang_nacl', |
| 'full-' + bias_arch.replace('i686', 'i386') |
| .replace('mipsel', 'mips32'), |
| 'libcompiler_rt.a'), |
| os.path.join('%(output)s', clang_libdir, |
| 'libgcc.a')), |
| command.Copy( |
| TranslatorFile('libgcc_eh', 'libgcc_eh.a'), |
| os.path.join('%(output)s', clang_libdir, 'libgcc_eh.a')), |
| BuildTargetObjectCmd('clang_direct/crtbegin.c', 'crtbeginT.o', |
| bias_arch, output_dir=clang_libdir), |
| BuildTargetObjectCmd('crtend.c', 'crtend.o', |
| bias_arch, output_dir=clang_libdir), |
| ] |
| if bias_arch == "mipsel": |
| commands.extend([ |
| BuildTargetObjectCmd('bitcode/pnaclmm.c', 'pnaclmm.o', bias_arch), |
| BuildTargetObjectCmd('clang_direct/nacl-tp-offset.c', |
| 'nacl_tp_offset.o', bias_arch, |
| extra_flags=['-I%(top_srcdir)s/..']), |
| command.Command([PnaclTool('ar'), 'rc', |
| command.path.join(clang_libdir, 'libpnacl_legacy.a'), |
| command.path.join('pnaclmm.o'), |
| command.path.join('nacl_tp_offset.o')]) |
| ]) |
| return commands |
| |
| def TargetLibBuildType(is_canonical): |
| return 'build' if is_canonical else 'build_noncanonical' |
| |
| def TargetLibs(bias_arch, is_canonical): |
| def T(component_name): |
| return GSDJoin(component_name, bias_arch) |
| target_triple = TripleFromArch(bias_arch) |
| newlib_triple = target_triple if not IsBCArch(bias_arch) else 'le32-nacl' |
| newlib_cpp_flags = '' |
| if IsBCArch(bias_arch): |
| # This avoids putting the body of memcpy in libc for bitcode |
| newlib_cpp_flags = ' -DPNACL_BITCODE' |
| elif bias_arch == 'arm': |
| # This ensures that nacl gets the asm version of memcpy (gcc defines this |
| # macro for armv7a but clang does not) |
| newlib_cpp_flags = ' -D__ARM_FEATURE_UNALIGNED' |
| |
| clang_libdir = os.path.join( |
| '%(output)s', 'lib', 'clang', CLANG_VER, 'lib', target_triple) |
| libc_libdir = os.path.join('%(output)s', MultilibLibDir(bias_arch)) |
| libs = { |
| T('newlib'): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': [ 'newlib_src', 'target_lib_compiler'], |
| 'commands' : [ |
| command.SkipForIncrementalCommand( |
| ['sh', '%(newlib_src)s/configure'] + |
| TargetTools(bias_arch) + |
| ['CFLAGS_FOR_TARGET=' + |
| TargetLibCflags(bias_arch) + |
| newlib_cpp_flags, |
| '--prefix=', |
| '--disable-newlib-supplied-syscalls', |
| '--disable-texinfo', |
| '--disable-libgloss', |
| '--enable-newlib-iconv', |
| '--enable-newlib-iconv-from-encodings=' + |
| 'UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4', |
| '--enable-newlib-iconv-to-encodings=' + |
| 'UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4', |
| '--enable-newlib-io-long-long', |
| '--enable-newlib-io-long-double', |
| '--enable-newlib-io-c99-formats', |
| '--enable-newlib-mb', |
| '--target=' + newlib_triple |
| ]), |
| command.Command(MakeCommand()), |
| command.Command(['make', 'DESTDIR=%(abs_output)s', 'install']), |
| ] + NewlibDirectoryCmds(bias_arch, newlib_triple) |
| }, |
| T('libcxx'): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': ['libcxx_src', 'libcxxabi_src', 'llvm_src', 'gcc_src', |
| 'target_lib_compiler', T('newlib'), |
| GSDJoin('newlib', MultilibArch(bias_arch)), |
| T('libs_support')], |
| 'commands' : |
| [command.SkipForIncrementalCommand( |
| [pnacl_commands.PrebuiltCmake(), '-G', 'Unix Makefiles', |
| '-DCMAKE_C_COMPILER_WORKS=1', |
| '-DCMAKE_CXX_COMPILER_WORKS=1', |
| '-DCMAKE_INSTALL_PREFIX=', |
| '-DCMAKE_BUILD_TYPE=Release', |
| '-DCMAKE_C_COMPILER=' + PnaclTool('clang', bias_arch), |
| '-DCMAKE_CXX_COMPILER=' + PnaclTool('clang++', bias_arch), |
| '-DCMAKE_SYSTEM_NAME=nacl', |
| '-DCMAKE_AR=' + PnaclTool('ar', bias_arch), |
| '-DCMAKE_NM=' + PnaclTool('nm', bias_arch), |
| '-DCMAKE_RANLIB=' + PnaclTool('ranlib', bias_arch), |
| '-DCMAKE_LD=' + PnaclTool('illegal', bias_arch), |
| '-DCMAKE_AS=' + PnaclTool('as', bias_arch), |
| '-DCMAKE_OBJDUMP=' + PnaclTool('illegal', bias_arch), |
| '-DCMAKE_C_FLAGS=-std=gnu11 ' + LibCxxCflags(bias_arch), |
| '-DCMAKE_CXX_FLAGS=-std=gnu++11 ' + LibCxxCflags(bias_arch), |
| '-DLIT_EXECUTABLE=' + command.path.join( |
| '%(llvm_src)s', 'utils', 'lit', 'lit.py'), |
| # The lit flags are used by the libcxx testsuite, which is |
| # currenty driven by an external script. |
| '-DLLVM_LIT_ARGS=--verbose --param shell_prefix="' + |
| os.path.join(NACL_DIR,'run.py') +' -arch env --retries=1" '+ |
| '--param exe_suffix=".pexe" --param use_system_lib=true ' + |
| '--param cxx_under_test="' + os.path.join(NACL_DIR, |
| 'toolchain/linux_x86/pnacl_newlib', |
| 'bin/pnacl-clang++') + |
| '" '+ |
| '--param link_flags="-std=gnu++11 --pnacl-exceptions=sjlj"', |
| '-DLIBCXX_ENABLE_CXX0X=0', |
| '-DLIBCXX_ENABLE_SHARED=0', |
| '-DLIBCXX_CXX_ABI=libcxxabi', |
| '-DLIBCXX_LIBCXXABI_INCLUDE_PATHS=' + command.path.join( |
| '%(abs_libcxxabi_src)s', 'include'), |
| '%(libcxx_src)s']), |
| command.Copy(os.path.join('%(gcc_src)s', 'gcc', |
| 'unwind-generic.h'), |
| os.path.join('include', 'unwind.h')), |
| command.Command(MakeCommand() + ['VERBOSE=1']), |
| command.Command([ |
| 'make', |
| 'DESTDIR=' + os.path.join('%(abs_output)s', target_triple), |
| 'VERBOSE=1', |
| 'install']), |
| ] + LibcxxDirectoryCmds(bias_arch) |
| }, |
| } |
| if IsBCArch(bias_arch): |
| libs.update({ |
| T('compiler_rt_bc'): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': ['compiler_rt_src', 'target_lib_compiler'], |
| 'commands': [ |
| command.Mkdir(clang_libdir, parents=True), |
| command.Command(MakeCommand() + [ |
| '-f', |
| command.path.join('%(compiler_rt_src)s', 'lib', 'builtins', |
| 'Makefile-pnacl-bitcode'), |
| 'libgcc.a', 'CC=' + PnaclTool('clang'), |
| 'AR=' + PnaclTool('ar')] + |
| ['SRC_DIR=' + command.path.join('%(abs_compiler_rt_src)s', |
| 'lib', 'builtins'), |
| 'CFLAGS=' + ' '.join([ |
| '-DPNACL_' + TargetArch(bias_arch).replace('-', '_')]) |
| ]), |
| command.Copy('libgcc.a', os.path.join(clang_libdir, 'libgcc.a')), |
| ], |
| }, |
| T('libs_support'): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': [ T('newlib'), 'target_lib_compiler'], |
| 'inputs': { 'src': os.path.join(NACL_DIR, |
| 'pnacl', 'support', 'bitcode')}, |
| 'commands': [ |
| command.Mkdir(clang_libdir, parents=True), |
| command.Mkdir(libc_libdir, parents=True), |
| # Two versions of crt1.x exist, for different scenarios (with and |
| # without EH). See: |
| # https://code.google.com/p/nativeclient/issues/detail?id=3069 |
| command.Copy(command.path.join('%(src)s', 'crt1.x'), |
| command.path.join(libc_libdir, 'crt1.x')), |
| command.Copy(command.path.join('%(src)s', 'crt1_for_eh.x'), |
| command.path.join(libc_libdir, 'crt1_for_eh.x')), |
| # Install crti.bc (empty _init/_fini) |
| BuildTargetObjectCmd('crti.c', 'crti.bc', bias_arch, |
| output_dir=libc_libdir), |
| # Install crtbegin bitcode (__cxa_finalize for C++) |
| BuildTargetObjectCmd('crtbegin.c', 'crtbegin.bc', bias_arch, |
| output_dir=clang_libdir), |
| # Stubs for _Unwind_* functions when libgcc_eh is not included in |
| # the native link). |
| BuildTargetObjectCmd('unwind_stubs.c', 'unwind_stubs.bc', |
| bias_arch, output_dir=clang_libdir), |
| BuildTargetObjectCmd('sjlj_eh_redirect.cc', |
| 'sjlj_eh_redirect.bc', bias_arch, |
| output_dir=clang_libdir), |
| # libpnaclmm.a (__atomic_* library functions). |
| BuildTargetObjectCmd('pnaclmm.c', 'pnaclmm.bc', bias_arch), |
| command.Command([ |
| PnaclTool('ar'), 'rc', |
| command.path.join(clang_libdir, 'libpnaclmm.a'), |
| 'pnaclmm.bc']), |
| ] |
| } |
| }) |
| else: |
| # For now some of the D2N support libs currently come from our native |
| # translator libs (libgcc_eh). crti/crtn and crt1 |
| # come from libnacl, built by scons/gyp. TODO(dschuff): Do D2N libgcc_eh. |
| |
| # Translate from bias_arch's triple-style (i686) names to the translator's |
| # style (x86-32). We don't change the translator's naming scheme to avoid |
| # churning the in-browser translator. |
| def TL(lib): |
| return GSDJoin(lib, pynacl.platform.GetArch3264(bias_arch)) |
| libs.update({ |
| T('libs_support'): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': [ 'compiler_rt_src', |
| GSDJoin('newlib', MultilibArch(bias_arch)), |
| TL('libgcc_eh'), |
| 'target_lib_compiler'], |
| 'inputs': { 'src': os.path.join(NACL_DIR, 'pnacl', 'support'), |
| 'tls_params': os.path.join(NACL_DIR, 'src', 'untrusted', |
| 'nacl', 'tls_params.h')}, |
| 'commands': D2NLibsSupportCommands(bias_arch, clang_libdir), |
| } |
| }) |
| |
| return libs |
| |
| |
| def SubzeroRuntimeCommands(arch, out_dir): |
| """Returns a list of commands to build the Subzero runtime. |
| |
| When the commands are executed, temporary files are created in the current |
| directory, and .o files are created in the out_dir directory. If arch isn't |
| among a whitelist, an empty list of commands is returned. |
| """ |
| AsmSourceBase = None |
| # LlcArchArgs contains arguments extracted from pnacl-translate.py. |
| if arch == 'x86-32-linux': |
| Triple = 'i686-linux-gnu' |
| LlcArchArgs = [ '-mcpu=pentium4m'] |
| elif arch == 'x86-32': |
| Triple = 'i686-none-nacl-gnu' |
| LlcArchArgs = [ '-mcpu=pentium4m'] |
| elif arch == 'x86-32-nonsfi': |
| Triple = 'i686-linux-gnu' |
| LlcArchArgs = [ '-mcpu=pentium4m', '-relocation-model=pic', |
| '-force-tls-non-pic', '-malign-double'] |
| AsmSourceBase = 'szrt_asm_x8632' |
| elif arch == 'x86-64-linux': |
| Triple = 'x86_64-none-linux-gnux32' |
| LlcArchArgs = [ '-mcpu=x86-64'] |
| elif arch == 'x86-64': |
| Triple = 'x86_64-none-nacl' |
| LlcArchArgs = [ '-mcpu=x86-64'] |
| elif arch == 'arm-linux': |
| Triple = 'arm-linux-gnu' |
| LlcArchArgs = [ '-mcpu=cortex-a9', '-float-abi=hard', '-mattr=+neon'] |
| elif arch == 'arm': |
| Triple = 'armv7a-none-nacl' |
| LlcArchArgs = [ '-mcpu=cortex-a9', '-float-abi=hard', '-mattr=+neon'] |
| elif arch == 'arm-nonsfi': |
| Triple = 'armv7a-none-linux-gnueabihf' |
| LlcArchArgs = [ '-mcpu=cortex-a9', '-float-abi=hard', '-mattr=+neon', |
| '-relocation-model=pic', '-force-tls-non-pic', |
| '-malign-double'] |
| AsmSourceBase = 'szrt_asm_arm32' |
| else: |
| return [] |
| LlcArchArgs.append('-mtriple=' + Triple) |
| |
| return [ |
| command.Command([ |
| PnaclTool('clang'), '-O2', |
| '-c', command.path.join('%(subzero_src)s', 'runtime', 'szrt.c'), |
| '-o', 'szrt.tmp.bc']), |
| command.Command([ |
| PnaclTool('opt'), '-pnacl-abi-simplify-preopt', |
| '-pnacl-abi-simplify-postopt', '-pnaclabi-allow-debug-metadata', |
| 'szrt.tmp.bc', '-S', '-o', 'szrt.ll']), |
| command.Command([ |
| PnaclTool('llc'), '-externalize', '-function-sections', '-O2', |
| '-filetype=obj', '-bitcode-format=llvm', |
| '-o', os.path.join(out_dir, 'szrt.o'), |
| 'szrt.ll'] + |
| LlcArchArgs), |
| command.Command([ |
| PnaclTool('llc'), '-externalize', '-function-sections', '-O2', |
| '-filetype=obj', '-bitcode-format=llvm', |
| '-o', os.path.join(out_dir, 'szrt_ll.o'), |
| command.path.join('%(subzero_src)s', 'runtime', 'szrt_ll.ll')] + |
| LlcArchArgs), |
| ] + ([ |
| command.Command([ |
| PnaclTool('llvm-mc'), |
| '-filetype=obj', |
| '-triple=' + Triple, |
| '--defsym', 'NONSFI=1', |
| '-o', os.path.join(out_dir, AsmSourceBase + '.o'), |
| command.path.join('%(subzero_src)s', 'runtime', AsmSourceBase + '.s')]) |
| ] if IsNonSFIArch(arch) else []) |
| |
| def TranslatorLibs(arch, is_canonical, no_nacl_gcc): |
| setjmp_arch = arch |
| if setjmp_arch.endswith('-nonsfi'): |
| setjmp_arch = setjmp_arch[:-len('-nonsfi')] |
| bias_arch = TranslatorArchToBiasArch(arch) |
| translator_lib_dir = os.path.join('translator', arch, 'lib') |
| |
| arch_cmds = [] |
| if arch == 'arm': |
| arch_cmds.append( |
| BuildTargetTranslatorCmd('aeabi_read_tp.S', 'aeabi_read_tp.o', arch)) |
| elif arch == 'x86-32-nonsfi': |
| arch_cmds.extend( |
| [BuildTargetTranslatorCmd('entry_linux.c', 'entry_linux.o', arch), |
| BuildTargetTranslatorCmd('entry_linux_x86_32.S', 'entry_linux_asm.o', |
| arch)]) |
| elif arch == 'arm-nonsfi': |
| arch_cmds.extend( |
| [BuildTargetTranslatorCmd('entry_linux.c', 'entry_linux.o', arch), |
| BuildTargetTranslatorCmd('entry_linux_arm.S', 'entry_linux_asm.o', |
| arch)]) |
| |
| if not IsNonSFIArch(arch): |
| def ClangLib(lib): |
| return GSDJoin(lib, bias_arch) |
| clang_deps = [ ClangLib('newlib'), ClangLib('libs_support') ] |
| # Extract the object files from the newlib archive into our working dir. |
| # libcrt_platform.a is later created by archiving all the object files |
| # there. |
| crt_objs = ['memmove', 'memcmp', 'memset', 'memcpy'] |
| if arch == 'mips32': |
| crt_objs.extend(['memset-stub', 'memcpy-stub']) |
| libcrt_platform_string_cmds = [command.Command([ |
| PnaclTool('ar'), 'x', |
| os.path.join('%(' + ClangLib('newlib') + ')s', |
| MultilibLibDir(bias_arch), 'libcrt_common.a'), |
| ] + ['lib_a-%s.o' % f for f in crt_objs])] |
| # Copy compiler_rt from nacl-clang |
| clang_libdir = os.path.join( |
| 'lib', 'clang', CLANG_VER, 'lib', TripleFromArch(bias_arch)) |
| compiler_rt_cmds = [command.Copy( |
| os.path.join('%(' + ClangLib('libs_support') + ')s', |
| clang_libdir, 'libgcc.a'), |
| os.path.join('%(output)s', 'libgcc.a'))] |
| else: |
| clang_deps = [] |
| extra_flags = NonSFITargetLibCflags(bias_arch).split() |
| libcrt_platform_string_cmds = [BuildTargetTranslatorCmd( |
| 'string.c', 'string.o', arch, ['-std=c99'], |
| source_dir='%(newlib_subset)s')] |
| # Build compiler_rt with PNaCl |
| compiler_rt_cmds = [ |
| command.Command(MakeCommand() + [ |
| '-C', '%(abs_compiler_rt_src)s', 'ProjObjRoot=%(cwd)s', |
| 'VERBOSE=1', |
| 'CC=' + PnaclTool('clang', arch=bias_arch), 'clang_nacl', |
| 'EXTRA_CFLAGS=' + (NewlibIsystemCflags('le32') + ' ' + |
| ' '.join(extra_flags))]), |
| command.Copy(os.path.join( |
| 'clang_nacl', |
| 'full-' + bias_arch.replace('i686', 'i386') |
| .replace('mipsel', 'mips32'), |
| 'libcompiler_rt.a'), |
| os.path.join('%(output)s', 'libgcc.a')), |
| ] |
| |
| libs = { |
| GSDJoin('libs_support_translator', arch): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'output_subdir': translator_lib_dir, |
| 'dependencies': [ 'newlib_src', 'compiler_rt_src', 'subzero_src', |
| 'target_lib_compiler', 'newlib_le32'] + clang_deps, |
| # These libs include |
| # arbitrary stuff from native_client/src/{include,untrusted,trusted} |
| 'inputs': { 'src': os.path.join(NACL_DIR, 'pnacl', 'support'), |
| 'include': os.path.join(NACL_DIR, 'src'), |
| 'newlib_subset': os.path.join( |
| NACL_DIR, 'src', 'third_party', |
| 'pnacl_native_newlib_subset')}, |
| 'commands': SubzeroRuntimeCommands(arch, '.') + [ |
| BuildTargetTranslatorCmd('crtbegin.c', 'crtbegin.o', arch, |
| output_dir='%(output)s'), |
| BuildTargetTranslatorCmd('crtbegin.c', 'crtbegin_for_eh.o', arch, |
| ['-DLINKING_WITH_LIBGCC_EH'], |
| output_dir='%(output)s'), |
| BuildTargetTranslatorCmd('crtend.c', 'crtend.o', arch, |
| output_dir='%(output)s'), |
| # libcrt_platform.a |
| BuildTargetTranslatorCmd('pnacl_irt.c', 'pnacl_irt.o', arch), |
| BuildTargetTranslatorCmd('relocate.c', 'relocate.o', arch), |
| BuildTargetTranslatorCmd( |
| 'setjmp_%s.S' % setjmp_arch.replace('-', '_'), |
| 'setjmp.o', arch), |
| # Pull in non-errno __ieee754_fmod from newlib and rename it to |
| # fmod. This is to support the LLVM frem instruction. |
| BuildTargetTranslatorCmd( |
| 'e_fmod.c', 'e_fmod.o', arch, |
| ['-std=c99', '-I%(abs_newlib_src)s/newlib/libm/common/', |
| '-D__ieee754_fmod=fmod'], |
| source_dir='%(abs_newlib_src)s/newlib/libm/math'), |
| BuildTargetTranslatorCmd( |
| 'ef_fmod.c', 'ef_fmod.o', arch, |
| ['-std=c99', '-I%(abs_newlib_src)s/newlib/libm/common/', |
| '-D__ieee754_fmodf=fmodf'], |
| source_dir='%(abs_newlib_src)s/newlib/libm/math')] + |
| arch_cmds + libcrt_platform_string_cmds + [ |
| command.Command(' '.join([ |
| PnaclTool('ar'), 'rc', |
| command.path.join('%(output)s', 'libcrt_platform.a'), |
| '*.o']), shell=True), |
| # Dummy IRT shim |
| BuildTargetTranslatorCmd( |
| 'dummy_shim_entry.c', 'dummy_shim_entry.o', arch), |
| command.Command([PnaclTool('ar'), 'rc', |
| command.path.join('%(output)s', |
| 'libpnacl_irt_shim_dummy.a'), |
| 'dummy_shim_entry.o']), |
| ] + compiler_rt_cmds, |
| }, |
| } |
| |
| if not arch.endswith('-nonsfi'): |
| libs.update({ |
| GSDJoin('libgcc_eh', arch): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'output_subdir': translator_lib_dir, |
| 'dependencies': [ 'gcc_src', 'target_lib_compiler'], |
| 'inputs': { 'scripts': os.path.join(NACL_DIR, 'pnacl', 'scripts')}, |
| 'commands': [ |
| # Instead of trying to use gcc's build system to build only |
| # libgcc_eh, we just build the C files and archive them manually. |
| command.RemoveDirectory('include'), |
| command.Mkdir('include'), |
| command.Copy(os.path.join('%(gcc_src)s', 'gcc', |
| 'unwind-generic.h'), |
| os.path.join('include', 'unwind.h')), |
| command.Copy(os.path.join('%(scripts)s', 'libgcc-tconfig.h'), |
| 'tconfig.h'), |
| command.WriteData('', 'tm.h'), |
| BuildLibgccEhCmd('unwind-dw2.c', 'unwind-dw2.o', arch, |
| no_nacl_gcc), |
| BuildLibgccEhCmd('unwind-dw2-fde-glibc.c', |
| 'unwind-dw2-fde-glibc.o', arch, no_nacl_gcc), |
| command.Command([PnaclTool('ar'), 'rc', |
| command.path.join('%(output)s', 'libgcc_eh.a'), |
| 'unwind-dw2.o', 'unwind-dw2-fde-glibc.o']), |
| ], |
| }, |
| }) |
| return libs |
| |
| def UnsandboxedRuntime(arch, is_canonical): |
| assert arch in ('arm-linux', 'x86-32-linux', 'x86-32-mac', 'x86-64-linux') |
| |
| compiler = { |
| 'arm-linux': 'arm-linux-gnueabihf-gcc', |
| 'x86-32-linux': 'gcc', |
| 'x86-32-mac': 'gcc', |
| # x86-64 can't use gcc because the gcc available in the bots does not |
| # support x32. clang is good enough for the task, and it is available in |
| # the bots. |
| 'x86-64-linux': '%(abs_target_lib_compiler)s/bin/clang', |
| }[arch] |
| |
| arch_cflags = { |
| 'arm-linux': ['-mcpu=cortex-a9', '-D__arm_nonsfi_linux__'], |
| 'x86-32-linux': ['-m32'], |
| 'x86-32-mac': ['-m32'], |
| 'x86-64-linux': ['-mx32'], |
| }[arch] |
| |
| libs = { |
| GSDJoin('unsandboxed_runtime', arch): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'output_subdir': os.path.join('translator', arch, 'lib'), |
| 'dependencies': [ 'subzero_src', 'target_lib_compiler'], |
| # This lib #includes |
| # arbitrary stuff from native_client/src/{include,untrusted,trusted} |
| 'inputs': { 'support': os.path.join(NACL_DIR, 'src', 'nonsfi', 'irt'), |
| 'untrusted': os.path.join( |
| NACL_DIR, 'src', 'untrusted', 'irt'), |
| 'include': os.path.join(NACL_DIR, 'src'), }, |
| 'commands': [ |
| # The NaCl headers insist on having a platform macro such as |
| # NACL_LINUX defined, but src/nonsfi/irt_interfaces.c does not |
| # itself use any of these macros, so defining NACL_LINUX here |
| # even on non-Linux systems is OK. |
| # TODO(dschuff): this include path breaks the input encapsulation |
| # for build rules. |
| command.Command([compiler] + arch_cflags + ['-O2', '-Wall', |
| '-Werror', '-I%(top_srcdir)s/..', |
| '-DNACL_LINUX=1', '-DDEFINE_MAIN', |
| '-c', command.path.join('%(support)s', 'irt_interfaces.c'), |
| '-o', command.path.join('%(output)s', 'unsandboxed_irt.o')]), |
| command.Command([compiler] + arch_cflags + ['-O2', '-Wall', |
| '-Werror', '-I%(top_srcdir)s/..', |
| '-c', command.path.join('%(support)s', 'irt_random.c'), |
| '-o', command.path.join('%(output)s', 'irt_random.o')]), |
| command.Command([compiler] + arch_cflags + ['-O2', '-Wall', |
| '-Werror', '-I%(top_srcdir)s/..', |
| '-c', command.path.join('%(untrusted)s', 'irt_query_list.c'), |
| '-o', command.path.join('%(output)s', 'irt_query_list.o')]), |
| ] + SubzeroRuntimeCommands(arch, '%(output)s'), |
| }, |
| } |
| return libs |
| |
| |
| def SDKCompiler(arches): |
| arch_packages = ([GSDJoin('newlib', arch) for arch in arches] + |
| [GSDJoin('libcxx', arch) for arch in arches]) |
| compiler = { |
| 'sdk_compiler': { |
| 'type': 'work', |
| 'output_subdir': 'sdk_compiler', |
| 'dependencies': ['target_lib_compiler'] + arch_packages, |
| 'commands': [ |
| command.CopyRecursive('%(' + t + ')s', '%(output)s') |
| for t in ['target_lib_compiler'] + arch_packages], |
| }, |
| } |
| return compiler |
| |
| |
| def SDKLibs(arch, is_canonical, extra_flags=[]): |
| scons_flags = ['--verbose', 'MODE=nacl', '-j%(cores)s', 'naclsdk_validate=0', |
| 'pnacl_newlib_dir=%(abs_sdk_compiler)s', |
| 'DESTINATION_ROOT=%(work_dir)s'] |
| scons_flags.extend(extra_flags) |
| if arch == 'le32': |
| scons_flags.extend(['bitcode=1', 'platform=x86-32']) |
| elif not IsBCArch(arch): |
| scons_flags.extend(['nacl_clang=1', |
| 'platform=' + pynacl.platform.GetArch3264(arch)]) |
| else: |
| raise ValueError('Should not be building SDK libs for', arch) |
| libs = { |
| GSDJoin('core_sdk_libs', arch): { |
| 'type': TargetLibBuildType(is_canonical), |
| 'dependencies': ['sdk_compiler', 'target_lib_compiler'], |
| 'inputs': { |
| 'src_untrusted': os.path.join(NACL_DIR, 'src', 'untrusted'), |
| 'src_include': os.path.join(NACL_DIR, 'src', 'include'), |
| 'scons.py': os.path.join(NACL_DIR, 'scons.py'), |
| 'site_scons': os.path.join(NACL_DIR, 'site_scons'), |
| }, |
| 'commands': [ |
| command.Command( |
| [sys.executable, '%(scons.py)s', |
| 'includedir=' +os.path.join('%(output)s', |
| TripleFromArch(MultilibArch(arch)), |
| 'include'), |
| 'libdir=' + os.path.join('%(output)s', MultilibLibDir(arch)), |
| 'install'] + scons_flags, |
| cwd=NACL_DIR), |
| ], |
| } |
| } |
| return libs |