目录
1.什么是CMake
2.CMakeflie的安装和版本的查看
3.几个简单示例
3.1.编译一个.cc文件
3.2.编译一个.hpp文件和一个.cc文件
3.3.编译一个.hpp文件和两个.cc文件
3.4.编译两个.hpp文件和一个.cc文件
4.CMakeLists.txt
4.1.CMakeLists.txt常用的几条指令
4.2.变量和缓存
4.2.1.变量定义与使用
4.2.2.缓存变量
4.3.查找库和包
4.3.1.find_package() 指令
4.3.2.使用第三方库
1.什么是CMake
Makefile想必大家都不陌生吧,它能够解决我们的自动化编译问题,大多是IDE软件都集成了make,譬如 Visual C++的 nmake、linux 下的 GNU make、Qt 的 qmake 等等。
不同的IDE所集成的make工具所遵循的规范和标准都不同,也就导致其语法、格式不同,也就不能很好的跨平台编译,会再次使得工作繁琐起来
那么cmake为了解决这个问题而诞生了,其允许开发者指定整个工程的编译流程,在根据编译平台,生成本地化的Makefile和工程文件,最后用户只需make编译即可
简而言之,可以把cmake看成一款自动生成 Makefile的工具,所以编译流程就变成了:cmake—>make–>用户代码–>可执行文件
2.CMakeflie的安装和版本的查看
首先我们需要安装我们的CMake
sudo yum install cmake
然后我们可以通过
cmake -version
来查看自己的cmake的版本
3.几个简单示例
事实上,cmake的用法特别简单
- 编写CMakeLists.txt
- 执行命令cmake .
- 执行命令make
- 运行执行程序
看几个例子来
3.1.编译一个.cc文件
首先让我们从最简单的代码入手,先来体验下cmake是如何操作的。编写main.cc,如下,
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
然后在main.cc相同目录下编写CMakeLists.txt,内容如下,
cmake_minimum_required (VERSION 2.8)
project (demo)
add_executable(main main.cc)
- 第一行意思是表示cmake的最低版本要求是2.8,我们安装的是3.20.2;
- 第二行是表示本工程信息,也就是工程名叫demo;
- 第三行比较关键,表示最终要生成的elf文件的名字叫main,使用的源文件是main.cc
在终端下切到main.cc所在的目录下,然后输入以下命令运行下面这个命令
cmake .
执行之后,就会有下面这样子的情况发生
我们再看看当前目录下面
我们发现当前目录下面有Makefile了,我们打开看看
好像不认识啊 ,这个我们不管,我们退出来make一下
完美啊!
3.2.编译一个.hpp文件和一个.cc文件
接下来我将编译一个.hpp文件和一个.cc文件
method.hpp
#pragma once
#include<iostream>
void Printf()
{
std::cout<<"hello world!"<<std::endl;
}
main.cc
#include"method.hpp"
int main()
{
Printf();
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(demo)
# 添加可执行文件,只需要列出源文件,头文件不需要列出
add_executable(main main.cc)
# method.hpp 是 main.cc 依赖的头文件,确保它位于正确的路径下
# CMake 会自动处理包含路径(如果设置了正确的包含目录)
# 如果需要,可以使用 include_directories 来指定头文件搜索路径
# include_directories(path/to/headers)
# 但头文件和源文件在同一目录下,通常不需要这样做
我们执行
cmake .
完美!
3.3.编译一个.hpp文件和两个.cc文件
接下来进入稍微复杂的例子:这次我们决定编译一个.h文件和两个.cc文件
method.hpp
#pragma once
#include<iostream>
void Printf();
method.cc
#include"method.hpp"
void Printf()
{
std::cout<<"hello world"<<std::endl;
}
main.cc
#include"method.hpp"
int main()
{
Printf();
}
我们现在就来编写CMakeLists.txt
CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (demo)
add_executable(main main.cc method.cc)
注意我这里只是在main.cc后面加路method.cc
我们使用一下
cmake .
完美啊!!
3.4.编译两个.hpp文件和一个.cc文件
接下来我们将使用method.hpp,way.hpp,main.cc文件来编译
way.hpp
#pragma once
#include<iostream>
void Printf1()
{
std::cout<<"Printf1"<<std::endl;
}
method.hpp
#pragma once
#include<iostream>
void Printf2()
{
std::cout<<"Printf2"<<std::endl;
}
main.cc
#include"way.hpp"
#include"method.hpp"
int main()
{
Printf1();
Printf2();
}
CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (demo)
add_executable(main main.cc)
注意:因为我这里只有一个源文件,所以我们写一个main.cc就好
我们执行
cmake .
完美!
4.CMakeLists.txt
编写CMakeLists.txt最常用的功能就是调用其他的.h头文件和.so/.a库文件,将.cpp/.c/.cc文件编译成可执行文件或者新的库文件。
4.1.CMakeLists.txt常用的几条指令
CMakeLists.txt 文件使用一系列的 CMake 指令来描述构建过程。常见的指令包括:
1、指定 CMake 的最低版本要求:
cmake_minimum_required(VERSION <version>)
例如:
cmake_minimum_required(VERSION 3.10)
2、定义项目的名称和使用的编程语言:
project(<project_name> [<language>...])
例如:
project(MyProject CXX)
3、指定要生成的可执行文件和其源文件:
add_executable(<target> <source_files>...)
例如:
add_executable(MyExecutable main.cpp other_file.cpp)
4、创建一个库(静态库或动态库)及其源文件:
add_library(<target> <source_files>...)
例如:
add_library(MyLibrary STATIC library.cpp)
5、链接目标文件与其他库:
target_link_libraries(<target> <libraries>...)
例如:
target_link_libraries(MyExecutable MyLibrary)
6、添加头文件搜索路径:
include_directories(<dirs>...)
例如:
include_directories(${PROJECT_SOURCE_DIR}/include)
7、设置变量的值:
set(<variable> <value>...)
例如:
set(CMAKE_CXX_STANDARD 11)
8、设置目标属性:
target_include_directories(TARGET target_name
[BEFORE | AFTER]
[SYSTEM] [PUBLIC | PRIVATE | INTERFACE]
[items1...])
例如:
target_include_directories(MyExecutable PRIVATE ${PROJECT_SOURCE_DIR}/include)
9、安装规则:
install(TARGETS target1 [target2 ...]
[RUNTIME DESTINATION dir]
[LIBRARY DESTINATION dir]
[ARCHIVE DESTINATION dir]
[INCLUDES DESTINATION [dir ...]]
[PRIVATE_HEADER DESTINATION dir]
[PUBLIC_HEADER DESTINATION dir])
例如:
install(TARGETS MyExecutable RUNTIME DESTINATION bin)
10、条件语句 (if, elseif, else, endif 命令)
if(expression)
# Commands
elseif(expression)
# Commands
else()
# Commands
endif()
例如:
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message("Debug build")
endif()
11、自定义命令 (add_custom_command 命令):
add_custom_command(
TARGET target
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [WORKING_DIRECTORY dir]
[COMMAND command2 [ARGS]]
[DEPENDS [depend1 [depend2 ...]]]
[COMMENT comment]
[VERBATIM]
)
例如:
add_custom_command(
TARGET MyExecutable POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)
实例
一个简单的 CMakeLists.txt 文件示例:
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)
# 添加源文件
add_executable(MyExecutable main.cpp)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
4.2.变量和缓存
CMake 使用变量来存储和传递信息,这些变量可以在 CMakeLists.txt 文件中定义和使用。
变量可以分为普通变量和缓存变量。
4.2.1.变量定义与使用
定义变量:
set(MY_VAR "Hello World")
使用变量:
message(STATUS "Variable MY_VAR is ${MY_VAR}")
4.2.2.缓存变量
缓存变量存储在 CMake 的缓存文件中,用户可以在 CMake 配置时修改这些值。缓存变量通常用于用户输入的设置,例如编译选项和路径。
定义缓存变量:
set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")
使用缓存变量:
message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")
4.3.查找库和包
CMake 可以通过 find_package() 指令自动检测和配置外部库和包。
常用于查找系统安装的库或第三方库。
4.3.1.find_package() 指令
基本用法:
find_package(Boost REQUIRED)
指定版本:
find_package(Boost 1.70 REQUIRED)
查找库并指定路径:
find_package(OpenCV REQUIRED PATHS /path/to/opencv)
使用查找到的库:
target_link_libraries(MyExecutable Boost::Boost)
设置包含目录和链接目录:
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
4.3.2.使用第三方库
假设你想在项目中使用 Boost 库,CMakeLists.txt 文件可能如下所示:
实例
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)
# 查找 Boost 库
find_package(Boost REQUIRED)
# 添加源文件
add_executable(MyExecutable main.cpp)
# 链接 Boost 库
target_link_libraries(MyExecutable Boost::Boost)
通过上述内容,用户可以了解 CMakeLists.txt 文件的基本结构和常用指令,掌握如何定义和使用变量,查找和配置外部库,从而能够有效地使用 CMake 管理项目构建过程。