Search code examples
c++cmakemultiple-projects

CMake: Set up Multiple Projects and Dependencies Between Them


I need help with writing good CMakeLists.txt files for C++ projects.

This is the structure of my projects:

MainProj
|  ProjLib/
|  |  include/
|  |  |  proj_lib.h
|  |  src/
|  |  |  proj_lib.cc
|  |  CMakeLists.txt
|  ProjExec/
|  |  include/
|  |  |  proj_exec.h
|  |  src/
|  |  |  proj_exec.cc
|  |  CMakeLists.txt
|  CMakeLists.txt

MainProj CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project(MainProj CXX)

# enable C and C++ language
enable_language(C CXX)

# Add sub-directories
add_subdirectory(ProjLib)
add_subdirectory(ProjExec)

ProjLib CMakeLists.txt:

set (PROJLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set (PROJLIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
 
set(PROJLIB_SRCS 
    ${CMAKE_CURRENT_SOURCE_DIR}/src/proj_lib.cc
)
 
include_directories("${PROJLIB_SOURCE_DIR}")
include_directories("${PROJLIB_INCLUDE_DIR}")
 
add_library(ProjLib SHARED ${PROJLIB_SRCS} ${PROJLIB_INCLUDE_DIR})

target_include_directories (ProjLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

ProjExec CMakeLists.txt:

set (PROJEXEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set (PROJEXEC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

set(PROJEXEC_SRCS 
    ${PROJEXEC_SOURCE_DIR}/proj_exec.cc
)
 
include_directories("${PROJEXEC_SOURCE_DIR}")
include_directories("${PROJEXEC_INCLUDE_DIR}")

add_executable(ProjExec ${PROJEXEC_SRCS})

target_link_libraries (ProjExec LINK_PUBLIC ProjLib)

proj_exec.cc:

#include "proj_lib.h"
...

And it doesn't found proj_lib.h in proj_exec.cc file. Do I need some additional entries in some cmake?


Solution

  • You need to make use of the CMake targets and their properties:

    MainProj/CMakeLists.txt:

    cmake_minimum_required(VERSION 2.8)
    project(MainProj)
    
    # Add sub-directories
    add_subdirectory(ProjLib)
    add_subdirectory(ProjExec)
    

    ProjLib/CMakeLists.txt

    add_library(ProjLib SHARED src/proj_lib.cc)
    target_include_directories(ProjLib PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
    

    ProjExec/CMakeLists.txt

    add_executable(ProjExec src/proj_exec.cc)
    target_include_directories(ProjExec PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include)
    target_link_libraries(ProjExec ProjLib)
    

    target_link_libraries makes sure that when building a target, its dependencies' PUBLIC and INTERFACE include directories will be used appropriately.