Cmake之深入理解find_package()的用法
“轻松搞定CMake”系列之find_package用法详解中提到Module模式和Config模式的区别:
- Module模式:find_package命令基础工作模式(Basic Signature),也是默认工作模式。
- Config模式:find_package命令高级工作模式(Full Signature)。 只有在find_package()中指定CONFIG、NO_MODULE等关键字,或者Module模式查找失败后才会进入到Config模式。
【Cmake之深入理解find_package()的用法中对Module模式和Config模式的区别的描述似乎和上面的描述不太符合】
https://www.jianshu.com/p/39fc5e548310
https://www.cnblogs.com/pandamohist/p/16177016.html
官方文档阅读
依赖项引入的方法,FetchContent和find_package()
- find_package():库使用cmake、非cmake构建的都可以使用find_package()来引入。
如果库是必要的,那么必须加上REQUIRED??
find_package(Catch2)
find_package(GTest REQUIRED)
find_package(Boost 1.79 COMPONENTS date_time)
1.79是版本,cmake如何检测版本对不对,检测文件名字吗??
COMPONENTS是个啥?
看不懂Module mode和Config mode的区别?
可以在cmake命令中指定使用哪种mode运行??
.pc文件和.cmake文件都是包含库文件和头文件,两者有什么区别??
什么叫components,是库文件吗??
如何写那种模式下的文件呢??
总结:Cmake之深入理解find_package()的用法
为了方便我们在项目中引入外部依赖包,cmake官方为我们预定义了许多寻找依赖包的Module,他们存储在path_to_your_cmake/share/cmake-<version>/Modules目录下。每个以Find<LibaryName>.cmake命名的文件都可以帮我们找到一个包。
【有些包会自动下载下来???】
cmake的安装路径中的path_to_your_cmake/share/cmake-<version>/Modules中含有一些cmake官方写的.cmake文件,如果linux中根本没有curl呢,如果curl安装在不知道什么地方呢?这些官方定义的.cmake为什么能起作用,什么时候起作用,什么时候不能起作用?
我的官方定义的.cmake文件在/usr/share/cmake-3.24/Modules
在Module模式中,cmake需要找到一个叫做Find
find_package的含义:在CMakeLists.txt中使用CMAKE_MODULE_PATH指明.cmake
文件所在目录,.cmake
指明库文件和头文件所在目录。find_library用于指明查找哪个库。
find_package的两种模式,一种是Module模式,一种叫做Config模式。【看不懂两者的区别?】
Module模式:安装cmake的时候,cmake官方写的.cmake文件
Config模式:安装各种包的时候,各种包提供的.cmake文件。
【由以上的例子可以看到,对于原生支持Cmake编译和安装的库通常会安装Config模式的配置文件到对应目录,这个配置文件直接配置了头文件库文件的路径以及各种cmake变量供find_package使用。而对于非由cmake编译的项目,我们通常会编写一个Find
官方文档
find_package的两种搜索模式:Module和Config,什么叫做搜索模式,搜索什么的呢??库文件和头文件所在的路径吗?
两种模式在.cmake文件的编写上有什么不同的吗?引用这两种搜索模式的.cmake文件的方法有什么不同吗??
Find
文中还提到这种方法,容易过时,那这种方法的意义是什么??
1.创建自己的xxxConfig.cmake,用于第三方使用
CMAKE_INSTALL_PREFIX:make install时的安装路径。不仅可以在CMakeLists.txt中使用,也可以在cmake命令上进行设置,如:
cmake -D CMAKE_INSTALL_PREFIX=/usr
参考:创建自己的xxxConfig.cmake,用于第三方使用
2.编写自己的Find.cmake模块
项目的目录结构:
├── libadd.cc
├── libadd.h
├── Makefile
└── test
├── addtest.cc
├── cmake
│ └── FindADD.cmake
└── CMakeLists.txt
具体内容如下:
libadd.h
int add(int i, int j);
libadd.cc
#include "libadd.h"
int add(int i, int j)
{
return i + j;
}
Makefile
# 1、准备工作,编译方式、目标文件名、依赖库路径的定义。
CC = g++
CFLAGS := -Wall -O3 -std=c++11
OBJS = libadd.o #.o文件与.cpp文件同名
LIB = libadd.so # 目标文件名
INCLUDE = ./ # 头文件目录
HEADER = libadd.h # 头文件
all : $(LIB)
# 2. 生成.o文件
$(OBJS) : libadd.cc
$(CC) $(CFLAGS) -I ./ -fpic -c $< -o $@
# 3. 生成动态库文件
$(LIB) : $(OBJS)
rm -f $@
g++ $(OBJS) -shared -o $@
rm -f $(OBJS)
# 4. 删除中间过程生成的文件
clean:
rm -f $(OBJS) $(TARGET) $(LIB)
# 5.安装文件
install:
cp $(LIB) /usr/lib
cp $(HEADER) /usr/include
编译和安装动态库:
make
sudo make install
addtest.cc
#include <stdio.h>
#include <stdlib.h>
#include "libadd.h"
int main(int argc, char *argv[])
{
printf("1 + 2 = %d\n", add(1, 2));
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(test)
# 将项目目录下的cmake文件夹加入到CMAKE_MODULE_PATH中,让find_pakcage能够找到我们自定义的函数库
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
add_executable(addtest addtest.cc)
find_package(ADD)
if(ADD_FOUND)
target_include_directories(addtest PRIVATE ${ADD_INCLUDE_DIR})
target_link_libraries(addtest ${ADD_LIBRARY})
else(ADD_FOUND)
message(FATAL_ERROR "ADD library not found")
endif(ADD_FOUND)
FindADD.cmake
# 在指定目录下寻找头文件和动态库文件的位置,可以指定多个目标路径
find_path(ADD_INCLUDE_DIR libadd.h /usr/include/ /usr/local/include ${CMAKE_SOURCE_DIR}/ModuleMode)
find_library(ADD_LIBRARY libadd.so /usr/lib/ /usr/local/lib/ ${CMAKE_SOURCE_DIR}/ModuleMode)
if (ADD_INCLUDE_DIR AND ADD_LIBRARY)
set(ADD_FOUND TRUE)
endif (ADD_INCLUDE_DIR AND ADD_LIBRARY)
编译和执行:
cd test
mkdir build
cd build
cmake ..
make
./addtest
输出:
1 + 2 = 3