1

I need to package a C++ library that links to some other static libraries, and I'd like to be able to ship the compiled files alone without the need to ship the transitive dependencies as well. To this effect, I'm following this guide regarding modern CMake techniques, and I've specified all the needed dependencies as PRIVATE, as they are not used in my library's exposed API.

The issue is that it seems that, despite having specified the dependencies as PRIVATE, the linker still does not include them in the output library, so if I try to link my library to an executable, the linker will complain about missing symbols (at least using MSVC). Is there a way to solve this?

I've already taken a look at this but I'm not sure how to integrate it in the existing INSTALL targets

  • Most likely you will have to build it differently for different systems. Look at a [solution](https://stackoverflow.com/questions/37924383/combining-several-static-libraries-into-one-using-cmake) for gcc/clang and for [MSVC](https://stackoverflow.com/questions/13492365/how-to-merge-two-windows-vc-static-library-into-one). Doubt there is a better way since the wish to combine static libs is rather peculiar and CMake is rather general. – ixSci Aug 30 '18 at 14:23
  • So I'll basically need to cook a custom build script, correct? I won't be able to rely on cmake-install – Francesco Bertolaccini Aug 30 '18 at 17:43
  • Well, I would not call it a custom script. It is just a few direct commands which you can write in your CMake. I do not think that libs combining is an install step either. It is just yet another build step which depends on other libraries but with different command to make that step, that's all. – ixSci Aug 30 '18 at 17:52
  • CPack uses install targets to create packages, so I'd like to reuse that to the purpose. If I apply some custom commands to the targets, I still have problems with the generated config files, as they will try to solve the transitive dependencies – Francesco Bertolaccini Aug 30 '18 at 22:16
  • Is this a static or a dynamic library? PRIVATE linking just controls whether CMake propagates link requirements between targets. It doesn't affect the linking itself AFAIK. – Johannes S. Aug 31 '18 at 07:55
  • It's a static library. I figured that PRIVATE doesn't affect linking already, but the issue is that even though I archive the library using lib/ar, the generated config/targets file will still try to find the imported targets even though they are included – Francesco Bertolaccini Aug 31 '18 at 07:59

1 Answers1

0

Assuming that you are creating a static library:

You receive unresolved symbols because dependencies in static libraries are not resolved during their creation. Only when you link the static lib to an executable or shared library, the linker actually tries to resolve the required symbols (and will fail in your case).

So you need to combine your static libraries to a single one (as you already found out).

You should follow the approach of combining add_custom_command and add_custom_target that is outlined in the answers you linked to (https://stackoverflow.com/a/32888999/1228449).

Then use INSTALL( FILES ....) to add the combined library to your install commands, e.g.:

include(GNUInstallDirs)
INSTALL( FILES ${LIBNAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} )

EDIT: Alternatively, create a shared library.

ADD_LIBRARY( mylibrary SHARED ...)

Then the required symbols of the privately used static libraries are resolved at link time of your library. Furthermore, only the symbols that your library actually uses, are integrated into your library (whereas the static library will contain everything).

Johannes S.
  • 4,158
  • 21
  • 40
  • I assume I won't be able to use CMakePackageConfigHelpers right? I'd have to write the mylib-config.cmake file manually, to avoid it having to search for the now-included dependencies – Francesco Bertolaccini Aug 31 '18 at 08:33