From 7b29ae7e8ceaa13a10213324792fe5e32b06f186 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 31 Jul 2026 16:48:39 -0700 Subject: [PATCH] Turn off shared library signature check when configuring `AC_CHECK_LIB(somelib, func)` writes the following to conftest.c: ```C char func (); int main(void) { return func (); } ``` Then runs `emcc conftest.c -lsomelib` and checks whether it succeeds. With static libraries the signature mismatch is just a warning but with shared libraries it is a hard error. Before emcc 6.0.0, even if configure tried to make a shared library it would make a fake dynamic library instead and we didn't see this problem. But since then it makes a real dynamic library and then fails to configure. The fix is if we are configuring pass `-Wl,--no-shlib-sigcheck` to disable the signature check. --- test/test_other.py | 15 +++++++++++++++ tools/link.py | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/test/test_other.py b/test/test_other.py index af0d39f4fb216..ddd8cd37342f0 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -12406,6 +12406,21 @@ def test_autoconf_mode(self): output = self.run_process([os.path.abspath('a.out')], stdout=PIPE).stdout self.assertContained('Hello, world!', output) + def test_autoconf_check_lib_side_module(self): + # AC_CHECK_LIB probes for a symbol using an unprototyped declaration and a + # zero-argument call. Verify that the signature mismatch against the real + # function does not make the probe fail when the library is a side module. + create_file('libtest.c', 'int identity(int x) { return x; }\n') + self.run_process([EMCC, '-fPIC', '-shared', '-o', 'libtest.so', 'libtest.c']) + create_file('conftest.c', ''' + char identity (); + + int main(void) { + return identity (); + } + ''') + self.run_process([EMCC, 'conftest.c', 'libtest.so', '-o', 'conftest.js']) + def test_standalone_export_main(self): # Tests that explicitly exported `_main` does not fail, even though `_start` is the entry # point. diff --git a/tools/link.py b/tools/link.py index daad61cc53659..fdf489889ae30 100644 --- a/tools/link.py +++ b/tools/link.py @@ -889,6 +889,13 @@ def phase_linker_setup(linker_args): # ruff: ignore[complex-structure, too-many # autoconf declares functions without their proper signatures, and STRICT causes that to trip up by passing --fatal-warnings to the linker. if settings.STRICT: exit_with_error('autoconfiguring is not compatible with STRICT') + # AC_CHECK_LIB probes for a symbol by declaring it without a prototype + # (`char foo ();`) and then calling it with no arguments. When the symbol + # comes from an object file or an archive lld only warns about the + # resulting signature mismatch and synthesizes a thunk, but when it comes + # from a shared library the mismatch is a hard error. This turns off the + # shared library check. + linker_args.append('--no-shlib-sigcheck') if settings.OPT_LEVEL >= 1: default_setting('ASSERTIONS', 0)