diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/shared.py | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/tools/shared.py b/tools/shared.py index 45400581..ba953e19 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -90,6 +90,7 @@ CLANG_CPP=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang++')) CLANG=CLANG_CPP LLVM_LINK=os.path.join(LLVM_ROOT, 'llvm-link') LLVM_LD=os.path.join(LLVM_ROOT, 'llvm-ld') +LLVM_AR=os.path.join(LLVM_ROOT, 'llvm-ar') LLVM_OPT=os.path.expanduser(os.path.join(LLVM_ROOT, 'opt')) LLVM_AS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-as')) LLVM_DIS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-dis')) @@ -367,13 +368,17 @@ class Building: return env @staticmethod - def handle_CMake_toolchain(args): + def handle_CMake_toolchain(args, env): CMakeToolchain = '''# the name of the target operating system SET(CMAKE_SYSTEM_NAME Linux) # which C and C++ compiler to use SET(CMAKE_C_COMPILER $EMSCRIPTEN_ROOT/emcc) SET(CMAKE_CXX_COMPILER $EMSCRIPTEN_ROOT/em++) +SET(CMAKE_AR $EMSCRIPTEN_ROOT/emar) +SET(CMAKE_RANLIB $EMSCRIPTEN_ROOT/emranlib) +SET(CMAKE_C_FLAGS $CFLAGS) +SET(CMAKE_CXX_FLAGS $CXXFLAGS) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include ) @@ -384,7 +389,10 @@ SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include ) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_from_root('')) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ + .replace('$EMSCRIPTEN_ROOT', path_from_root('')) \ + .replace('$CFLAGS', env['CFLAGS']) \ + .replace('$CXXFLAGS', env['CFLAGS']) toolchainFile = mkstemp(suffix='.txt')[1] open(toolchainFile, 'w').write(CMakeToolchain) args.append('-DCMAKE_TOOLCHAIN_FILE=%s' % os.path.abspath(toolchainFile)) @@ -395,8 +403,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ if env is None: env = Building.get_building_env() env['EMMAKEN_JUST_CONFIGURE'] = '1' - if 'cmake' in sys.argv[0]: - args = Building.handle_CMake_toolchain(args) + if 'cmake' in args[0]: + args = Building.handle_CMake_toolchain(args, env) Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0] del env['EMMAKEN_JUST_CONFIGURE'] @@ -443,18 +451,18 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ stderr=open(os.path.join(project_dir, 'configure_err'), 'w'), env=env) Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_'), 'w'), stderr=open(os.path.join(project_dir, 'make_err'), 'w'), env=env) - bc_file = os.path.join(project_dir, 'bc.bc') - Building.link(generated_libs, bc_file) if cache is not None: - cache[cache_name] = open(bc_file, 'rb').read() + cache[cache_name] = {} + for f in generated_libs: + cache[cache_name][f] = open(f, 'rb').read() if old_dir: os.chdir(old_dir) - return bc_file + return generated_libs @staticmethod def link(files, target): try_delete(target) - output = Popen([LLVM_LINK] + files + ['-o', target], stdout=PIPE).communicate()[0] + output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target], stdout=PIPE).communicate()[0] assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output # Emscripten optimizations that we run on the .ll file @@ -546,6 +554,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ assert os.path.exists(output_filename), 'emcc could not create output file' @staticmethod + def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None): + try_delete(output_filename) + Popen([EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate() + if 'c' in action: + assert os.path.exists(output_filename), 'emar could not create output file' + + @staticmethod def emscripten(filename, append_ext=True, extra_args=[]): # Allow usage of emscripten.py without warning os.environ['EMSCRIPTEN_SUPPRESS_USAGE_WARNING'] = '1' @@ -725,6 +740,22 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ return filename + '.cc.js' + _is_ar_cache = {} + @staticmethod + def is_ar(filename): + try: + if Building._is_ar_cache.get(filename): + return Building._is_ar_cache[filename] + b = open(filename, 'r').read(8) + sigcheck = b[0] == '!' and b[1] == '<' and \ + b[2] == 'a' and b[3] == 'r' and \ + b[4] == 'c' and b[5] == 'h' and \ + b[6] == '>' and ord(b[7]) == 10 + Building._is_ar_cache[filename] = sigcheck + return sigcheck + except: + return False + @staticmethod def is_bitcode(filename): # checks if a file contains LLVM bitcode @@ -733,9 +764,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ defs = Building.llvm_nm(filename, stderr=PIPE) # If no symbols found, it might just be an empty bitcode file, try to dis it if len(defs.defs) + len(defs.undefs) + len(defs.commons) == 0: - test_ll = os.path.join(EMSCRIPTEN_TEMP_DIR, 'test.ll') - Building.llvm_dis(filename, test_ll) - assert os.path.exists(test_ll) + # llvm-nm 3.0 has a bug when reading symbols from ar files + # so try to see if we're dealing with an ar file, in which + # case we should try to dis it. + if not Building.is_ar(filename): + test_ll = os.path.join(EMSCRIPTEN_TEMP_DIR, 'test.ll') + Building.llvm_dis(filename, test_ll) + assert os.path.exists(test_ll) except: return False @@ -743,6 +778,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ b = open(filename, 'r').read(4) if b[0] == 'B' and b[1] == 'C': return True + # look for ar signature + elif Building.is_ar(filename): + return True # on OS X, there is a 20-byte prefix elif ord(b[0]) == 222 and ord(b[1]) == 192 and ord(b[2]) == 23 and ord(b[3]) == 11: b = open(filename, 'r').read(24) |