diff --git a/emcc.py b/emcc.py index fdae1bc40bf1e..90dc74cb93eca 100755 --- a/emcc.py +++ b/emcc.py @@ -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'!\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]) # diff --git a/tests/test_other.py b/tests/test_other.py index 579f9b52cec9e..bbacabd6373d0 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -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 = {}