cmake:设置多个项目和它们之间的依赖关系

时间:2016-10-24 20:50:57

标签: c++ cmake multiple-projects

我需要帮助为C ++项目编写一个好的CMakeLists.txt。

我找了答案,但我发现了什么。 这是我项目的结构:

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"
...

并没有在proj_exec.cc文件中找到proj_lib.h。 如果我在某些cmake中需要一些额外的条目?

任何帮助将不胜感激。 :)

3 个答案:

答案 0 :(得分:14)

您需要使用CMake目标及其属性:

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确保在构建目标时,依赖性' PUBLIC和INTERFACE包括目录将被适当使用。

答案 1 :(得分:1)

您的cmake项目模板看起来很好并且自包含。首先,我假设GAITPARAMS_SRCS应该是PROJEXEC_SRCS,当前指向proj_exec.cc包含main()方法。 (如果您要管理SRCS列表,请注意不要在列表顶部添加源文件,add_executable期望主函数位于第一个条目中)

其次,问题出在ProjLib/CMakeLists.txt。尝试使用以下代码替换target_include_directories来电:

target_include_directories (ProjLib PUBLIC ${PROJLIB_INCLUDE_DIR})

当应用target_link_libraries命令时,这会将包含目录信息传播到ProjExec。如果你不想这样做,我猜你可以通过#include <include/ProjLib.h>访问,但这只是令人困惑。我的建议是在include文件夹中添加另一个文件夹(与cmake文件夹完全相同)并在其中添加标题。像这样:

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

这允许您使用foldername包含标头(更不用说防止名称冲突了。)。像这样:

#include <ProjLib/proj_lib.h>

并配置您的CMakeLists.txt文件以匹配模式。

答案 2 :(得分:-1)

以下所有内容均有效,但rubenvb's answer中解释了最佳选项。

您至少有3个选项:

1)在ProjExec / CMakeLists.txt中添加以下行:

 target_include_directories (ProjExec PUBLIC ${CMAKE_SOURCE_DIR}/ProjLib/include)

2)您可以通过添加PROJLIB_INCLUDE_DIR关键字来扩展变量CACHE INTERNAL的可见性

 set(PROJLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "")

然后在ProjExec / CMakeLists.txt中使用它:

 target_include_directories (ProjExec PUBLIC ${PROJLIB_INCLUDE_DIR})

请参阅How to set the global variable in a function for cmake?
当然,ProjLib必须位于主CMakeLists.txt文件的add_subdirectory序列中。

3)我无法测试这个。如果你在ProjLib的CMakeLists.txt中使用这一行:

 target_include_directories (ProjLib PUBLIC ${PROJLIB_INCLUDE_DIR})

然后在ProjExec的CMakeLists.txt中,您可以提取属性INTERFACE_INCLUDE_DIRECTORIES,并使用它:

 get_target_property(ProjLib PROJLIB_INCLUDE_DIR INTERFACE_INCLUDE_DIRECTORIES) #Do not use anymore CACHE INTERNAL (Point 2)
 target_include_directories (ProjExec PUBLIC ${PROJLIB_INCLUDE_DIR}) #or PRIVATE

这两行可以使用cmake-generator-expressions(未经测试)压缩为一个:

target_include_directories (ProjExec PUBLIC $<TARGET_PROPERTY:ProjLib,INTERFACE_INCLUDE_DIRECTORIES>) #or PRIVATE

另请参阅target_include_directoriesget_target_property

<小时/> 其他说明:

  • 使用include_directoriestarget_include_directories,而不是两者。
  • 您通常不需要将源目录作为包含目录,即您可以删除include_directories("${PROJLIB_SOURCE_DIR}")include_directories("${PROJEXEC_SOURCE_DIR}")