1

I'm using Ubuntu 16.04, g++ 5.4.0, and CMake 3.5.1, but my results are consistent on macOS Mojave with the most recent XCode version.

I have one program with a SWIG module, MyModule, that depends on a system that is a bunch of C++ libraries and its own SWIG module, PSEngine. Whenver I try to run the MyModule Java program which loads PSEngine, I get the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: psengine.PSEngineInterfaceJNI.swig_module_init()V
    at psengine.PSEngineInterfaceJNI.swig_module_init(Native Method)
    at psengine.PSEngineInterfaceJNI.<clinit>(PSEngineInterfaceJNI.java:356)
    at psengine.PSEngine.makeInstance(PSEngine.java:59)
    at MyModule.Main.main(Main.java:19)

Ultimately, my question is this: why isn't dlsym searching in libPSEngine_g.so for the symbol, and how can I make it look there? The rest of my journey and what I've tried follows.

LD_LIBRARY_PATH points to the directory containing libPSEngine_g.so, and I am passing that same directory to Java using -Djava.library.path. I double-checked what symbol it was looking for by breakpointing at dlsym, and confirmed that the C++ symbol it's looking for is this:

Java_psengine_PSEngineInterfaceJNI_swig_1module_1init

That symbol is present in libPSEngine_g.so:

$ nm libPSEngine_g.so | grep PSEngineInterfaceJNI_swig_1module
000000000005f2e1 T Java_psengine_PSEngineInterfaceJNI_swig_1module_1init

For some reason, libMyModule.so didn't depend on libPSEngine_g.so or any of the other, non-SWIG C++ libraries in the system it's supposed to depend on:

$ ldd libMyModule.so 
    linux-vdso.so.1 =>  (0x00007fffd56a9000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa6b1d60000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa6b1990000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa6b1680000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa6b2400000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa6b1450000)

This is the initial link entry in the MyModule CMakeLists.txt:

swig_link_libraries(${PROJECT}
  "PSEngine${EUROPA_SUFFIX}"
  "System${EUROPA_SUFFIX}"
  "Resource${EUROPA_SUFFIX}"
  "Solvers${EUROPA_SUFFIX}"
  "NDDL${EUROPA_SUFFIX}"
  "TemporalNetwork${EUROPA_SUFFIX}"
  "RulesEngine${EUROPA_SUFFIX}"
  "ConstraintEngine${EUROPA_SUFFIX}"
  "Utils${EUROPA_SUFFIX}"
  "TinyXml${EUROPA_SUFFIX}"
  )

I thought at first that this was a problem I'd seen with linking SWIG libraries using "newer" (less than 8 years old) linkers, and it wasn't including symbols from libPSEngine_g.so because nothing in libMyModule.so actually mentioned those symbols. I tried forcing it to be undefined in the link, to coax the linker to define the symbol:

swig_link_libraries(${PROJECT}
  "-Wl,-u,${PSENGINE_SYMBOL}"
  "PSEngine${EUROPA_SUFFIX}"
  "System${EUROPA_SUFFIX}"
  "Resource${EUROPA_SUFFIX}"
  "Solvers${EUROPA_SUFFIX}"
  "NDDL${EUROPA_SUFFIX}"
  "TemporalNetwork${EUROPA_SUFFIX}"
  "RulesEngine${EUROPA_SUFFIX}"
  "ConstraintEngine${EUROPA_SUFFIX}"
  "Utils${EUROPA_SUFFIX}"
  "TinyXml${EUROPA_SUFFIX}"
  )

However, this just left the symbol undefined in libMyModule.so. That wasn't the problem. A bunch of googling around turned up a bunch of possible linker options, including --no-as-needed, --export-dynamic, and --no-copy-dt-needed-entries. Of that, the only one that produces the dependency that I'm looking for is --no-as-needed:

