18

I try to build two libraries (say A and B) from one project. I use add_subdirectory cmake command in root cmake file. B depends on A.

When I try to add

INSTALL (TARGETS B EXPORT B
    PUBLIC_HEADER DESTINATION "include/B"
    LIBRARY DESTINATION "lib"
    ARCHIVE DESTINATION "lib")

INSTALL (EXPORT B DESTINATION "./")

CMake warns me about error in line with INSTALL (EXPORT .... It prints:

CMake Error: INSTALL (EXPORT "B" ...) includes target "B" which requires target "A" that is not in the export set.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
Dmitriy Erlih
  • 507
  • 2
  • 4
  • 12

2 Answers2

12

The error-message already tells you that you are exporting only one project, while it depends on the other project. The easiest solution is to export both projects. If they are both build by the same CMakeLists.txt you can simply call

install( TARGETS A B ... )

If not, then you probably have a top-level CMakeLists.txt (where you use add_subdirectory). You can setup an install-target there, let's call it "MyInstall". And in your subdirs refer to this top-level install-target

In your subdir...

install( TARGETS A EXPORT MyInstall ... )

similar for target B, and then you export "MyInstall" your top-level CMakeLists.txt:

install( EXPORT MyInstall ... )
André
  • 18,348
  • 6
  • 60
  • 74
  • 21
    And what if a shared lib meant to be installed depends on a static lib which is going to become part of the shared lib? In that case I don't need the static lib get installed but still CMake demands the static lib go to the same export. – krokoziabla Nov 02 '19 at 12:25
  • 1
    See here for further info: https://stackoverflow.com/questions/40183810/why-does-cmake-export-require-static-libraries-used-to-build-a-shared-library – Michael B May 17 '21 at 08:07
3

Aside from fixing

"A" that is not in the export set

part of the error message, one could consider to fix the part

target "B" which requires target "A"

by using PRIVATE linkage of B with A:

target_link_libraries(B PRIVATE A)

Such linkage implies that A is needed only for building the library B, but is not needed for anyone who links with B.

It depends from the library B whether such linkage is sufficient. But if it is, then this is a preferable way to overcome the error: If users of B doesn't need to link with A, then there is no reason to EXPORT A.


There are some easy signs when PRIVATE linkage is NOT an option:

  1. Some public header of library B includes a header of library A. In that case, if a user #include-s that header of B, then the header of A will be included too. And to find that header a compiler should be aware of include directories for A.
  2. B is a STATIC library, and A is either STATIC or SHARED. In that case, the binary file for B won't "embed" the binary file for A. So, when link with B, one should explicitly link with A too.

However, if both A and B are SHARED libraries, then PRIVATE linkage could still be an option:

While binary file for shared B doesn't "embed" the binary file for shared A, the binary file for B contains reference to the binary file for A. So when a linker will find B binary in the command line, it will link with A binary too. If B is installed, then A should be installed too (otherwise the linker won't find A). But for being able to export B, the A needn't to be exported.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Any ideas why cmake would generate this error when PRIVATE linkage is already being used? – pavon May 08 '23 at 18:03
  • @pavon: Probably you hit the case 2: You export a **static** library, so all linked libraries - private or not - are needed to be exported. – Tsyvarev May 08 '23 at 18:09