aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-05-21 17:08:11 +0200
committerAlon Zakai <alonzakai@gmail.com>2012-05-21 17:08:11 +0200
commita6615bc683a49e60085a05e83a491c7d9af653f9 (patch)
tree091093941b885368594e234296ac8b852030519b /tools
parentc6de9619dac086caf56803141202e9ff8354b259 (diff)
track symbols during linking in order to emulate gcc ld behavior of archives
Diffstat (limited to 'tools')
-rw-r--r--tools/shared.py24
1 files changed, 18 insertions, 6 deletions
diff --git a/tools/shared.py b/tools/shared.py
index 00ed25de..08fc581b 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -519,25 +519,37 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
@staticmethod
def link(files, target):
actual_files = []
+ unresolved_symbols = set() # necessary for .a linking, see below
+ resolved_symbols = set()
for f in files:
- if Building.is_ar(f):
- # Extract object files from ar archives, so we can link them using llvm-link
+ if not Building.is_ar(f):
+ new_symbols = Building.llvm_nm(f)
+ resolved_symbols = resolved_symbols.union(new_symbols.defs)
+ unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
+ actual_files.append(f)
+ else:
+ # Extract object files from ar archives, and link according to gnu ld semantics
+ # (link in an entire .o from the archive if it supplies symbols still unresolved)
cwd = os.getcwd()
try:
os.chdir(EMSCRIPTEN_TEMP_DIR)
if not os.path.exists('ar_output'):
os.makedirs('ar_output')
os.chdir('ar_output')
- contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n'))
+ contents = map(os.path.abspath, filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n')))
if len(contents) == 0:
print >> sys.stderr, 'Warning: Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f
else:
Popen([LLVM_AR, 'x', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
- actual_files += map(os.path.abspath, contents)
+ for content in contents:
+ new_symbols = Building.llvm_nm(content)
+ # Link in the .o if it provides symbols, *or* this is a singleton archive (which is apparently an exception in gcc ld)
+ if new_symbols.defs.intersection(unresolved_symbols) or len(files) == 1:
+ resolved_symbols = resolved_symbols.union(new_symbols.defs)
+ unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
+ actual_files.append(content)
finally:
os.chdir(cwd)
- else:
- actual_files.append(f)
try_delete(target)
output = Popen([LLVM_LINK] + actual_files + ['-o', 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