我有以下目录布局:
main_folder
+ static_lib1
+ executable
- “static_lib1”和“executable”都有一个完整的CMakeLists,因此可以独立生成。
- “可执行文件”依赖于“static_lib1”。它使用
find_package()
来定位“static_lib1”。 - main_folder包含一个CMakeLists,它通过
add_subdirectory
同时包含“static_lib1”和“executable”,以便一次构建整个项目。
如果我手动生成“static_lib1”,然后再生成“executable”,一切都正常。但当从主文件夹运行CMakeLists时,我得到一个错误,因为find_package
无法从“static_lib1”中找到尚未生成的库文件。
如何在保持CMakeLists文件独立的同时解决此问题(即,不将static_lib的CMakeLists与可执行文件的CMakeLists包括在一起)?
3条答案
按热度按时间wvt8vs2t1#
在可执行文件的CMakeLists.txt中,您可以检查是独立生成还是作为项目的一部分生成:
7vux5j2d2#
从基于文件的方法切换到基于目标的方法,以处理从
executable
到static_lib1
的依赖关系。发生最初的问题是因为
executable
调用find_package
来定位static_lib1
,然后static_lib1
试图通过调用find_library
用库文件的路径填充STATIC_LIB1_LIBRARY
之类的变量。executable
然后在target_link_libraries(executable ${STATIC_LIB1_LIBRARY})
调用中使用该变量的内容。这里的问题是,由于这些库文件只作为构建的一部分生成,对find_library
调用将无法找到任何内容。构建
executable
需要支持以下两种场景:1.构建单机版,其中
static_lib1
的预编译版本位于光盘上的某个位置。1.从
main_folder
生成,其中executable
和static_lib1
都是同一生成的一部分。问题中的方法支持场景1,但不支持场景2。
在两个构建版本之间使用一个目标来传递依赖关系,而不是使用一个变量。
static_lib1
的CMakeLists.txt
可能会创建一个像add_library(static_lib1 [...])
这样的库目标。在可执行文件中,我们现在只需执行target_link_libraries(executable PUBLIC static_lib1)
。这足以支持场景2。为了同时考虑到场景1,我们在
executable
的CMakeLists.txt
中查看对find_package(static_lib1)
的调用。此调用现在需要提供一个目标static_lib1
以供使用,而不是像以前那样提供一个变量。因此,我们将
static_lib1
的find脚本调整为以下行为:static_lib1
已经存在,则不需要执行任何操作,find脚本可以直接返回(这是场景2)。find_library
来定位光盘上的库文件(如之前的原始方法),然后创建一个新的导入目标:add_library(static_lib1 STATIC IMPORTED)
。然后,我们将静态库的所有相关属性配置到该目标。为了支持像MSVC这样的多配置生成器,您将需要设置像
IMPORTED_LOCATION_DEBUG
andIMPORTED_LOCATION_RELEASE
这样的配置特定属性,而不是设置IMPORTED_LOCATION
和IMPORTED_LINK_INTERFACE_LANGUAGES
。您可以让CMake生成此信息,包脚本的查找机制在内部的工作方式略有不同,但CMakeLists.txt
中的executable
代码看起来是一样的,只是简单地调用find_package(static_lib1)
。主要区别在于,此调用不会分派给手写的find脚本,而是分派给作为static_lib1
构建过程的一部分由CMake自动生成的package脚本。ryhaxcpt3#
我想我会把这个答案留给后人,因为直到最近我才寻找到这个问题的解决方案,并发现...
从CMake 3.24开始,这是可能的!
可以使用
FetchContent_Declare()
标志**OVERRIDE_FIND_PACKAGE
**重写对find_package()
的后续调用。您的
必须将
main_folder/CMakeLists.txt
中的调用替换为:对
find_package(static_lib1)
的任何调用都将为您调用FetchContent_MakeAvailable()
,实际上使其与add_subdirectory()
调用相同。您可以在CMake文档中阅读更多关于
OVERRIDE_FIND_PACKAGE
的信息。