#!/usr/bin/env python3 # Copyright 2016 The Emscripten Authors. All rights reserved. # Emscripten is available under two separate licenses, the MIT license and the # University of Illinois/NCSA Open Source License. Both these licenses can be # found in the LICENSE file. """Archive helper script This script acts as a frontend replacement for `ar`. See emcc. This is needed because, unlike a traditional linker, emscripten can't handle archive with duplicate member names. This is because emscripten extracts archive to a temporary location and duplicate filenames will clobber each other in this case. """ # TODO(sbc): Implement `ar x` within emscripten, in python, to avoid this issue # and delete this file. from __future__ import print_function import hashlib import os import shutil import sys import tempfile from tools.toolchain_profiler import ToolchainProfiler from tools import shared from tools.response_file import substitute_response_files, create_response_file if __name__ == '__main__': ToolchainProfiler.record_process_start() # # Main run() function # def run(): if shared.Settings.WASM_BACKEND: # The wasm backend does suffer from the same probllem as fastcomp so doesn't # need the filename hashing. cmd = [shared.LLVM_AR] + sys.argv[1:] return shared.run_process(cmd, stdin=sys.stdin, check=False).returncode try: args = substitute_response_files(sys.argv) except IOError as e: shared.exit_with_error(e) newargs = [shared.LLVM_AR] + args[1:] tmpdir = None response_filename = None # The 3 argmuent form of ar doesn't involve other files. For example # 'ar x libfoo.a'. if len(newargs) > 3: tmpdir = tempfile.mkdtemp(prefix='emar-') cmd = newargs[1] if 'r' in cmd or 'q' in cmd: # We are adding files to the archive. # Normally the output file is then arg 2, except in the case were the # a or b modifiers are used in which case its arg 3. if 'a' in cmd or 'b' in cmd: out_arg_index = 3 else: out_arg_index = 2 # Add a hash to colliding basename, to make them unique. for j in range(out_arg_index + 1, len(newargs)): orig_name = newargs[j] full_name = os.path.abspath(orig_name) basename = os.path.basename(full_name) h = hashlib.md5(full_name.encode('utf-8')).hexdigest()[:8] parts = basename.split('.') parts[0] += '_' + h newname = '.'.join(parts) full_newname = os.path.join(tmpdir, newname) shutil.copyfile(orig_name, full_newname) newargs[j] = full_newname if shared.DEBUG: print('emar:', sys.argv, ' ==> ', newargs, file=sys.stderr) response_filename = create_response_file(newargs[3:], shared.get_emscripten_temp_dir()) newargs = newargs[:3] + ['@' + response_filename] if shared.DEBUG: print('emar:', sys.argv, ' ==> ', newargs, file=sys.stderr) rtn = shared.run_process(newargs, stdin=sys.stdin, check=False).returncode if tmpdir: shutil.rmtree(tmpdir) shared.try_delete(response_filename) return rtn if __name__ == '__main__': sys.exit(run())