Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cmake: Exporting subproject targets to main project

I currently have a project called LIBS with a structure like this:

├── Lib1
│   ├── CMakeLists.txt
│   ├── lib1-class.cpp
│   └── lib1-class.h
├── lib2
│   └── CMakeLists.txt
│   ├── lib2-class.cpp
│   ├── lib2-class.h
├── cmake
│   └── LIBSConfig.cmake.in
├── CMakeLists.txt                                                           

in the main cmake file, I have:

install(
        TARGETS
        lib1
        lib2
        DESTINATION
        ${PROJECT_DIRNAME_lib}
        EXPORT
        ${PROJECT_NAME}Exports
)

install(
        EXPORT
        ${PROJECT_NAME}Exports
        DESTINATION
        ${PROJECT_DIRNAME_lib}
)

as I want to export these in a package that is discoverable by find_package().

My problem is that I generate lib1 and lib2 in their respective directories and when installing them, Cmake tells me that

Error:install TARGETS given target "lib1" which does not exist in this directory.

As suggested here, My understanding is that I should use Export() and in lib1 and lib2, have something of the form:

export(TARGETS lib1 FILE lib1Exports.cmake)

and in the LIBS project, have something like this:

ADD_LIBRARY(lib1 UNKNOWN IMPORTED)
set_property(TARGET lib1 PROPERTY IMPORTED_LOCATION lib1)

However it does not like me using the same name for this library that is being added from the parent project. It tells me:

Error:add_library cannot create imported target "lib1" because another target with the same name already exists.

so the library is available and I can link to it, etc. if I were to create another target in the parent directory, but I can't install it.

I have found the exact same problem in a bug report here but I believe cmake handles things differently now and I am just not doing it correctly. So am I doing it wrong? I would like to avoid using external packages if possible.

Update: the accepted solution works only for cases where there is no dependency between lib1, lib2. In that case one should use the solution provided to this question.

like image 368
ShS Avatar asked Mar 16 '16 13:03

ShS


People also ask

How do I export a target from CMake?

The export() command is used to generate a file exporting targets from a project build tree. Here we use the export() command to generate the export targets for the build tree. In this case, we'll create a file called MathFunctionsTargets. cmake in the cmake subdirectory of the build directory.

How do I find CMake targets?

You can show the Targets View by clicking on the view dropdown in the Solution Explorer: If you have worked with the projects and Solutions generated by CMake before, you should feel right at home.

What does Add_subdirectory do in CMake?

Add a subdirectory to the build. Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.


1 Answers

As noted in the bugreport you refer to install() command should be issued from the same directory where target is created. As you have libraries target created in different directories, you need to assign different export names for them, and, consequently, different export files.

But you are free to include both export files into the LIBSConfig.cmake script:

cmake/LIBSConfig.cmake:

get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/LIBS-lib1.cmake)
include(${SELF_DIR}/LIBS-lib2.cmake)

lib1/CMakeLists.txt:

add_library(lib1 ...)
install(TARGET lib1 EXPORT lib1-export ...)

lib2/CMakeLists.txt:

add_library(lib2 ...)
install(TARGET lib2 EXPORT lib2-export ...)

CMakeLists.txt:

add_subdirectory(lib1)
add_subdirectory(lib2)

install(EXPORT lib1-export FILENAME LIBS-lib1.cmake DESTINATION lib/LIBS)
install(EXPORT lib2-export FILENAME LIBS-lib2.cmake DESTINATION lib/LIBS)
install(FILES cmake/LIBSConfig.cmake DESTINATION lib/LIBS)

Note, that export command exports build tree. It is usually not suitable for find_package, which is normally used for find installed files.

like image 64
Tsyvarev Avatar answered Nov 11 '22 09:11

Tsyvarev