CMake学习笔记:find_package
一、用途
find_package它主要用于查找并加载外部库或框架,自动在CMake的模块路径中搜索相应的FindXXX.cmake或者XXXconfig.cmake或者xxx-config.cmake文件,并根据该文件提供的信息设置库文件路径、头文件路径以及链接选项等。
我们在mac系统下,以Poco库为例子学习find_package的使用。mac安装Poco库的方法在我的文章中。
二、使用find_package的简单例子
CMakeLists.txt的一段代码,其中查找Poco库中的Foundation和Util两个库
cmake_minimum_required(VERSION 3.30)
project(findPackageDemo)
add_executable(findPackDemo main.cpp)
find_package(
Poco
COMPONENTS Foundation Util
REQUIRED
)
我们通过下面这段代码,查看找到的库的头文件搜索路径信息和动态库路径信息。
foreach(m ${Poco_LIBRARIES})
message(STATUS "Poco: ${m}")
#获取头文件的搜索路径
get_target_property(
m_poco_include_dir ${m} INTERFACE_INCLUDE_DIRECTORIES
)
message(STATUS " m_poco_include_dir: ${m_poco_include_dir}")
#获取动态库的路径
get_target_property(
m_poco_location ${m} INTERFACE_LOCATION
)
message(STATUS " m_poco_location: ${m_poco_location}")
endforeach()
运行结果如下
[cmake] -- Poco: Poco::Foundation
[cmake] -- m_poco_include_dir: /usr/local/include;/usr/local/include
[cmake] -- m_poco_location: /usr/local/lib/libPocoFoundation.103.dylib
[cmake] -- Poco: Poco::Util
[cmake] -- m_poco_include_dir: /usr/local/include;/usr/local/include
[cmake] -- m_poco_location: /usr/local/lib/libPocoUtil.103.dylib
find_package在查找和解析Poco库信息的时候,分为两种模式:Module模式和Config模式。Module模式下解析 Findxxx.cmake
文件,Config模式下解析xxxConfig.cmake
文件或者 xxx-config.cmake文件。
三、Module模式
3.1 find_package
参数
find_package(<package> [VERSION] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
3.2 文件搜索过程
Module 模式下,在CMAKE_MODULE_PATH
和 CMake 安装路径下(CMAKE_ROOT)的 Modules 目录中查找名为 Find<PackageName>.cmake
的配置文件。
测试代码如下
message(STATUS "----------------Module模式---------------")
#查找到名为 Find<PackageName>.cmake 的配置文件
#只需要查找两个路径 CMAKE_MODULE_PATH CMAKE_ROOT
message(STATUS ${CMAKE_ROOT})
message(STATUS ${CMAKE_MODULE_PATH})
find_package(GTest REQUIRED) #Cmake提供的现成开发库
运行结果如下
[cmake] -- ----------------Module模式---------------
[cmake] -- /Applications/CMake.app/Contents/share/cmake-3.30
[cmake] --
四、Config模式
4.1 用法
Config 模式的参数更多更复杂,但实际使用只需要掌握基本的参数用法即可
4.2 文件搜索过程
Config 模式搜索文件路径顺序如下:
message(STATUS "----------------Config模式---------------")
#搜索路径有4类
#<PackageName>_DIR
#CMAKE_PREFIX_PATH CMAKE_FRAMEWORK_PATH CMAKE_APPBUNDLE_PATH
#PATH 环境变量路径
#CMAKE_SYSTEM_PREFIX_PATH 系统变量
#<PackageName>_DIR 需要指定到<PackageName>config.cmake文件所在目录
#CMAKE_PREFIX_PATH 只需要指定查找的根目录即可
#找到根目录后,会匹配根目录下的路径,用于找到<PackageName>config.cmake
五、FindXXX.cmake简单例子
任务背景:封装一个自己的MYPOCO动态库,MYPOCO库中依赖第三方Poco库的部分内容。创建一个MYProject项目,依赖MYPOCO库。以此练习find*.cmake文件的编写和find_package的使用。macOS的第三方Poco库的编译安装参考MacOS编译和安装Poco库的方法。
5.1 MYProject项目源代码
1. 首先写一个要被依赖第三方项目MYPOCO,生成动态库libMyPoco.dylib。我们将MYPOCO的头文件和动态库放在如下的公共路径下。MyPOCO项目代码
Common
|_ include
|_ mypocoApi.h
|_ lib
|_ libMyPoco.dylib
|_cmake
|_ FindMyPoco.cmake
2. 编写自己的项目MYProject,使用第三方库libMyPoco.dylib功能。
MYProject项目目录结构
MYPROJECT
|_ CMakeLists.txt
|_ main.cpp
MYProject项目CMakeLists.txt
cmake_minimum_required(VERSION 3.30)
project(MyProject)
#获取当前项目路径的上一级路径
set(_IMPORT_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})
get_filename_component(_IMPORT_PREFIX ${_IMPORT_PREFIX} PATH)
#手动把cmake的搜索路径赋值,用于找到Mypoco对应的cmake文件
set(CMAKE_MODULE_PATH "${_IMPORT_PREFIX}/Common/cmake")
find_package(MyPoco REQUIRED)
#添加可执行程序
add_executable(MyProject main.cpp)
#添加第三方库MyPoco的链接
target_link_libraries(
MyProject
PUBLIC MyPoco
)
MYProject项目main.cpp
#include <iostream>
#include "mypocoApi.h"
using namespace std;
int main()
{
cout<<"This is myProject"<<endl;
MYTHREELIB::mypoco mp(888);
mp.mypocoFormat();
return 1;
}
5.2 FindMyPoco.cmake
编写FindMyPoco.cmake文件,用于其他项目找到MyPoco库的路径
FindMyPoco.cmake文件
get_filename_component(MyPoco_root ${CMAKE_CURRENT_SOURCE_DIR} PATH)
set(MyPoco_root ${MyPoco_root}/Common)
#寻找动态路的搜索路径
find_library(
MyPoco_LIB
NAMES libMyPoco.dylib
PATHS ${MyPoco_root}/lib
NO_DEFAULT_PATH #不使用其他默认搜索路径
)
#寻找头文件搜索路径
find_path(
MyPoco_INCLUDE_DIR
NAMES mypocoApi.h
PATHS ${MyPoco_root}/include
)
find_package(
Poco
COMPONENTS Foundation
REQUIRED
)
set(MyPoco_INCLUDE_DIRS ${MyPoco_INCLUDE_DIR} /usr/local/include)
set(MyPoco_LIBS ${MyPoco_LIB})
#防止目标被重复制作
if(NOT TARGET MyPoco)
add_library(MyPoco SHARED IMPORTED)
set_target_properties(MyPoco PROPERTIES
IMPORTED_LOCATION ${MyPoco_LIB}
INTERFACE_INCLUDE_DIRECTORIES "${MyPoco_INCLUDE_DIRS}")
target_link_libraries(MyPoco INTERFACE Poco::Foundation)
endif()
5.3 MYPOCO项目源代码
MYPoco项目目录结构
MYPOCO
|_ CMakeLists.txt
|_ main.cpp
|_ mypocoApi.h
|_ mypocoApi.cpp
MYPOCO项目CMakeLists.txt
cmake_minimum_required(VERSION 3.30)
project(MyPoco)
#打印出来看一下
message(STATUS "${m_poco_include_dir}")
#生成MyPoco的动态库libMyPoco.dylib
add_library(MyPoco SHARED main.cpp mypocoApi.cpp)
#add_executable(MyPoco main.cpp mypocoApi.cpp)
#查找依赖的第三方库PocoFoundation
find_package(
Poco
COMPONENTS Foundation
REQUIRED
)
#获取目标的头文件搜索路径
get_target_property(
m_poco_include_dir
Poco::Foundation
INTERFACE_INCLUDE_DIRECTORIES
)
#链接第三方库PocoFoundation
target_link_libraries(
MyPoco
PUBLIC Poco::Foundation;Poco::Foundation
)
#包含第三方库PocoFoundation的头文件搜索路径
target_include_directories(
MyPoco
INTERFACE m_poco_include_dir
BUILD_INTERFACE m_poco_include_dir
)
MYPOCO项目main.cpp
#include <iostream>
#include "mypocoApi.h"
using namespace std;
int main()
{
MYTHREELIB::mypoco c_poco(666);
c_poco.mypocoFormat();
return 1;
}
MYPOCO项目mypocoApi.h
#include <iostream>
#include "Poco/Foundation.h"
#include "Poco/Format.h"
using namespace std;
namespace MYTHREELIB{
class mypoco
{
public:
mypoco(int num):m_myformat(num){}
int m_myformat;
void mypocoFormat();
};
}
MYPOCO项目mypocoApi.cpp
#include "mypocoApi.h"
void MYTHREELIB::mypoco::mypocoFormat()
{
string res = Poco::format("%d", m_myformat);
cout<<"This is mypocoFormat res "<<res<<endl;
}
六、XXXConfig.cmake简单例子
XXXConfig.cmake的编写方法todo...
原文地址:https://blog.csdn.net/flybirddizi/article/details/142694369
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!