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...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值