LLVM library versionitis

I have a DSL that creates LLVM IR on the fly and JITs to x86 at runtime. (https://github.com/imageworks/OpenShadingLanguage)

Primarily, we have a main app that uses the library that implements our DSL. But we have other usage cases in which we have written dynamically-loaded plugins to 3rd party apps that we don't control, and our plugins use our language, which necessitates linking to LLVM.

Unfortunately, LLVM is getting popular enough that we are no longer the only part of our tool chain that uses it. In particular, one of those 3rd party apps now embeds LLVM, in fact a much older version than we like to use, and its symbols are conflicting at dynamic link time with the version we need to use for our plugin. The inverse situation is surely right around the corner as well -- some app that embeds our DSL may itself allow plugins, one of which may try to use LLVM and expect a different version than we have linked with.

Unfortunately, LLVM does not seem to have accounted for this problem. I started going down the straightforward route of changing the "llvm" namespace in my local LLVM build, with essentially this substitution:

  'namespace llvm {' -> 'namespace llvm_31 {} namespace llvm=llvm_31; namespace llvm_31 {'

Worked great for the C++ portion, but of course I quickly found parts of the LLVM core that are straight "C" linkage (no namespaces).

An ideal solution would be to have a build-time 'configure' option for everything to be wrapped in a namespace, and for all the "C" symbols to have names that incorporated versions, or even more generally, an arbitrary prefix that could completely sequester the symbols needed by an app or plugin. This is obviously a big operation, not an easy fix.

Can I convince anybody else of the wisdom of this for future LLVM releases?

Alternately, and/or in the mean time, does anybody have suggestions for me about how to deal with the very real problem I have about an app (I don't control) linking an LLVM version that is incompatible with the LLVM versions required by a plugin that uses my library?

Thanks.

I have a DSL that creates LLVM IR on the fly and JITs to x86 at runtime. (https://github.com/imageworks/OpenShadingLanguage)

Primarily, we have a main app that uses the library that implements our DSL. But we have other usage cases in which we have written dynamically-loaded plugins to 3rd party apps that we don't control, and our plugins use our language, which necessitates linking to LLVM.

Unfortunately, LLVM is getting popular enough that we are no longer the only part of our tool chain that uses it. In particular, one of those 3rd party apps now embeds LLVM, in fact a much older version than we like to use, and its symbols are conflicting at dynamic link time with the version we need to use for our plugin. The inverse situation is surely right around the corner as well -- some app that embeds our DSL may itself allow plugins, one of which may try to use LLVM and expect a different version than we have linked with.

Unfortunately, LLVM does not seem to have accounted for this problem. I started going down the straightforward route of changing the "llvm" namespace in my local LLVM build, with essentially this substitution:

'namespace llvm {' -> 'namespace llvm_31 {} namespace llvm=llvm_31; namespace llvm_31 {'

Worked great for the C++ portion, but of course I quickly found parts of the LLVM core that are straight "C" linkage (no namespaces).

An ideal solution would be to have a build-time 'configure' option for everything to be wrapped in a namespace, and for all the "C" symbols to have names that incorporated versions, or even more generally, an arbitrary prefix that could completely sequester the symbols needed by an app or plugin. This is obviously a big operation, not an easy fix.

Can I convince anybody else of the wisdom of this for future LLVM releases?

Alternately, and/or in the mean time, does anybody have suggestions for me about how to deal with the very real problem I have about an app (I don't control) linking an LLVM version that is incompatible with the LLVM versions required by a plugin that uses my library?

Since you're using dynamic linking you could get around patching by hiding LLVM's symbols to be internal to the shared library. This can be done with a list of symbols passed to the linker or by using visibility attributes[1] and building with -fvisibility=hidden. If you're supporting win32 you probably have a macro for __declspec(dllexport) already that could be reused.

[1] http://gcc.gnu.org/wiki/Visibility

- Ben

I can say that this approach does work, and is really important. Depending on what OS you're building for, using visibility hidden can work, or you can use an export file to make sure that no llvm symbols are exported from your [library / app] boundary.

-Chris