CMake 的 FetchContent 与 Makefile 构建的依赖项
Posted
技术标签:
【中文标题】CMake 的 FetchContent 与 Makefile 构建的依赖项【英文标题】:CMake's FetchContent with Makefile-built dependency 【发布时间】:2019-10-31 13:33:05 【问题描述】:我当前的项目需要一个使用 Makefile 构建的库。我想在我的项目编译期间编译这个库;此功能是 FetchContent 的主要卖点,它与 CMake 依赖项配合得非常好。不过,我无法让它与 Makefile 一起工作,也找不到有关如何做到这一点的示例。
FetchContent_Declare(
make_lib
URL http://url/library_code.tar.gz
BUILD_COMMAND $CMAKE_COMMAND -E env make -j 8
BUILD_IN_SOURCE true
BINARY_DIR ""
)
FetchContent_GetProperties(make_lib)
if (NOT make_lib_POPULATED)
FetchContent_Populate(make_lib)
# here I would like to declare imported libraries:
add_library(make_lib::libA STATIC IMPORTED GLOBAL)
target_include_directories(make_lib::libA INTERFACE $make_lib_SOURCE_DIR/include)
set_property(TARGET make_lib::libA PROPERTY IMPORTED_LOCATION <path to "to be built" lib>)
endif()
make
的“编译时”执行是否可能?
如果是这样,它可以并行吗?
是否可以使用依赖编译库声明导入的目标?
【问题讨论】:
"make 的“编译时”执行是否完全可能"...这是什么意思?无论如何,运行make
通常被认为是编译时,所以我不确定为什么它不会在你的情况下。您能否更具体地说明何时您希望make
为该库运行?
使用 CMake 时,脚本通常可以在两个不同的阶段执行,配置时间(运行 make 命令时)或编译时间(执行生成器时...对于 case ninja,或 make) .上面的例子有一个嵌套的makefile,可以在任何时候执行,但是我很难让它在后一种情况下工作。如果我没有正确地提出问题,我很抱歉。但是你的回答并没有完全解决我的疑惑。
好吧,这更有意义。我最初并没有完全理解你的问题。我更新了我的答案,详细介绍了一种可能的解决方案。希望这会有所帮助!
【参考方案1】:
FetchContent_*
命令只是获取来自特定外部资源的内容或元数据,并填充 CMake 变量;它们实际上并不执行任何配置、构建或安装步骤。因此,在调用FetchContent_Declare()
时,与这些步骤相关的任何选项都会显式忽略。这包括以下选项:
CONFIGURE_COMMAND
BUILD_COMMAND
INSTALL_COMMAND
TEST_COMMAND
来自FetchContent
文档:
此模块允许在配置时通过
ExternalProject
模块支持的任何方法填充内容。ExternalProject_Add()
在构建时下载,FetchContent
模块使内容立即可用,允许配置步骤在命令中使用内容,如add_subdirectory()
、include()
或file()
操作。
这不适用于您的用例,因为像 add_subdirectory()
这样的调用会失败,因为外部库中没有 CMake 文件。
正如this 帖子中所述,ExternalProject_Add()
在您的情况下更有意义。您的调用可能如下所示:
ExternalProject_Add(make_lib
DOWNLOAD_DIR $CMAKE_CURRENT_BINARY_DIR
URL http://url/library_code.tar.gz
UPDATE_COMMAND ""
SOURCE_DIR $make_lib_SOURCE_DIR
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND "make -j8"
INSTALL_COMMAND "$make_lib_install_commands"
)
add_library(make_lib_libA STATIC IMPORTED GLOBAL)
set_property(TARGET make_lib_libA
PROPERTY IMPORTED_LOCATION
$make_lib_SOURCE_DIR/path/to/make_lib_libA.a
)
add_dependencies(myOtherLib make_lib)
注意,这里的BUILD_COMMAND
不会被忽略,而是会在编译时运行make -j8
。您还应该能够将导入的库声明为您的代码布局。但重要的是,请记住调用add_dependencies()
,它告诉CMake 你的make_lib
被另一个目标使用;否则,make-lib
将不会构建。
调用ExternalProject_Add()
后,可以使用ExternalProject_Get_Property()
查询外部项目目标的信息。链接示例显示了如何获取项目的源目录,这对于获取构建库的位置很有用。
【讨论】:
您能否更简洁地说明它的外观?我的示例编写了一个被忽略的 BUILD_COMMAND,并且该库没有配置、测试或安装。您仍然没有解释如何声明您刚刚下载的内容的导入目标。而且我完全不明白 cmake 如何将作业数量转发到嵌套的 makefile,对于初学者来说,我使用 ninja 来构建。以上是关于CMake 的 FetchContent 与 Makefile 构建的依赖项的主要内容,如果未能解决你的问题,请参考以下文章