一、cmake的介绍
CMak可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,只需要少量的修改,非常方便。camke的主要特点:
- 跨平台(可以从很多开源的代码都提供cmakelist文件即可看出)
- 能够管理大型项目
- 简化编译构建过程,写好了cmakelist.txt文件后,在终端只需要输入cmake+make即可
二、安装cmake
安装cmake的命令:
sudo apt install cmake
查看cmake版本号的命令:
cmake -version
三、简单样例
学习编程的最简单的案例—打印Hello World
3.1 创建main.c的命令
touch main.c
3.2 在main.c文件中,粘贴以下代码
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
3.3 创建CMakeLists.txt(文件名是CMakeLists.txt才行,这样才能让cmake识别出来)
touch CMakeLists.txt
在CMakeLists.txt中,粘贴以下代码
# 表示cmake的最低版本要求是2.8
cmake_minimum_required (VERSION 2.8)
# 表示本工程信息,也就是工程名叫demo
project (demo)
# 表示最终要生成的elf文件的名字叫main,使用的源文件是main.c
add_executable(main main.c)
3.4 在main.c和CMakeLists.txt所在的目录下,创建build文件,并将终端切到build文件中
# 创建名字为build的文件夹
mkdir build
# 将终端切到build的文件夹里面
cd build
3.5 输入以下命令运行cmake和make
# 编译CMakeLists.txt来生成makefile文件,由于CMakeLists.txt在上一级目录,所有用“..”
cmake ..
# 编译程序
make
3.6 编译成功后,会生成的一堆文件,运行可执行文件来打印Hello World
./main
四、cmake指令介绍
4.1 基本的指令,cmake的最低版本号、工程名称、是否包含当前目录、c++的版本
#cmake的最低版本号
cmake_minimum_required(VERSION 2.6)
#工程名称
project(demo)
#设置工程包含当前目录
set(CMAKE_INCLUDE_CURRENT_DIR ON)
添加编译选项,如-Wall,-std=c++11等
add_compile_options(-std=c++11 -Wall)
4.2 添加目录
向工程添加多个指定头文件的搜索路径,因为c文件和cpp文件一般包含很多头文件(这些头文件的写法一般为相对路径),因此需要添加对应的头文件搜索路径
include_directories (include) # 添加当前目录下的include文件夹路径
查找在某个路径下的所有源文件
aux_source_directory (src SRC_LIST) # 其与FILE(GLOB SRC_FILES "./src/*.c")功能类似
4.3 加载源文件
在实际工程中,为了规划程序,一般将cpp文件放到src文件夹
FILE(GLOB_RECURSE SRC_FILES "./src/*.cpp")
注释:GLOB_RECURSE与GLOB的区别—GLOB只会将某个目录中的源文件加载,而不会加载其子目录的源文件;而GLOB_RECURSE会将某个目录和其子目录的源文件都加载
4.4 动态库和静态库的编译控制和加载
add_library (testFunc_shared SHARED ${SRC_LIST})
add_library (testFunc_static STATIC ${SRC_LIST})
set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "testFunc")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library:生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件)
set_target_properties: 设置最终生成的库的名称,还有其它功能,如设置库的版本号等等
LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录
动态库和静态库的加载
find_library(TESTFUNC_LIB testFunc HINTS ${PROJECT_SOURCE_DIR}/lib)
target_link_libraries (main ${TESTFUNC_LIB})
find_library: 在指定目录下查找指定库,并把库的绝对路径存放到变量里,其第一个参数是变量名称,第二个参数是库名称,第三个参数是HINTS,第4个参数是路径,其它用法可以参考cmake文档
target_link_libraries: 把目标文件与库文件进行链接
find_library(TESTFUNC_LIB testFunc HINTS ${PROJECT_SOURCE_DIR}/testFunc/lib)
target_link_libraries (main ${TESTFUNC_LIB})
4.5 加载cuda、opencv、protobuf、tensorrt的设置
查找cuda
find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
link_directories(/usr/local/cuda-11.4/lib64)
查找opencv
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS}/opencv ${OpenCV_INCLUDE_DIRS}/opencv2)
#link_directories(${OpenCV_LIBS})
查找protobuf
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
#link_directories(${Protobuf_LIBRARIES})
#查找tensorrt
include_directories(/home/***/TensorRT-8.2.1.8/include)
link_directories(/home/***/TensorRT-8.2.1.8/lib)
4.6 qt应用的设置
打开全局moc,设置自动生成moc文件,AUTOMOC打开可以省去QT5_WRAP_CPP命令.如果源代码中使用qt的QObject派生的C++类,一定要设置
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
查找需要的Qt库文件,最好每一个库都要写,Qt也会根据依赖关系自动添加
find_package(Qt5Widgets)
find_package(Qt5Core)
# 或者
find_package(Qt5 COMPONENTS Widgets Core)
4.7 编译可执行文件
add_executable(${PROJECT_NAME} ${CPP_LIST}) # 编译可执行文件
TARGET_LINK_LIBRARIES(hello PRIVATE Qt5::Widgets ${OpenCV_LIBS} ${CUDA_LIBRARIES} ${Protobuf_LIBRARIES} -lopenvino_intel_gpu_plugin -lopenvino_onnx_frontend -lopenvino -ltbb) # 导入库
4.8 对于需要加载cu文件
#查找当前文件夹内的所有cu文件
FILE(GLOB_RECURSE CU_LIST ${PROJECT_SOURCE_DIR}/*.cu)
#当需要编译cu文件时,需要加入下面来两行代码
set(CUDA_GEN_CODE "-gencode=arch=compute_75,code=sm_75")# compute_75:需要根据自己设备的算力来设置
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11 -O0 -Xcompiler -fPIC -g -w ${CUDA_GEN_CODE}")
注释:由于cu文件是涉及到cuda核函数,所以在生成可执行文件的代码由add_executable变成CUDA_add_executable
在QT上如何利用CMakeList.txt来打开项目
第一步:打开qtcreator软件
第二步:在软件的左上角点击“文件”的选项
第三步:选择打开文件或者项目,选定好CMakeList.txt,即可