【发布时间】:2015-07-21 11:19:28
【问题描述】:
您有一个启用 CMake 的库项目。您需要在另一个库或可执行文件中使用它。如何使用 CMake 查找并链接到库?您可能有以下偏好:
- 尽可能少地编写样板代码
- 将链接库的内部细节与消费目标解耦
理想情况下,该库的用法应如下所示:
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)
【问题讨论】:
标签: cmake
您有一个启用 CMake 的库项目。您需要在另一个库或可执行文件中使用它。如何使用 CMake 查找并链接到库?您可能有以下偏好:
理想情况下,该库的用法应如下所示:
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)
【问题讨论】:
标签: cmake
让我通过一个具体的例子来演示一个可能的解决方案:
myapp 项目我们有一个可执行目标myapp。我们将它与mylib 链接起来,它是在它自己的构建树中构建的。在myapp 的CMakeLists.txt 中,我们找到并指定mylib 作为myexe 的依赖项:
find_package(mylib REQUIRED)
...
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)
让我们看看如何设置 mylib 和构建 myexe 来完成这项工作。
mylib 项目mylib的目录布局:
mylib
- CMakeLists.txt
- mylib.c
+ include
- mylib.h # single public header
在mylib 的CMakeLists.txt 中,我们需要创建目标并指定其源文件:
add_library(mylib mylib.c include/mylib.h)
mylib 和mylib 的客户都将公共标头mylib.h 包含为#include "mylib.h":
mylib本身和mylib的CMake项目中构建的其他目标(例如测试)需要从mylib源树中找到include/mylib.h
mylib 的客户在自己的项目中构建(如myexe)需要在其安装位置找到include/mylib.h
CMake 允许我们为 mylib 指定两个包含路径:
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
我们在这里使用PUBLIC 选项,因为mylib 的公共接口上需要此标头。使用PRIVATE 包含mylib 内部的路径。
INSTALL_INTERFACE 指定相对于安装根目录的路径,即CMAKE_INSTALL_PREFIX。实际安装公共标头:
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h")
我们还需要安装库本身以及所谓的 config-module 和相关文件。 config-module 是消费项目将使用的文件,例如 myapp 以查找 mylib 并获取与其链接所需的所有参数。它类似于 pkg-config 的 .pc 文件。
我们需要两个相关的install 命令。第一个:
install(TARGETS mylib
EXPORT mylib-targets
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
包含静态库的所有标准安装位置所需的目标列表,dll 和 so。如果您确定您的库将专门构建为静态库,则可以使用单个 DESTINATION lib。
有趣的部分是EXPORT 选项。它将目标列表(目前只有mylib)分配给标识符mylib-targets。此标识符将在下一个命令中用于生成和安装一些特殊文件,这些文件使 find_package(mylib) 在消费项目中工作:
install(EXPORT mylib-targets
NAMESPACE mylib::
FILE mylib-config.cmake
DESTINATION lib/cmake/mylib)
此命令生成多个文件:
mylib-config.cmake
文件将安装到${CMAKE_INSTALL_PREFIX}/lib/cmake/mylib,这是find_package(mylib) 命令将搜索mylib-config.cmake 的众多标准位置之一。
mylib
我们需要在变量CMAKE_INSTALL_PREFIX中指定安装位置:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
并构建和安装库:
cmake --build . --target install
myexe
myexe 需要知道在哪里寻找mylib。变量CMAKE_PREFIX_PATH 可以是路径列表。我们需要指定之前的安装位置:
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=$PWD/../out ../myexe
cmake --build .
通常我们需要构建多个配置(Debug、Release)。一个关键问题是指定与配置相关的文件名或安装位置。例如,您可以为库项目设置DEBUG_POSTFIX 属性的默认值:
set(CMAKE_DEBUG_POSTFIX d)
mylib 库文件的调试版本将命名为 libmylibd.lib(或在 Windows 上命名为 mylibd.lib)。生成的EXPORT 文件将包含修改后的文件名。
如果您使用 makefile 样式的 CMake 生成器,您可以通过设置 CMAKE_BUILD_TYPE 变量来控制构建配置:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install
您可能需要为每个配置使用单独的构建目录,或者您可以重复使用相同的构建目录。在这种情况下,为了安全起见,最好在构建之前明确清理:
cmake --build . --target install --clean-first
如果您使用的是多配置 IDE 生成器,例如 Xcode 或 Visual Studio,则需要在构建时指定配置:
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install --config Release
您可以克隆和构建包含mylib 和myexe 项目的this repository(在Windows 和Linux 上测试)。
查看CMake documentation。最重要的相关命令是:
还有两篇详细的文章:
【讨论】: