Search code examples
c++visual-studio-2010dependenciescmakeheader-files

CMake - dependencies (headers) between apps/libraries in same project


I have the following project structure:

  • CMakeLists.txt
  • lib1/CMakeLists.txt and all cpp and header files of the lib
  • lib2/CMakeLists.txt and all cpp and header files of the lib
  • app/CMakeLists.txt and all cpp and header files of the app

The main CMakeLists.txt looks like:

PROJECT( ${PROJECT_NAME} )
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)

The lib1/CMakeLists.txt looks eg like (stripped):

SET(SOURCE
    file.cpp
)
SET(HEADERS
    some_lib_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )

and the one for the app looks the same except of ADD_EXECUTABLE:

SET(SOURCE
    main.cpp
)
SET(HEADERS
    some_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
ADD_EXECUTABLE( app ${SOURCE} ${HEADERS} )

I found the setup working well this way because out of this, I can generate one Visual Studio solution file which contains all those three projects. But my problem is that my app includes header files of lib1 (and also of lib2, which depends on lib1). When I do

$mkdir build
$cd build
$cmake -C ..\myproject

it generates out-of-source VS .sln file as I want it, but the app doesn't compile because it can't find the header files of lib1 (obviously).

Now I read and tried many things, like TARGET_LINK_LIBRARIES( app lib1 ) (which got the app to link with the lib1, but not solve the header include issue), and things like add_subdirectory( ../lib1 ) in various variants in the CMakeLists.txt of app (which all throwed errors that I couldn't fix), and also find_package (which I guess is the wrong approach).

So how can I solve this (I guess simple...) problem?


Solution

  • Here's one possible solution:

    Root CMakeLists.txt:

    cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
    project(${PROJECT_NAME})
    add_subdirectory(lib1)
    add_subdirectory(lib2)
    add_subdirectory(app)
    


    lib1/CMakeLists.txt:

    project(Lib1)
    add_library(lib1 lib1.cpp lib1.h)
    


    lib2/CMakeLists.txt:

    project(Lib2)
    add_library(lib2 lib2.cpp lib2.h)
    
    # Add /lib1 to #include search path
    include_directories(${Lib1_SOURCE_DIR})
    # Specify lib2's dependency on lib1
    target_link_libraries(lib2 lib1)
    


    app/CMakeLists.txt:

    project(App)
    add_executable(app main.cpp some_header.h)
    
    # Add /lib1 and /lib2 to #include search path
    include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR})
    # Specify app's dependency on lib2.
    # lib2's dependency on lib1 is automatically added.
    target_link_libraries(app lib2)
    


    There are plenty of different ways to achieve the same end result here. For a relatively small project, I'd probably just use a single CMakeLists.txt:

    cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
    project(Test)
    
    add_library(lib1 lib1/lib1.cpp lib1/lib1.h)
    add_library(lib2 lib2/lib2.cpp lib2/lib2.h)
    add_executable(app app/main.cpp app/some_header.h)
    
    include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2)
    
    target_link_libraries(lib2 lib1)
    target_link_libraries(app lib2)
    


    For further info on the relevant commands and their rationale, run:

    cmake --help-command add_subdirectory
    cmake --help-command include_directories
    cmake --help-command target_link_libraries