让我通过一个具体的例子来演示一个可能的解决方案:
The myapp
project
我们有一个可执行的目标myapp
。我们将它与mylib
,它是在自己的构建树中构建的。在里面CMakeLists.txt
of myapp
我们找到并指定mylib
作为一个依赖项myexe
:
find_package(mylib REQUIRED)
...
add_executable(myexe ...)
target_link_libraries(myexe mylib::mylib)
我们来看看如何设置mylib
和构建myexe
使这项工作成功。
The mylib
project
的目录布局mylib
:
mylib
- CMakeLists.txt
- mylib.c
+ include
- mylib.h # single public header
In the CMakeLists.txt
of mylib
我们需要创建目标并指定其源文件:
add_library(mylib mylib.c include/mylib.h)
公共标头mylib.h
将被包含为#include "mylib.h"
两者均由mylib
和客户mylib
:
-
mylib
本身和其他内置目标mylib
的CMake项目(例如测试)需要找到include/mylib.h
来自mylib
源树
- 的客户
mylib
在自己的项目中构建(例如myexe
)需要找到include/mylib.h
在其安装位置
CMake 允许我们指定两个包含路径mylib
:
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
我们正在使用PUBLIC
此处的选项,因为在公共接口上需要此标头mylib
. Use PRIVATE
对于包含内部路径mylib
.
The INSTALL_INTERFACE
指定相对于安装根目录的路径,即CMAKE_INSTALL_PREFIX
。要实际安装公共标头:
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h")
我们还需要安装库本身以及所谓的配置模块和相关文件。配置模块是将由消费项目使用的文件,例如myapp
找到mylib
并获取与其链接所需的所有参数。它类似于pkg 配置's .pc
files.
我们需要两个相关的install
命令。第一个:
install(TARGETS mylib
EXPORT mylib-targets
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
覆盖静态库的所有标准安装位置所需的目标列表,dll
's and 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
(or mylibd.lib
在 Windows 上)。生成的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
or Visual Studio
,您需要在构建时指定配置:
cmake -DCMAKE_INSTALL_PREFIX=$PWD/../out ../mylib
cmake --build . --target install --config Release
参考
您可以克隆和构建这个存储库 https://github.com/tamaskenez/stackoverflow-cmake-find-link-example其中包含mylib
and myexe
项目(在 Windows 和 Linux 上测试)。
查看CMake 文档 http://www.cmake.org/cmake/help/v3.3。最重要的相关命令是:
- 添加库 http://www.cmake.org/cmake/help/v3.3/command/add_library.html
- 目标链接库 http://www.cmake.org/cmake/help/v3.3/command/target_link_libraries.html
- 查找包 http://www.cmake.org/cmake/help/v3.3/command/find_package.html
- install http://www.cmake.org/cmake/help/v3.3/command/install.html
- 目标包含目录 http://www.cmake.org/cmake/help/v3.3/command/target_include_directories.html
- 目标编译定义 http://www.cmake.org/cmake/help/v3.3/command/target_compile_definitions.html
以及两篇详细的文章:
- 构建系统 http://www.cmake.org/cmake/help/v3.3/manual/cmake-buildsystem.7.html
- Packages http://www.cmake.org/cmake/help/v3.3/manual/cmake-packages.7.html