Search code examples
c++cmake

Link two cmake projects next to each other


Lets say I have two cmake libraries: lib1 and lib2, where lib2 depends on lib1. How can I do it without putting them into one general cmake project, meaning there should be only two CMakeLists.txt (one for lib1 and one for lib2) but not general CMakeLists.txt that link them together.

cmake_agnostic_root/
|-- lib1/
|   |-- src/
|   |-- include/
|   |-- CMakeLists.txt
|-- lib2/
|   |-- src/
|   |-- include/
|   |-- CMakeLists.txt
|-- (there must be no CMakeLists.txt on this level)

In my understanding there should be something inside lib2's CMakeLists.txt only that will include lib1.

What I tried (nothing worked):

  1. add_subdirectory: Tried to add this line to lib2 cmake:
add_subdirectory(../lib1 lib1)

but lib2 still can't find lib1's headers

  1. ExternalProject: Tried to add this lines to lib2 cmake:
include(ExternalProject)

ExternalProject_Add(
  lib1
  SOURCE_DIR ../lib1
)

Probably I use this command wrong, as in all examples it downloads git repositories, but I need to use local folder lib1 next to lib2.

What am I doing wrong?

Edit: I want to call cmake in lib2 that triggers lib1 build and then use it to build lib2.


Solution

  • I created a test project with exe + lib:

    cmake_agnostic_root/
    |-- app/
    |   |-- src/
    |   |-- include/
    |   |-- CMakeLists.txt
    |-- lib/
    |   |-- src/
    |   |-- include/
    |   |-- CMakeLists.txt
    |-- (there must be no CMakeLists.txt on this level)
    

    It't bit ugly and need improvements but a good starting point

    The exe CMakeList.txt:

    project(app)
    
    cmake_minimum_required(VERSION 3.16)
    
    include(ExternalProject)
    
    if (CMAKE_CONFIGURATION_TYPES)
        # support multiple configurations: Debug and Release 
        set(TEST_INSTALL_PREFIX "<INSTALL_DIR>/$<CONFIG>")
        set(TEST_LIBRARY_FILE ${CMAKE_BINARY_DIR}/test/$<CONFIG>/lib/test.lib)
        set(TEST_LIBRARY_HEADERS ${CMAKE_BINARY_DIR}/test/$<CONFIG>/include)
    else()
        # single configuration: Debug or Release
        set(TEST_INSTALL_PREFIX "<INSTALL_DIR>")
        set(TEST_LIBRARY_FILE ${CMAKE_BINARY_DIR}/test/lib/libtest.a)
        set(TEST_LIBRARY_HEADERS ${CMAKE_BINARY_DIR}/test/include)
    endif()
    
    ExternalProject_Add(test.proj
        URL ${CMAKE_CURRENT_SOURCE_DIR}/../lib
        PREFIX test
        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${TEST_INSTALL_PREFIX}
        BUILD_BYPRODUCTS ${TEST_LIBRARY_FILE}
    )
    
    add_library(test INTERFACE)
    target_include_directories(test INTERFACE ${TEST_LIBRARY_HEADERS})
    target_link_libraries(test INTERFACE ${TEST_LIBRARY_FILE})
    add_dependencies(test test.proj)
    
    add_executable(app src/main.cpp)
    target_link_libraries(app test)
    

    The lib's CMakeList.txt:

    project(test)
    
    cmake_minimum_required(VERSION 3.16)
    
    add_library(test src/test.cpp)
    target_include_directories(test PRIVATE include)
    
    install(TARGETS test DESTINATION lib)
    install(FILES include/test.h DESTINATION include)