【CMake系列】07-export与find
为了将我们的库文件更方便地提供给他人使用,cmake 提供了一种方式,通过查找 .cmake 文件,将库导入项目中。
本节学习的内容,就是将我们的库导出一个 xxx.cmake 文件,以及 在项目中导入
本专栏的实践代码全部放在 github 上,欢迎 star !!!
如有问题,欢迎留言、或加群【392784757】交流
xxxConfig.cmake 文件是一个 CMake 配置文件用于在项目中查找和使用某个库。目的是方便在其 CMake 构建系统中找到并正确配置该库。
cmake_minimum_required(VERSION 3.20)
project(export_my_package)
file(WRITE include/slib.h "void slib();")
file(WRITE slib.cpp [=[
#include <iostream>
#include "slib.h"
void slib()
{
std::cout<<"in slib func\n" <<std::endl;
}
]=])
add_library(slib STATIC slib.cpp)
# 导出头文件; file glob 加入所有 头文件
set_target_properties(slib PROPERTIES PUBLIC_HEADER include/slib.h)
设置 头文件include路径,这里的设置有两个层面
如果仅这样设置
target_include_directories(slib PUBLIC include) # PUBLIC 第三方调用时 也可以导入头文件
会在构建时报错
#[[
Target "slib" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"E:/my-github-repos/learn-cmake-together/ref_course/506export_my_package/include"
which is prefixed in the source directory.
]]
提示 INTERFACE_INCLUDE_DIRECTORIES 包含了一个源目录路径。这个路径是绝对路径,而不是相对于安装目录的相对路径。当你尝试导出或安装这个目标时,绝对路径可能会导致错误,因为在安装后的环境中,这个路径可能不存在。
因此我们需要对这个include 路径进行 分别设置,一个是 构建时,一个是导出时【也就是他人使用时 用到的路径】
通过 生成表达式 我们可以根据 是在哪个行为 进而设置路径
# 路径被两次引用 1 编译slib 库时 2 export 写入config时
target_include_directories(slib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # 仅在编译时有效
$<INSTALL_INTERFACE:include> # 只在install 时有值 绝对路径/include
)
安装导出
在安装过程中,通过添加EXPORT 这一指令,将我们的库配置文件导出
install(TARGETS slib
EXPORT slib # 导出
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
install(EXPORT slib FILE slibConfig.cmake DESTINATION config)
导出文件的默认名称
#
# slibConfig.cmake
构建指令
cmake -B build -S .
cmake --build build
cmake --install build --prefix=out # --config=Debug # windows下需要添加--congig
执行后,结构如下
在config 目录下,有库对应的 xxx.cmake 文件,也就是我们后续导入库 需要找到的文件
导入
cmake_minimum_required(VERSION 3.20)
project(find_my_package)
file(WRITE main.cpp [=[
#include "slib.h"
#include <iostream>
using namespace std;
int main()
{
cout<<"in main"<<endl;
slib();
return 0;
}
]=])
find_package(slib)
message("slib_found = ${slib_FOUND}")
if(slib_FOUND)
message("find slib success!")
endif()
add_executable(main main.cpp)
target_link_libraries(main slib)
get_target_property(inc slib INTERFACE_INCLUDE_DIRECTORIES)
message("INTERFACE_INCLUDE_DIRECTORIES = ${inc}")
执行后提示 找不到
CMake Warning at CMakeLists.txt:21 (find_package):
By not providing "Findslib.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "slib", but
CMake did not find one.
Could not find a package configuration file provided by "slib" with any of
the following names:
slibConfig.cmake
slib-config.cmake
Add the installation prefix of "slib" to CMAKE_PREFIX_PATH or set
"slib_DIR" to a directory containing one of the above files. If "slib"
provides a separate development package or SDK, be sure it has been
installed.
通过提示,我们看到添加slib路径的方法
- 添加 slib 安装路径 到 CMAKE_PREFIX_PATH
- 设置 slib_DIR 变量 包含 xxx.cmake 路径
set(slib_DIR "替换包含 slibConfig.cmake 所在的路径")
然后重新构建,执行
导入成功
版本问题
相关的库可以设置版本,设定相应的限制,只导入指定要求的版本,这样也需要在导出配置时,进行一定的设置
version 的变量值 可以预先设定 + -Dversion 传入的方式实现
install(EXPORT slib FILE slibConfig.cmake DESTINATION config/slib-${version})
# <packagename>Config.cmake
# slibConfig.cmake
# 写入版本信息 slibConfigVersion.cmake
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_INSTALL_PREFIX}/config/slib-${version}/slibConfigVersion.cmake
VERSION ${version}
COMPATIBILITY SameMajorVersion #版本兼容问题 cmake.org.cn
)