0

I read extensively on this topic but simply did not find a solution, which I could say is the preferred CMAKE way.

Problem: I have multiple third-party open-source libraries (say libA, and libB) which support building either a static or shared library using CMake. I have my own library (libC) which depends on these libraries (libA and libB) privately.

find_package(libA REQUIRED)
find_package(libB REQUIRED)
add_library(libC STATIC ${SOURCE-FILES})
target_link_libraries(libC PRIVATE libA libB)

Now the static library 'libC' is my delivery/artifact, and I prefer that to be a static library only. Now imagine that a client wants to build an application (APP1) based on my delivery 'libC'.

find_package(libC REQUIRED)
add_executable(APP1 ${SOURCE-FILES})
target_link_libraries(APP1 PRIVATE libC)

Now, APP1 fails to compile because it cannot find the third-party libraries I used internally ('libA' and 'libB'). I understand why this does not compile ('libC' does not actually link against the third-party dependencies. Therefore all clients which link against my artifact should also have access to 'libA' and 'libB').

But my question is, what is the CMake way of doing this, among the options given below, or am I missing anything else ? How should CMakeLists.txt for libC look, such that its dependencies (libA,libB) are taken care of, and APP1 developer does not have to worry about them ?

  1. Object libraries of libA and libB: It has been widely mentioned that this is the CMake way. IMHO, this makes no sense for third-party libraries. What if libA and libB do not support this option, as in my case ? I am forced to do this myself.

  2. Supply libA, libB and libC together: This would be my preferred way, although I do not know yet how to find the location of the library (may be find_library?)

  3. Include sources of libA and libB directly in libC: This would be a no-go solution for me and I suppose for anyone. Note that libA and libB are NOT header only libraries.

  4. Dirty file tricks: Many people as in HERE tried to extract the object files from libA and libB and then link them directly to libC. The CMakeLists.txt for libC would look absolutely terrible but might generate a clean library.

  5. --whole-archive compiler option: This is pretty much same as option-4 but is suggested HERE. Again I believe the CMakeLists.txt will look terrible and no idea how the export/instll options work.

lightsunray
  • 409
  • 5
  • 16
  • This more or less depends on how you distribute the lib. E.g. for linux distribution as a `.deb` file you can mention the libs as dependencies (assuming they are available via the package manager. This would result in the libraries being installed from the repository when your lib is installed. You're not so lucky, if you distribute the lib as `.tar.gz`; in this case you'd probably need to distribute the libs alongside your own libs or instruct the user to install the libs you depend on... – fabian Jan 06 '21 at 21:19
  • I must clarify 'distributable' does not necessarily mean as packages. The libC project could be another independent CMake project in a different repo. But my question is how should CMakeLists.txt for libC look, in the ideal case ? What is the best way to handle the dependencies of libA and libB, so that APP1 developer does not have to worry about libC dependencies. I assume you would go with option-2 and provide libC and its dependencies as artifacts to clients ? – lightsunray Jan 06 '21 at 23:02
  • Assuming the user of your lib also uses CMake and `libA` and `libB` include proper `install` instructions you could link the dependencies to `libC` publicly and generate a configuration script for `libC` using `install(EXPORT)`, ect.. If they don't there's probably a way to achieve similar functionality, but it's more tedious. – fabian Jan 08 '21 at 17:09

0 Answers0