There are a lot of matches spanning various graphical applications, from the zig programming language to LibreOffice, Darktable, Blender, to various other things using Flatpak, AppImage, etc.
The most common reason for this issue is that an application uses its own statically-linked version of LLVM, likely to JIT-compile something, while the user’s graphics driver likely links against the graphics driver, libGL.so, which for users of either Intel or AMD (or any other Mesa-based) drivers, links against the distro’s libLLVM.so
But there does not seem to be any consensus about how to solve that meaningfully, and allowing an application to be built a single time, e.g. against a static LLVM-10 because it has been updated to LLVM-10 API, and still run on a wide range of linux distros.
Proposing to add the software to the Linux repos does not cut it - what if I make a new software tomorrow ? There are still plenty of people on Ubuntu 16.04/18.04/20.04 for instance - they should be able to use that software, especially considering that this is a non-issue on macOS and Windows.
Neither does “rebuilding the app for each distro” - if an app uses LLVM 10 API, how many distros can be targeted today ? Pretty much only Arch Linux and similar.
So, is there a way ? A special option to set while building LLVM ? Is this issue on the radar of the LLVM team ?
I believe you need your application to either be packaged for the distro (and so linked against the LLVM present in the distribution repo), or embed LLVM inside your application with private visibility so that the copy of LLVM you embed won’t interact with the rest of the distribution (like the graphic drivers).
What if this happens on an out-of-source pass running in opt? I have specific case where i am using the Linker in a pass. If i link the Linker lib e.g:
I get in opt: opt: CommandLine Error: Option 'debug-pass' registered more than once!
if i don’t link the Linker lib i get: opt: symbol lookup error: lib/Transforms/libLinkRT.so: undefined symbol: _ZN4llvm6Linker11linkModulesERNS_6ModuleESt10unique_ptrIS1_St14default_deleteIS1_EEjSt8functionIFvS2_RKNS_9StringSetINS_15MallocAllocatorEEEEE
What I managed to do is add a linker script when linking my app that puts every symbol (including the statically-linked LLVM symbols) in a namespace.
The script looks like :
Can we get this fixed? Would be nice if people could use my software on Linux without running into this issue.
Maybe it could be fixed by having an option when building the LLVM libs of using an alternative namespace (for example you could use “my_llvm” instead of “llvm”.
That way the symbols won’t clash with another LLVM loaded into the process.
Not sure if this one is still valid, so here come my 2 cents:
I came across the same problem recently when building my own clang/llvm version with debug info. The solution I found when searching was to change the way the LLVM library was linked into the project inside the CMakeLists.txt.
Example:
//Find the libraries that correspond to the LLVM components
//that we wish to use
llvm_map_components_to_libnames(llvm_libs support core irreader)
The list of libraries is determined by using the llvm_map_components_to_libnames() CMake function. For a list of available
components look at the output of running llvm-config --components.
Not sure about the inner details of that function (more than the function name already explains) but it works for me.
I might be a little bit late to the party, but this thread was the first I found while I was researching this error, so I am posting my findings here.
I’ve had the same issue when using a pass-plugin that is statically linked against LLVM in clang (that also links LLVM statically). When trying to load the plugin, the constructor _GLOBAL__sub_I_RegAllocBasic.cpp of the plugin meanders to a
that lives in the compiler that loads the plugin. Just as it is described at #47565
I think the issue here is that it is clang’s singleton that tries to register the command line option and not the plugins. Since I am on macos, I think the dyld sees that the constructor tries to call the symbol and selects the global symbol exported by the compiler to resolve the call (and not the correct local one).
My solution was to instruct the apple linker to only export the functions needed for the plugin to be loaded by clang. So when you link your plugin something like this needs to be present: