Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

install EXPORT problem for shared lib with dependencies

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.

like image 347
Dmitriy Erlih Avatar asked Mar 21 '11 13:03

Dmitriy Erlih


2 Answers

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 ... )
like image 94
André Avatar answered Nov 17 '22 00:11

André


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.

like image 1
Tsyvarev Avatar answered Nov 16 '22 22:11

Tsyvarev