105 строки
3.3 KiB
Python
Executable File
105 строки
3.3 KiB
Python
Executable File
#!/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
|
|
|
|
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():
|
|
args = substitute_response_files(sys.argv)
|
|
newargs = [shared.LLVM_AR] + args[1:]
|
|
|
|
to_delete = []
|
|
|
|
# The 3 argmuent form of ar doesn't involve other files. For example
|
|
# 'ar x libfoo.a'.
|
|
if len(newargs) > 3:
|
|
cmd = newargs[1]
|
|
if 'r' 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
|
|
|
|
contents = set()
|
|
if os.path.exists(newargs[out_arg_index]):
|
|
cmd = [shared.LLVM_AR, 't', newargs[out_arg_index]]
|
|
output = shared.check_call(cmd, stdout=shared.PIPE).stdout
|
|
contents.update(output.split('\n'))
|
|
|
|
# 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)
|
|
dirname = os.path.dirname(full_name)
|
|
basename = os.path.basename(full_name)
|
|
if basename not in contents:
|
|
contents.add(basename)
|
|
continue
|
|
h = hashlib.md5(full_name.encode('utf-8')).hexdigest()[:8]
|
|
parts = basename.split('.')
|
|
parts[0] += '_' + h
|
|
newname = '.'.join(parts)
|
|
full_newname = os.path.join(dirname, newname)
|
|
assert not os.path.exists(full_newname)
|
|
try:
|
|
shutil.copyfile(orig_name, full_newname)
|
|
newargs[j] = full_newname
|
|
to_delete.append(full_newname)
|
|
contents.add(newname)
|
|
except:
|
|
# it is ok to fail here, we just don't get hashing
|
|
contents.add(basename)
|
|
pass
|
|
|
|
if shared.DEBUG:
|
|
print('emar:', sys.argv, ' ==> ', newargs, file=sys.stderr)
|
|
|
|
response_filename = create_response_file(newargs[3:], shared.get_emscripten_temp_dir())
|
|
to_delete += [response_filename]
|
|
newargs = newargs[:3] + ['@' + response_filename]
|
|
|
|
if shared.DEBUG:
|
|
print('emar:', sys.argv, ' ==> ', newargs, file=sys.stderr)
|
|
|
|
try:
|
|
return shared.run_process(newargs, stdin=sys.stdin, check=False).returncode
|
|
finally:
|
|
for d in to_delete:
|
|
shared.try_delete(d)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(run())
|