I’m trying to compile a simple C++ program that embeds some julia code. I’ve gotten this to work on macOS, but when trying to compile on my CentOS machine, I get this warning, followed by lots of errors:
/usr/bin/ld: warning: libLLVM-9jl.so, needed by /opt/julia-1.5.3/lib/libjulia.so, not found (try using -rpath or -rpath-link)
I compile with g++ -o jl_test -fPIC -I/opt/julia-1.5.3/include/julia -L/opt/julia-1.5.3/lib -Wl,-rpath,/opt/julia-1.5.3/lib src/embedded_julia.cpp -ljulia
Does anyone have any suggestions for fixing this or further diagnosing the issue?
Thanks, that was ultimately the issue, which I fixed simply by using the makefile in the docs. Now, though, I am getting many errors like this:
/opt/julia-1.5.3/lib/libjulia.so: undefined reference to `vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >@GLIBCXX_3.4.21'
followed by, at the end:
collect2: error: ld returned 1 exit status
make: *** [<builtin>: src/embedded_julia] Error 1
I’m having a hard time figuring out what this could be. I thought that maybe I need a newer version of gcc/g++, since strings /lib64/libsdtc++.so.6 | grep GLIBCXX does not show GLIBCXX_3.4.21 (mentioned in the errors), but I tried updating to gcc v8.3.1 and I’m running into the same issues…
EDIT: I see now that /opt/julia-1.5.3/lib/julia contains its own libstdc++, which does show the necessary GLIBCXX version, so I’m at a loss…
I tried to build the embedding example in a Centos 7 Docker container:
FROM centos:7
RUN yum install -y gcc make
RUN curl -sL "https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.3-linux-x86_64.tar.gz" | tar xzf - -C /usr/local --strip-components=1
COPY embed_example.c Makefile /root/
WORKDIR "/root"
Inside the container:
[root@5a985425fcb5 ~]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[root@5a985425fcb5 ~]# make
cc -std=gnu99 -I'/usr/local/include/julia' -fPIC -L'/usr/local/lib' -Wl,--export-dynamic embed_example.c -Wl,-rpath,'/usr/local/lib' -Wl,-rpath,'/usr/local/lib/julia' -ljulia -o embed_example
[root@5a985425fcb5 ~]# ./embed_example
1.4142135623730951
[root@5a985425fcb5 ~]# ldd embed_example
linux-vdso.so.1 => (0x00007ffc985ba000)
libjulia.so.1 => /usr/local/lib/libjulia.so.1 (0x00007f7541713000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7541345000)
libunwind.so.8 => /usr/local/lib/julia/libunwind.so.8 (0x00007f754110c000)
libLLVM-9jl.so => /usr/local/lib/julia/libLLVM-9jl.so (0x00007f753d9a9000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f753d7a5000)
librt.so.1 => /lib64/librt.so.1 (0x00007f753d59d000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f753d381000)
libstdc++.so.6 => /usr/local/lib/julia/libstdc++.so.6 (0x00007f753d003000)
libm.so.6 => /lib64/libm.so.6 (0x00007f753cd01000)
libgcc_s.so.1 => /usr/local/lib/julia/libgcc_s.so.1 (0x00007f753cae9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7541ee2000)
Can you provide more information about your environment?
I’m wondering if you should remove the “normal” lib paths when doing the link. I’m not sure how to do that. Maybe setting LD_LIBRARY_PATH to an empty string?
I’m fairly certain this is the relevant difference. I found this thread, which describes the problem I was having (@pixel27, you were on the right track), so I’m trying to follow the advice there.
Unfortunately, now I keep running into /opt/julia-1.5.3/lib/julia/libstdc++.so.6: error adding symbols: DSO missing from command line, and I haven’t been able to figure that out yet…
I installed CentOS Stream in a VirtualBox VM then downloaded Julia 1.5.3 and just extracted it into my home directory, .bashrc was updated to add $HOME/julia-1.5.3/bin to the path.
I started with the Makefile you specified and added the compile commands (the C file I saved as test.c) which ended up with:
Thanks - to be clear, when I try to compile the C test case, it works for me too. My end goal is not to compile this particular toy problem - I have a need to embed the julia code in some (actual) C++ code. I provided the toy problem because it gives me the same errors as my actual C++ example.
[root@ab82e3a1343c ~]# make
g++ -std=gnu99 -I'/usr/local/include/julia' -fPIC -L'/usr/local/lib' -Wl,--export-dynamic embed_example.cpp -Wl,-rpath,'/usr/local/lib' -Wl,-rpath,'/usr/local/lib/julia' -ljulia -nodefaultlibs "/usr/local/lib/julia/libstdc++.so.6" -lc -o embed_example
cc1plus: warning: command line option '-std=gnu99' is valid for C/ObjC but not for C++ [enabled by default]
[root@ab82e3a1343c ~]# ./embed_example
1.4142135623730951
[root@ab82e3a1343c ~]# ldd ./embed_example
linux-vdso.so.1 => (0x00007ffe54cc2000)
libjulia.so.1 => /usr/local/lib/libjulia.so.1 (0x00007fa1defbb000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa1debed000)
libunwind.so.8 => /usr/local/lib/julia/libunwind.so.8 (0x00007fa1de9b4000)
libLLVM-9jl.so => /usr/local/lib/julia/libLLVM-9jl.so (0x00007fa1db251000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fa1db04d000)
librt.so.1 => /lib64/librt.so.1 (0x00007fa1dae45000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa1dac29000)
libstdc++.so.6 => /usr/local/lib/julia/libstdc++.so.6 (0x00007fa1da8ab000)
libm.so.6 => /lib64/libm.so.6 (0x00007fa1da5a9000)
libgcc_s.so.1 => /usr/local/lib/julia/libgcc_s.so.1 (0x00007fa1da391000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa1df78a000)
The trick (suggested by @staticfloat) is to use -nodefaultlibs to not use the standard libraries (both C and C++), specify the full path to Julia’s libstdc++ and then use system’s libc.
Side note: this oversimplified example which is pure C would compile and run also without passing libstdc++ to the compiler, and the executable will not link to it. This is fine because the program is pure C. libllvm needs libstdc++, but it’ll look for $$ORIGIN/libstdc++ and find the one sitting next to it.
First of all, thanks again for your help, I appreciate it since I am fairly out of my depth here. I can indeed compile my original simple example with the modified makefile, however when I try it on my actual code (which I cannot share, unfortunately), I get an error. I was able to reproduce the error by just adding a string definition (again, unused here, sorry for the contrived code):
embed_example.cpp:
#include <julia.h>
#include <string>
int main(int argc, char *argv[])
{
std::string teststr = "abc";
/* required: setup the Julia context */
jl_init();
jl_value_t* ans = jl_eval_string("println(sqrt(2.0))");
jl_atexit_hook(0);
return 0;
}
g++ -std=gnu99 -I'/opt/julia-1.5.3/include/julia' -fPIC -L'/opt/julia-1.5.3/lib' -Wl,--export-dynamic embed_example.cpp -Wl,-rpath,'/opt/julia-1.5.3/lib' -Wl,-rpath,'/opt/julia-1.5.3/lib/julia' -ljulia -nodefaultlibs "/opt/julia-1.5.3/lib/julia/libstdc++.so.6" -lc -o embed_example
cc1plus: warning: command line option ‘-std=gnu99’ is valid for C/ObjC but not for C++ [enabled by default]
/usr/bin/ld: /tmp/ccqNnBOC.o: undefined reference to symbol '_Unwind_Resume@@GCC_3.0'
/opt/julia-1.5.3/lib/julia/libgcc_s.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [embed_example] Error 1
[root@d19e7a2a4c20 ~]# make
g++ -std=gnu99 -I'/usr/local/include/julia' -fPIC -L'/usr/local/lib' -Wl,--export-dynamic embed_example.cpp -Wl,-rpath,'/usr/local/lib' -Wl,-rpath,'/usr/local/lib/julia' -ljulia -nodefaultlibs "/usr/local/lib/julia/libstdc++.so.6" -lc "/usr/local/lib/julia/libgcc_s.so.1" -o embed_example
cc1plus: warning: command line option '-std=gnu99' is valid for C/ObjC but not for C++ [enabled by default]
[root@d19e7a2a4c20 ~]# ./embed_example
1.4142135623730951
Thanks very much - this works great for me. I guess I am still confused why we still need to specify the paths for libstdc++ and libgcc though, after including -Wl,-rpath,'/opt/julia-1.5.3/lib/julia, but I suspect that’s just more of my inexperience with gcc showing. I appreciate your help.
I think because those standard libraries have higher priority compared to Julia’s library in the search paths. You can see with -Wl,--trace that if you ask for -lstdc++ the linker will always look for GCC’s libstdc++