文章目录
1.构建自己xxxConfig.cmake
构建自己的xxxConfig.cmake,可以让第三方人员通过find_package找到并进行使用。
1.1.文件架构
整个文件的架构如下所示:
├── CMakeLists.txt # cmake构建脚本
├── include # 库的头文件
│ └── plus.h
├── PLUSConfig.cmake.in # 用于生成 xxxConfig.cmake
└── src # 库的源文件
└── plus.cpp
其中plus.cpp的作用是将两个整数进行求和,其内容如下;
#include "plus.h"
int plus(int a, int b){
return a+b;
}
构建一个库,该库会提供上述的函数plus供第三方使用
1.2.configure_package_config_file
该命令用于生成xxxCionfig.cmake文件的,其使用方式如下:
configure_package_config_file(
<input>
<output>
INSTALL_DESTINATION <path>
[PATH_VARS <var1> <var2> ... <varN>]
[NO_SET_AND_CHECK_MACRO]
[NO_CHECK_REQUIRED_COMPONENTS_MACRO]
[INSTALL_PREFIX <path>]
)
inpu
t:文件名,一般为xxxConfig.cmake.in
文件,需要自己提供output
:文件名,一般为xxConfig.cmake
文件。其会通过input
中的文件进行生成INSTALL_DESTINATION
:改参数后跟绝对或相对路径,表示output
中的文件在install的时候会被装载到那个位置。如果使用相对路径,则其相对于INSTALL_PREFIX
所表示的路径PATH_VARS
:其后跟这变量的名字,这些变量需要在xxxConfig.cmake.in
文件中出现。例如变量名A
,则在xxxConfig.cmake.in
中要以@PACKAGE_A@
的形式出现。这些变量的作用一般是在xxxConfig.cmake.in
生成xxxConfig.cmake
的时候进行对应的变量替换INSTALL_PREFIX
:install时候的prefix path
1.3.CMakeLists.txt编写
主要参考cmake的官方文档:Generating a Package Configuration File
CMakeLists.txt的编写如下:
# -----------------------------------生成库-----------------------------------
cmake_minimum_required(VERSION 3.4)
project(PLUS)
# 我自定义了install时候的路径,也可以定义为自己的install路径
SET(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)
add_library(plus SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/plus.cpp)
target_include_directories(plus PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
set_target_properties(plus PROPERTIES PUBLIC_HEADER "include/plus.h")
#==================生成目标文件的xxxTarget.cmake======================
# 会将生成的库libplus.so安装到${CMAKE_INSTALL_PREFIX}/lib下
install(
TARGETS plus
EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
# 生成 xxxTargets.cmake文件
install(
EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
DESTINATION lib/cmake/mylib
)
#======================生成 xxxConfig.cmake===============================
# 该变量会通过xxxConfig.cmake.in用于在生成的xxxConfig.cmake中
set(INCLUDE_DIRS include)
set(LIBRARIES plus)
set(LIB_DIR lib)
# 由cmake提供
include(CMakePackageConfigHelpers)
# 生成 xxxConfigVersion.cmake文件
write_basic_package_version_file(
${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION 1.1.1
COMPATIBILITY SameMajorVersion
)
# 用于生成 xxxConfig.cmake文件
configure_package_config_file(
${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION lib/cmake/mylib
PATH_VARS INCLUDE_DIRS LIBRARIES LIB_DIR
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
)
install(
FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION lib/cmake/mylib
)
1.4.cmake.in文件编写
其中xxxConfig.cmake.in文件中的内容如下:
@PACKAGE_INIT@
set( @PROJECT_NAME@_LIBRARIES plus)
set( @PROJECT_NAME@_INCLUDE_DIRS @PACKAGE_INCLUDE_DIRS@)
set( @PROJECT_NAME@_LIBRARY_DIRS @PACKAGE_LIB_DIR@)
check_required_components(${PROJECT_NAME})
其中:
@PACKAGE_INIT@
:必须有,用于命令configure_package_config_file
进行识别。该语句之后的命令才会被用于构建xxxConfig.cmake
在CMakeLists.txt
中的变量INCLUDE_DIRS
,在xxxConfig.cmake.in
中以@PACKAGE_INCLUDE_DIRS@
形式出现,在生成xxxConfig.cmake
的时候,会被替换成变量INCLUDE_DIRS
表示的内容
1.5.构建
构建命令如下:
cd <project_path>
mdkir build && cd build
cmake ..
make
make install
执行命令后,得到文件分布如下:
├── CMakeLists.txt
├── include
│ └── plus.h
├── install
│ ├── include
│ │ └── plus.h
│ └── lib
│ ├── cmake
│ │ └── mylib
│ │ ├── PLUSConfig.cmake
│ │ ├── PLUSConfigVersion.cmake
│ │ ├── PLUSTargets.cmake
│ │ └── PLUSTargets-noconfig.cmake
│ └── libplus.so
├── PLUSConfig.cmake.in
└── src
└── plus.cpp
其中 xxxConfig.cmake文件的内容:
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was PLUSConfig.cmake.in ########
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
macro(check_required_components _NAME)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(NOT ${_NAME}_${comp}_FOUND)
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
####################################################################################
set( PLUS_LIBRARIES plus)
set( PLUS_INCLUDE_DIRS ${PACKAGE_PREFIX_DIR}/include)
set( PLUS_LIBRARY_DIRS ${PACKAGE_PREFIX_DIR}/lib)
check_required_components(${PROJECT_NAME})
2.使用
我们在别的地方进行使用我们生成的xxxConfig.cmake文件。另外起一个单独的项目,其CMakeLists.txt内容如下:
cmake_minimum_required(VERSION 3.4)
project(Te)
# 设置find_package的查找路径
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/plus/install/lib/cmake/mylib)
find_package(PLUS REQUIRED)
if(PLUS_FOUND)
message(STATUS "PLUS_FOUND = ${PLUS_FOUND}")
message(STATUS "PLUS_INCLUDE_DIRS = ${PLUS_INCLUDE_DIRS}")
message(STATUS "PLUS_LIBRARIES = ${PLUS_LIBRARIES}")
message(STATUS "PLUS_LIBRARY_DIRS = ${PLUS_LIBRARY_DIRS}")
endif()
add_executable(ppp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_directories(ppp PUBLIC ${PLUS_LIBRARY_DIRS})
target_link_libraries(ppp plus)
target_include_directories(ppp PUBLIC ${PLUS_INCLUDE_DIRS})