在 CMake 中跨子目录保持文件层次结构
到目前为止,我仍然不明白为具有许多子目录的 CMake 项目执行此操作的最佳实践"是什么.
Till date I still do not really understand what the 'best practice' is for doing this for a CMake project with many subdirectories.
假设我有一个项目层次结构,每个子目录中都有源文件...
Say I have a project hierarchy as such and each subdirectory has source files in it...
--CMake Project Source dir
|-- SubD1
|-- SubSubD1
|-- SubD2
我通常要做的是分别对根目录的CMakeLists.txt中的D2和SubD1目录的CMakeLists.txt中的子目录分别进行add_subdirectory(SubD1)
和D2,同时在每个子目录中声明变量并使用 PARENT_SCOPE
使它们在根目录中可见.
What I would usually do is to do add_subdirectory(SubD1)
and respectively for D2 in the CMakeLists.txt of the root directory and recursively for the subdirectory in the CMakeLists.txt of the SubD1 directory, while declaring variables in each subdirectory and making them visible in the root directory with PARENT_SCOPE
.
这意味着如果文件 Source2.cpp
存在于 `SubSubD1' 中,我会这样做
That means if a file Source2.cpp
exists in `SubSubD1', I'd simply do
set(SUBSUBD1_SOURCES Source2.cpp PARENT_SCOPE)
并期望能够在我的 SubD1
目录中使用 SUBSUBD1_SOURCE.随后,说 Source.cpp
存在于 SubD1 中,我会这样做
and expect to be able to use SUBSUBD1_SOURCE in my SubD1
directory.
Subsequently, say Source.cpp
exists in SubD1, I would do
set(SUBD1_SOURCES ${SUBSUBD1_SOURCES} Source.cpp PARENT_SCOPE)
以便所有源都在根目录中可见.
so that all sources would be visible in root dir.
问题是当然,当变量到达根目录时,文件路径没有保留.我目前正在做的是我set
的所有源文件,我包括一个${CMAKE_CURRENT_LIST_DIR}
,使其成为
The problem is of course that the file paths aren't kept when the variables arrive at the root directory. What I'm currently doing is for all source files that I set
, I include a ${CMAKE_CURRENT_LIST_DIR}
, making it
set(SUBSUBD1_SOURCES ${CMAKE_CURRENT_LIST_DIR}/Source2.cpp PARENT_SCOPE)
和
set(SUBD1_SOURCES ${SUBSUBD1_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/Source.cpp PARENT_SCOPE)
在这种情况下,我可以说,在我的 CMake 项目的根目录中执行 add_executable(myProg SUBSUBD1_SOURCES)
.
In this case, I could then say, do add_executable(myProg SUBSUBD1_SOURCES)
in the root directory of my CMake project.
是否有更好的方法来做到这一点,然后必须始终在所有源文件前面包含一个 CMake 变量?
Are there any better ways of doing this then having to always include a CMake variable in front of all source files?
推荐答案
我以前用过 3 种方法.我通常更喜欢第一种方式,但已经根据用例使用了所有 3 种方式:
There are 3 ways I have used before. I normally prefer the 1st way, but have already used all 3 depending on the use case:
1.您直接在根 CMakeLists.txt
文件中命名源
1. You directly name the sources in your root CMakeLists.txt
file
set(
SUBD1_SOURCES
"SubD1/SubSubD1/Source2.cpp"
"SubD1/Source.cpp"
)
set(
SUBD2_SOURCES
"SubD2/Source3.cpp"
)
add_executable(myProg ${SUBD1_SOURCES} ${SUBD2_SOURCES})
2.您使用OBJECT
中间图书馆 收集/分组您??的来源
2. You use OBJECT
intermediate libraries to collect/group your sources
SubD1/SubSubD1/CMakeLists.txt:
SubD1/SubSubD1/CMakeLists.txt:
add_library(SubSubD1Objs OBJECT Source2.cpp)
SubD1/CMakeLists.txt:
SubD1/CMakeLists.txt:
add_subdirectory(SubSubD1)
add_library(SubD1Objs OBJECT Source.cpp)
CMakeLists.txt:
CMakeLists.txt:
add_executable(myProg $<TARGET_OBJECTS:SubSubD1Objs> $<TARGET_OBJECTS:SubD1Objs>)
3.您编写自己的function()
来收集数据(并添加前缀)
3. You write your own function()
to collect the data (and do the prefixing)
CMakeLists.txt:
CMakeLists.txt:
function(my_collect_sources)
foreach(_source IN ITEMS ${ARGN})
if (IS_ABSOLUTE "${_source}")
set(source_abs "${_source}")
else()
get_filename_component(_source_abs "${_source}" ABSOLUTE)
endif()
set_property(GLOBAL APPEND PROPERTY GlobalSourceList "${_source_abs}")
endforeach()
endfunction(my_collect_sources)
add_subdirectory(SubD1)
#add_subdirectory(SubD2)
get_property(MY_SOURCES GLOBAL PROPERTY GlobalSourceList)
add_executable(myProg ${MY_SOURCES})
SubD1/CMakeLists.txt:
SubD1/CMakeLists.txt:
add_subdirectory(SubSubD1)
my_collect_sources(Source.cpp)
SubD1/SubSubD1/CMakeLists.txt:
SubD1/SubSubD1/CMakeLists.txt:
my_collect_sources(Source2.cpp)
相关文章