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

f4t66c6m  于 2023-08-05  发布在  其他
关注(0)|答案(4)|浏览(181)

我需要帮助写一个好的CMakeLists.txt的C++项目。
我寻找答案,但我找到了任何东西。这是我的项目结构:

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?
如果你能帮忙的话,我将不胜感激。:)

a6b3iqyw

a6b3iqyw1#

您需要使用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包含目录。

gg0vcinb

gg0vcinb2#

您的cmake项目模板看起来很好并且是自包含的。首先,我假设GAITPARAMS_SRCS应该是PROJEXEC_SRCS,它当前指向proj_exec.cc,包含一个main()方法。(如果你要管理一个SRCS列表,注意不要在列表的顶部添加源文件,add_executable期望main函数在第一个条目中)
其次,问题出在你的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


这使您可以在文件夹名中包含标题(更不用说防止名称冲突了)。就像这样:

#include <ProjLib/proj_lib.h>


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

qxgroojn

qxgroojn3#

以下所有选项都有效,但最佳选项在rubenvb's answer中进行了说明。
你至少有三个选择:
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_directoriesget_target_property
其他注意事项:

  • 要么使用include_directories,要么使用target_include_directories,不要同时使用。
  • 通常不需要将源目录作为包含目录,即可以删除include_directories("${PROJLIB_SOURCE_DIR}")include_directories("${PROJEXEC_SOURCE_DIR}")
q35jwt9p

q35jwt9p4#

在设置目标的属性时,一个关键点是理解target_include_directories命令及其关键字PRIVATEINTERFACEPUBLICPRIVATE表示只有目标需要include目录。INTERFACE表示当其他目标想要链接这个目标时需要包含目录,cmake将自动处理它。PUBLIC意味着这个目标和依赖于它的其他目标都必须将这个目录压缩到它的搜索路径中。所有这些都是由你的代码决定的。

相关问题