假设我有一个由n不同项目组成的分层CMake项目:
CMakeLists.txt
proj-1/CMakeLists.txt
proj-2/CMakeLists.txt
(...)
proj-n/CMakeLists.txt显然,每个项目也会有源文件。
我会确保将所有感兴趣的命令都添加到根CMakeLists.txt文件中--比如CMAKE_CXX_STANDARD、enable_testing()、add_compile_options()等。如果我理解正确的话,根CMakeLists.txt文件中包含的任何选项都会应用于所有子CMakeLists.txt文件--如果我说错了,请纠正我,因为我认为这是一种行为。根CMakeLists.txt还包含对应于每个X = 1,...,n的add_subdirectory(proj-X)语句。
不管怎么说。假设,由于某种原因,我只想构建一个proj-X文件夹,比如proj-1。也许构建在其他项目中中断了,或者我需要修复proj-1上的错误,它不依赖于其他项目,构建所有项目将永远花费时间。
重点是:我希望在proj-1/CMakeLists.txt上运行cmake,而不是在根CMakeLists.txt文件上运行,但我希望确保proj-1的构建方式与在根CMakeLists.txt文件上运行cmake的构建方式完全相同。这是一个问题,因为根CMakeLists.txt包含子CMakeLists.txt在常规情况下应该“继承”的语句,在这种情况下,它是从根构建的,而在这个场景中,我是直接从proj-1/CMakeLists.txt构建的(在这个场景中,根CMakeLists.txt文件不在这个场景中)。
据我所知,一种可能性是将根CMakeLists.txt文件中的所有选项复制到每个其他proj-X/CMakeLists.txt文件中。当然,这是一个黑客和维护的噩梦,但我认为它会工作。
还有其他可能的解决方案吗?比如说,我可以创建一个包含所有公共选项的文件并将其保存到根目录,然后在每个proj-X/CMakeLists.txt文件中执行#include的CMake等效项吗?当从根目录开始构建时,运行相同的命令两次(一次在根CMakeLists.txt上,另一次在proj-X/CMakeLists.txt文件上)会不会出现问题?
发布于 2021-04-07 15:30:07
您可能需要重新处理某些CMakeLists.txt文件。
我推荐看幻灯片(幻灯片可用here)。
它的要点是,您的所有项目都应该提供构建或编译所需的一切,本质上是构建需求和使用需求。要以可维护和可伸缩的方式实现这一点,您必须远离变量和设置全局选项(add_compile_options、include_directories等),而是专注于目标(target_compile_options、target_include_directories等)。
因此,在您的例子中,proj-1/CMakeLists.txt将提供一个目标(让我们称之为proj::proj1)来设置适当的PUBLIC和INTERFACE选项(我所说的选项指的是所需的编译器特性、依赖项、包含目录等)。
一个抽象的例子:
project(proj1)
add_library(proj1 src.cpp)
# This are private include files, whoever uses this library does not need them
target_include_directories(proj1 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
# These are public, needed both by this target and by whoever uses it.
target_include_directories(proj1 PUBLIC
# This is used when building the target
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include>
# This is used when the target is installed
$<INSTALL_INTERFACE:include>)
# Instead of asking directly for a language standard we ask for a compiler feature. We make this public so whoever depends on this target knows they also need this feature.
target_compile_features(proj1 PUBLIC cxx_strong_enums)
# As above, but this is needed only by this target during the build.
target_compile_features(proe1 PRIVATE cxx_lambdas)
# Add an alias, users can use target_link_libraries(target PRIVATE|PUBLIC proj::proj1) to add this target as a dependency (this will propagate all the PUBLIC include paths, compile options, compile features, dependencies, etc.
add_library(proj::proj1 ALIAS proj1)这是高度抽象的,这取决于您在构建脚本中实际在做什么,很难给出比Daniel Pfeifer更好的解释,所以我建议您观看他的演讲或至少阅读幻灯片。它将使您的构建脚本更易于编写、阅读和使用。
另一个很棒的资源是this site。
https://stackoverflow.com/questions/66978505
复制相似问题