Assertion: jl_TargetMachine

Summary of situation:
built julia-1.2.0-rc2 from source for centos6 with gcc 6.4.0 and -DGLIBCXX_USE_CXX11_ABI=0
dlopen an .so which embeds some simple julia code. “Lifted” into global namespace with dlopen(RTLD_NOW | RTLD_GLOBAL)
from a maya plugin.

jl_init() results in this assert:
void* jl_init_llvm(): Assertion `jl_TargetMachine && “Failed to select target machine -” " Is the LLVM backend for this CPU enabled?"’ failed.

Any ideas? A toy julia embedding works fine ( not loaded from maya )

I don’t know why this happens, but since you’re building from source you can investigate by logging out relevant-looking information at the location of the assert:

https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp#L7718

Also I’d try without RTLD_GLOBAL; there’s some WIP docs for this at https://github.com/JuliaLang/julia/pull/28886

XRef embedding julia in .so assert: jl_TargetMachine · Issue #32616 · JuliaLang/julia · GitHub

I had stepped into that function before ( built in debug ) basically most of the parameters to that function are empty. I can do it again, but the assert seems to indicate I’ll see the same thing.

RTLD_GLOBAL is needed. I’m a little fuzzy on the details of dlopen and namespacing when it relates to shared library symbols. What I believe happens is that maya loads plugins dynamically into a non-GLOBAL namespace ( I can’t control this ). If I then dlopen libjulia into non-GLOBAL namespace ( default in linux, not in other os’s ) and then julia dlopens, for example, sys.so, libjulia does not have access to the symbols from sys.

I might try to change the julia source so it’s dlopen flags default to RTLD_GLOBAL and see if that works.

RTLD_GLOBAL vs RTLD_LOCAL

from the dlopen man pages ( Linux ):
RTLD_GLOBAL

The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries.

RTLD_LOCAL

This is the converse of RTLD_GLOBAL , and the default if neither flag is specified. Symbols defined in this library are not made available to resolve references in subsequently loaded libraries.

If filename is a NULL pointer, then the returned handle is for the main program. When given to dlsym (), this handle causes a search for a symbol in the main program, followed by all shared libraries loaded at program startup, and then all shared libraries loaded by dlopen () with the flag RTLD_GLOBAL .

External references in the library are resolved using the libraries in that library’s dependency list and any other libraries previously opened with the RTLD_GLOBAL flag. If the executable was linked with the flag “-rdynamic” (or, synonymously, “–export-dynamic”), then the global symbols in the executable will also be used to resolve references in a dynamically loaded library.


Julia defaults to dlopen(RTLD_LOCAL) on linux. So anything Julia dlopens: the symbols defined by that library will not be made available for symbol resolution of subsequently loaded libraries. This seems ok.
If libjulia.so was dlopened with RTLD_LOCAL then it’s symbols won’t be available to anything it dlopens. Not clear what flags the dynamic linker will open libjulia’s dependencies with. This seems to create a problem.
For example, if you build a custom system image, it won’t be able to call any functions in libjulia, which seems a bit crippling. My example here is assuming sys.so ( or whatever your system image is called ) is dlopen by libjulia, which was the case in 0.6, but may not be true now, I haven’t stepped/grepped though the code to confirm it’s still doing so.

updated the issue at
XRef https://github.com/JuliaLang/julia/issues/32616

with a MWE in case anyone with more knowledge about dynamic linking cares to take a look.