blob: 0f2b0f87fdbcb3a2b0c86d05448f2bd19629ca0d [file] [log] [blame]
#!/usr/bin/env python2
# 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())