swig_link_libraries(${PROJECT}
  "-Wl,--no-as-needed"
  "PSEngine${EUROPA_SUFFIX}"
  "System${EUROPA_SUFFIX}"
  "Resource${EUROPA_SUFFIX}"
  "Solvers${EUROPA_SUFFIX}"
  "NDDL${EUROPA_SUFFIX}"
  "TemporalNetwork${EUROPA_SUFFIX}"
  "RulesEngine${EUROPA_SUFFIX}"
  "ConstraintEngine${EUROPA_SUFFIX}"
  "Utils${EUROPA_SUFFIX}"
  "TinyXml${EUROPA_SUFFIX}"
  )

Gives me the link command:

/usr/bin/c++  -fPIC   -shared  -o libMyProject.so CMakeFiles/MyProject.dir/MyProjectJAVA_wrap.cxx.o -Wl,--no-as-needed /home/miatauro/workspace/my_project/europa/dist/europa/libPSEngine_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libSystem_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libResource_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libSolvers_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libANML_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libNDDL_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libTemporalNetwork_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libRulesEngine_g.so /usr/local/lib/libantlr3c.so /home/miatauro/workspace/my_project/europa/dist/europa/libPlanDatabase_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libConstraintEngine_g.so /home/miatauro/workspace/my_project/europa/dist/europa/libUtils_g.so -ldl /home/miatauro/workspace/my_project/europa/dist/europa/libTinyXml_g.so -Wl,-rpath,/home/miatauro/workspace/my_project/europa/dist/europa:/usr/local/lib 

Which produces the dependencies:

$ ldd libMyModule.so 
    linux-vdso.so.1 =>  (0x00007fffddb15000)
    /home/miatauro/workspace/my_project/europa/dist/europa/libPSEngine_g.so (0x00007f1f52720000)
    libSystem_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libSystem_g.so (0x00007f1f524f0000)
    libResource_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libResource_g.so (0x00007f1f51f47000)
    libSolvers_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libSolvers_g.so (0x00007f1f51b61000)
    libANML_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libANML_g.so (0x00007f1f517c0000)
    libNDDL_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libNDDL_g.so (0x00007f1f5142b000)
    libTemporalNetwork_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libTemporalNetwork_g.so (0x00007f1f5111a000)
    libRulesEngine_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libRulesEngine_g.so (0x00007f1f50e30000)
    libantlr3c.so => /usr/local/lib/libantlr3c.so (0x00007f1f50c10000)
    libPlanDatabase_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libPlanDatabase_g.so (0x00007f1f50692000)
    libConstraintEngine_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libConstraintEngine_g.so (0x00007f1f501f8000)
    libUtils_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libUtils_g.so (0x00007f1f4ff60000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1f4fd30000)
    libTinyXml_g.so => /home/miatauro/workspace/my_project/europa/dist/europa/libTinyXml_g.so (0x00007f1f4fb10000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1f4f780000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1f4f460000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1f4f240000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1f4ee70000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1f52c00000)

The dependency on libPSEngine_g.so is oddly different from the rest, just containing the full path.

This doesn't solve the lookup problem, though, and turning on LD_DEBUG=all in my environment produces the following when it's looking for the relevant symbol:

     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libSystem_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libANML_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libResource_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libSolvers_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libNDDL_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libTemporalNetwork_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libRulesEngine_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libPlanDatabase_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libConstraintEngine_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libUtils_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/home/miatauro/workspace/my_project/europa/dist/europa/libTinyXml_g.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/lib/x86_64-linux-gnu/libgcc_s.so.1 [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/usr/local/lib/libantlr3c.so [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/lib/x86_64-linux-gnu/libm.so.6 [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/lib/x86_64-linux-gnu/libdl.so.2 [0]
     18673: symbol=Java_psengine_PSEngineInterfaceJNI_swig_1module_1init;  lookup in file=/lib64/ld-linux-x86-64.so.2 [

libPSEngine_g.so doesn't appear in the search at all. Setting LD_PRELOAD for the java command to load libPSEngine_g.so doesn't change anything in the search order.

I'm totally stumped. StackOverflow, what is your wisdom?

Michael Iatauro
  • 133
  • 1
  • 4

0 Answers0