mirror of
https://github.com/Z3Prover/z3
synced 2026-04-02 18:08:57 +00:00
Fix Java UnsatisfiedLinkError on macOS (#7640)
On macOS, libz3java.dylib was built without an rpath to find libz3.dylib in the same directory. When Java loaded the JNI library, the dynamic linker could not resolve the libz3 dependency, causing UnsatisfiedLinkError. Three fixes: - mk_util.py: add -Wl,-rpath,@loader_path to the macOS JNI link command - CMakeLists.txt: set MACOSX_RPATH, BUILD_RPATH, INSTALL_RPATH for z3java target; remove duplicate headerpad block - update_api.py: improve Native.java error message to show the root cause from both load attempts instead of only the fallback error Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
3745bdd43b
commit
d3f5fd6825
4 changed files with 59 additions and 7 deletions
|
|
@ -1919,6 +1919,9 @@ class JavaDLLComponent(Component):
|
|||
if IS_WINDOWS: # On Windows, CL creates a .lib file to link against.
|
||||
out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' %
|
||||
os.path.join('api', 'java', 'Native'))
|
||||
elif IS_OSX:
|
||||
out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) -Wl,-rpath,@loader_path $(SLINK_EXTRA_FLAGS)\n' %
|
||||
os.path.join('api', 'java', 'Native'))
|
||||
else:
|
||||
out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) $(SLINK_EXTRA_FLAGS)\n' %
|
||||
os.path.join('api', 'java', 'Native'))
|
||||
|
|
|
|||
|
|
@ -208,6 +208,45 @@ class TestJNIArchitectureFlagsInMakefile(unittest.TestCase):
|
|||
"(the import library)",
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Tests for macOS rpath, so libz3java.dylib can find libz3.dylib
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_macos_uses_loader_path_rpath(self):
|
||||
"""
|
||||
On macOS, the JNI link command must include -Wl,-rpath,@loader_path
|
||||
so that libz3java.dylib can find libz3.dylib in the same directory
|
||||
at runtime. Without this, Java fails with UnsatisfiedLinkError.
|
||||
"""
|
||||
comp = self._make_java_dll_component()
|
||||
text = self._generate_makefile(
|
||||
comp, is_windows=False, is_osx=True, is_arch_arm64=True
|
||||
)
|
||||
link_lines = self._find_jni_link_lines(text)
|
||||
self.assertTrue(link_lines, "Expected at least one JNI link line")
|
||||
for line in link_lines:
|
||||
self.assertIn(
|
||||
'-Wl,-rpath,@loader_path', line,
|
||||
"macOS JNI link command must set rpath to @loader_path "
|
||||
"so libz3java.dylib finds libz3.dylib at runtime",
|
||||
)
|
||||
|
||||
def test_linux_does_not_use_loader_path(self):
|
||||
"""
|
||||
On Linux, @loader_path is a macOS concept and must not appear.
|
||||
"""
|
||||
comp = self._make_java_dll_component()
|
||||
text = self._generate_makefile(
|
||||
comp, is_windows=False, is_osx=False, is_arch_arm64=False
|
||||
)
|
||||
link_lines = self._find_jni_link_lines(text)
|
||||
self.assertTrue(link_lines, "Expected at least one JNI link line")
|
||||
for line in link_lines:
|
||||
self.assertNotIn(
|
||||
'@loader_path', line,
|
||||
"@loader_path is macOS-specific and must not appear on Linux",
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Consistency check: SLINK_EXTRA_FLAGS in mk_config for cross-compile
|
||||
# ------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -631,7 +631,16 @@ def mk_java(java_src, java_dir, package_name):
|
|||
java_native.write(' try {\n')
|
||||
java_native.write(' System.loadLibrary("z3java");\n')
|
||||
java_native.write(' } catch (UnsatisfiedLinkError ex) {\n')
|
||||
java_native.write(' System.loadLibrary("libz3java");\n')
|
||||
java_native.write(' try {\n')
|
||||
java_native.write(' System.loadLibrary("libz3java");\n')
|
||||
java_native.write(' } catch (UnsatisfiedLinkError ex2) {\n')
|
||||
java_native.write(' throw new UnsatisfiedLinkError(\n')
|
||||
java_native.write(' "Failed to load z3java native library. "\n')
|
||||
java_native.write(' + "Tried z3java: " + ex.getMessage() + "; "\n')
|
||||
java_native.write(' + "Tried libz3java: " + ex2.getMessage() + ". "\n')
|
||||
java_native.write(' + "Make sure both the JNI library and libz3 are in java.library.path "\n')
|
||||
java_native.write(' + "or set DYLD_LIBRARY_PATH (macOS) / LD_LIBRARY_PATH (Linux).");\n')
|
||||
java_native.write(' }\n')
|
||||
java_native.write(' }\n')
|
||||
java_native.write(' }\n')
|
||||
java_native.write(' }\n')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue