我还推荐对于简单项目使用FetchContent。
然而,有时需要更多对下载的库进行控制。
这时候ExternalProject很有用,因为它有许多定制选项。
关键在于理解你要下载的库。阅读它的CMakeLists.txt文件以了解如何修改安装目录,或者在构建或安装之前��要哪些配置。
以下示例将下载ZeroMQ(也称为zmq)。
该库需要在库内部运行一个bash脚本来正确配置事务,并且它还有一些选项可用于自定义安装。
我个人不喜欢标准的文件保存位置,也不需要将库安装到我的系统中。所以我想将其安装在我的项目中。因此,您可以按照自己的方式指定目录。
在我的项目中,我覆盖了CMAKE_INSTALL_PREFIX和CMAKE_INCLUDE_PREFIX以指向我希望文件存在的文件夹。
set(ZMQ_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
set(ZMQ_DIR "${CMAKE_CURRENT_BINARY_DIR}/ZeroMQ")
set(ZMQ_SRC_DIR "${ZMQ_DIR}/src")
set(ZMQ_INSTALL_INCLUDEDIR "${CMAKE_INCLUDE_PREFIX}/ZeroMQ")
include(ExternalProject)
ExternalProject_Add(ZeroMQ
URL https://github.com/zeromq/libzmq/releases/download/v4.3.4/zeromq-4.3.4.tar.gz
PREFIX "${ZMQ_DIR}/prefix"
TMP_DIR "${ZMQ_DIR}/tmp"
STAMP_DIR "${ZMQ_DIR}/stamp"
DOWNLOAD_DIR "${ZMQ_DIR}"
SOURCE_DIR "${ZMQ_SRC_DIR}"
BINARY_DIR "${ZMQ_DIR}/build"
CONFIGURE_COMMAND cd ${ZMQ_SRC_DIR} && ./configure --with-pic --prefix=${ZMQ_INSTALL_DIR}
BUILD_COMMAND ""
INSTALL_COMMAND cd ${ZMQ_SRC_DIR} && $(MAKE) install
)
请注意,ZeroMQ并不是实际的库目标,它只是我为ExternalProject目标选择的一个名称。库目标应该是zmq。因此,库文件应该是libzmq.so。
在构建或安装之后,您的主目标需要显示它依赖于外部库,以便按正确的顺序构建事物。
因此,在您的目标所在的CMakeLists.txt中(或任何父级CMakeLists.txt中),您需要添加以下内容:
include_directories("${CMAKE_INCLUDE_PREFIX}/ZeroMQ")
add_dependencies(your_target ZeroMQ)
target_link_libraries(your_target zmq)
如果你需要下载另一个依赖于zmq的外部库,你可以在ExternalProject_Add中添加一个DEPENDS参数。
ExternalProject_Add(
cppzmqDownload
URL https://github.com/zeromq/cppzmq/archive/refs/tags/v4.10.0.tar.gz
DEPENDS ZeroMQ
CMAKE_ARGS
-DCMAKE_MODULE_PATH:PATH=${CMAKE_INSTALL_PREFIX}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}
-DCMAKE_INSTALL_INCLUDEDIR:PATH=${CMAKE_INCLUDE_PREFIX}/cppzmq
-DCPPZMQ_BUILD_TESTS=OFF
-DPC_LIBZMQ_INCLUDE_DIRS=${ZMQ_INSTALL_INCLUDEDIR}
-DPC_LIBZMQ_LIBRARY_DIRS=${CMAKE_LIB_PREFIX}
)
我希望这能帮助到某人,尽管这是一个旧帖子。
ExternalProject_Add
的行为就像add_subdirectory
并公开所有目标,那将是很好的。你上面描述的解决方案可能仍然是最干净的。 - mirkokieferExternalProject
包含一些外部项目提供了哪些优势。是一致性更好,还是更加规范,或者其他原因?我肯定我在这里缺少一些基本的东西。 - Fraser