Skip to content

Don't depend on llvm-nm to detect archive indexes #10300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,21 +480,36 @@ def do_emscripten(infile, memfile):
return outfile


def is_ar_file_with_missing_index(archive_file):
# We parse the archive header outselves because llvm-nm --print-armap is slower and less
# reliable.
# See: https://github.com/emscripten-core/emscripten/issues/10195
archive_header = b'!<arch>\n'
file_header_size = 60

with open(archive_file, 'rb') as f:
header = f.read(len(archive_header))
if header != archive_header:
# This is not even an ar file
return False
file_header = f.read(file_header_size)
if len(file_header) != file_header_size:
# We don't have any file entires at all so we don't consider the index missing
return False

name = file_header[:16].strip()
# If '/' is the name of the first file we have an index
return name != '/'


def ensure_archive_index(archive_file):
# Fastcomp linking works without archive indexes.
if not shared.Settings.WASM_BACKEND or not shared.Settings.AUTO_ARCHIVE_INDEXES:
return
# Ignore stderr since llvm-nm prints "no symbols" to stderr for each object that has no symbols
stdout = run_process([shared.LLVM_NM, '--print-armap', archive_file], stdout=PIPE, stderr=PIPE).stdout
stdout = stdout.strip()
# Ignore empty archives
if not stdout:
return
if stdout.startswith('Archive map\n') or stdout.startswith('Archive index\n'):
return
shared.warning('%s: archive is missing an index; Use emar when creating libraries to ensure an index is created', archive_file)
shared.warning('%s: adding index', archive_file)
run_process([shared.LLVM_RANLIB, archive_file])
if is_ar_file_with_missing_index(archive_file):
shared.warning('%s: archive is missing an index; Use emar when creating libraries to ensure an index is created', archive_file)
shared.warning('%s: adding index', archive_file)
run_process([shared.LLVM_RANLIB, archive_file])


#
Expand Down
13 changes: 13 additions & 0 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8728,6 +8728,19 @@ def test_archive_no_index(self):
# The default behavior is to add archive indexes automatically.
run_process([PYTHON, EMCC, 'libfoo.a', 'hello_world.o'])

@no_fastcomp('AUTO_ARCHIVE_INDEXES only applies to wasm backend')
def test_archive_non_objects(self):
create_test_file('file.txt', 'test file')
# llvm-nm has issues with files that start with two or more null bytes since it thinks they
# are COFF files. Ensure that we correctly ignore such files when we process them.
create_test_file('zeros.bin', '\0\0\0\0')
run_process([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c')])
# No index added.
# --format=darwin (the default on OSX has a strange issue where it add extra
# newlines to files: https://bugs.llvm.org/show_bug.cgi?id=42562
run_process([PYTHON, EMAR, 'crS', '--format=gnu', 'libfoo.a', 'file.txt', 'zeros.bin', 'hello_world.o'])
run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), 'libfoo.a'])

def test_flag_aliases(self):
def assert_aliases_match(flag1, flag2, flagarg, extra_args):
results = {}
Expand Down