This is what I effectively do. Although because I build the projects I
work on I use the CMake config file that LLVM exports to make it
trivially easy to use the LLVM libraries from within CMake (see
Building LLVM with CMake — LLVM 18.0.0git documentation).
The last time that I tried this, I hit all sorts of errors when LLVM was built as shared libraries and eventually just had my cmake files invoke llvm-config and manually populate the relevant CXX / LD flags.
AFAIK the exported CMake targets only work with the static LLVM
libraries right now.
That depends. It should work with shared libraries if the LLVM you are importing was built with BUILD_SHARED_LIBS=On. It will also work with llvm-shlib if it was built with LLVM_BUILD_LLVM_DYLIB=On.
The intention is that user's of LLVM should use
the llvm_map_components_to_libnames() function in CMake. Right now
that returns the names of the static library targets. In principle I
suppose it could be modified to return the shared library target
instead if a shared build was done. But there are a few issues to
consider here:
* When LLVM is built it possible to pick what components go into the
shared library which means in some cases
``llvm_map_components_to_libnames()`` would not work as intended if
just returns the LLVM shared library target name.
* A user of LLVM may want the ability to pick the static libraries
even though the shared libraries were built.
If static libraries are built, but the user wants shared libraries, there is no way to handle this other than re-configuring and rebuilding LLVM.
* In the shared library the C++ symbols hidden so we would need to add
an option to disable this behaviour.
LLVM_DYLIB_EXPORT_ALL=On will export all symbols from the dylib.
Here's what I'd like to suggest:
- Modify ``llvm_map_components_to_libnames()`` to take an optional
keyword which is either STATIC or SHARED. To avoid ambiguity this
means we cannot have a component called "STATIC" or "SHARED", I don't
imagine this would ever happen in practice. So the signature would
look like this
llvm_map_components_to_libnames(OUTPUTVAR [STATIC|SHARED] component0 ...)
- If set to static the static library names will be returned if the
components exists, otherwise emit an error message.
- If SHARED is specified CMake will check that the requested
components were added to the shared library when it was built. For
this to work the names of the components will need to be written into
LLVMConfig.cmake. If all the components requested are supposed to be
in the shared library then return the shared library target, otherwise
emit an error message (this includes the case where the shared library
was not built).
I have thought about doing this, and it wouldn’t be terribly complicated. There is already some goop in tools/llvm-c-test/CMakeLists.txt to check against the list of libraries in the dylib before linking the libraries separately.
While I don’t disagree with what you’re proposing, I actually think we need a larger reworking of how llvm_map_components_to_libnames works. The file that function comes from is basically a re-implementation of llvm-config in CMake, and it is really a bit of a dirty hack, and it unfortunately results in us having 2 different systems for expressing libraries dependencies at varying levels of robustness. I would like to find a way to get rid of all of the duplication, and to have a project-agnostic way to do this so that clang and other sub-projects could benefit from it as well.
That’s all a bit of a pipe dream though, so we shouldn’t let it prevent us from making the existing hacks work better.
- If STATIC or SHARED is not specified use STATIC so as to not break
the interface for existing users of llvm_map_components_to_libnames().
- Switch C++ symbol hiding in the shared library off by default.
I disagree with this. When I added llvm-shlib to the CMake build system I did it this way intentionally with specific clients in mind (the key one being WebKit). I’ve added lots of options to configure it in any way you want, but my inclination is that the default configuration should be what it is now. The library that llvm-shlib generates was not intended to be used by llvm in-tree tools, nor was it intended to be used by projects that import our build system. The whole point of having a single shared library is that your link command line is trivial (-lLLVM). While I’m completely in favor of extending it to work better for other use cases (and in fact we have a few planned uses ourselves), I would prefer if the default behavior didn’t change.
-Chris