cmake:设置多个项目和它们之间的依赖关系
cmake: setup multiple projects and dependiencies between them
我需要帮助为 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
主项目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 中添加一些额外的条目?
如有任何帮助,我们将不胜感激。 :)
您的 cmake 项目模板看起来不错 self-contained。首先,我假设 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 文件夹完全相同)并在其中添加您的 headers 。像这样:
MainProj
| ProjLib/
| | include/
| | | ProjLib/
| | | | proj_lib.h
| | src/
| | | proj_lib.cc
| | CMakeLists.txt
这使您可以将 headers 包含在文件夹名称中(更不用说防止名称冲突了。)。像这样:
#include <ProjLib/proj_lib.h>
并配置您的 CMakeLists.txt 文件以匹配模式。
以下所有内容均有效,但最佳选项在 中有解释。
您至少有 3 个选项:
1) 在ProjExec/CMakeLists.txt 中添加以下行:
target_include_directories (ProjExec PUBLIC ${CMAKE_SOURCE_DIR}/ProjLib/include)
2) 您可以通过添加 CACHE INTERNAL
关键字
来扩展变量 PROJLIB_INCLUDE_DIR
的可见性
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_directories and get_target_property。
其他说明:
- 使用
include_directories
或 target_include_directories
,不能同时使用。
- 您通常不需要将源目录作为包含目录,即您可以删除
include_directories("${PROJLIB_SOURCE_DIR}")
和 include_directories("${PROJEXEC_SOURCE_DIR}")
您需要使用 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 包含目录。
我需要帮助为 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
主项目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 中添加一些额外的条目?
如有任何帮助,我们将不胜感激。 :)
您的 cmake 项目模板看起来不错 self-contained。首先,我假设 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 文件夹完全相同)并在其中添加您的 headers 。像这样:
MainProj
| ProjLib/
| | include/
| | | ProjLib/
| | | | proj_lib.h
| | src/
| | | proj_lib.cc
| | CMakeLists.txt
这使您可以将 headers 包含在文件夹名称中(更不用说防止名称冲突了。)。像这样:
#include <ProjLib/proj_lib.h>
并配置您的 CMakeLists.txt 文件以匹配模式。
以下所有内容均有效,但最佳选项在
您至少有 3 个选项:
1) 在ProjExec/CMakeLists.txt 中添加以下行:
target_include_directories (ProjExec PUBLIC ${CMAKE_SOURCE_DIR}/ProjLib/include)
2) 您可以通过添加 CACHE INTERNAL
关键字
PROJLIB_INCLUDE_DIR
的可见性
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_directories and get_target_property。
其他说明:
- 使用
include_directories
或target_include_directories
,不能同时使用。 - 您通常不需要将源目录作为包含目录,即您可以删除
include_directories("${PROJLIB_SOURCE_DIR}")
和include_directories("${PROJEXEC_SOURCE_DIR}")
您需要使用 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 包含目录。