01 编写 CMake 的 HelloWorld
目标
写一个最简单的 CMake 示例 HelloWorld
一、HelloWorld
1.选择某个目录(这里我选择的是 /home/lql,即家目录)为根目录,进入该目录
① 进入家目录命令(有两种方式)
// 普通用户家目录 /home/xxx,root 用户家目录 /root
cd /home/lql
或
cd ~
执行结果
如果你不知道自己是谁(当前用户是谁)
查看当前用户
whoami
执行结果
② 切换到 root 用户
// user:你要切换的用户,不写默认切换到 root 用户
sudo su user
如果要退出 root 用户
exit
2.创建 cmake 目录,用于存放练习代码
① 创建 cmake 目录
mkdir cmake
执行结果
② 进入 cmake 目录
cd cmake
执行结果(pwd:查看用户当前所在目录)
3.创建 main.c 文件
// 使用 vi 也可以,vim 和 vi 的区别:vim 有高亮
vim main.c
执行结果
按 i 进入编辑模式
输入内容
#include <stdio.h>
int main() {
printf("Hello World from tl Main!\n");
return 0;
}
按 Esc 退出编辑模式
按 :(冒号)
按 wq
回车
4.创建 CMakeLists.txt
vim CMakeLists.txt
按 i 进入编辑模式
输入内容
PROJECT(HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
其中第 3、4 行只是用来打印目录信息(二进制目录和源文件目录)
然后和第 3 步一样,依次按
Esc
:
wq
然后回车
此时,cmake 目录下面有刚刚创建的两个文件
ls 命令查看当面目录
ls
执行结果
5.开始构建
// 注意后面有个点号,表示当前目录
// 如果提示没有 cmake,按照提示安装 cmake 后,再执行当前操作
cmake .
执行结果
没有报错提示,证明编译成功,使用 ls 命令查看当前目录,会发现多出了一些文件
如上图所示,只需要知道最后帮我们生成了 Makefile 这个脚本文件即可
6.实际构建
make
执行结果
使用 ls 命令查看当前目录
看到比上一步,多出了一个 hello 文件,这是一个可执行文件
7.运行 hello 文件
./hello
执行结果
o**k,成功输出打印结果:Hello World from tl Main!
恭喜,到此为止,你已经掌握了 cmake 的使用方法
其实第 5 步时,我们可以采用官方推荐的外部构建的方式(生成的中间文件和可执行文件在单独的目录中,便于操作和管理)
5.开始构建
5.1 创建并进入 build 文件夹
mkdir build && cd build
5.2 执行 cmake
// 注意后面那两个点号,表示上一级目录
cmake ..
执行结果
生成的文件全部都在当前目录 build 中,便于管理,接下来的实际构建和上面的第 6 步一毛一样
二、CMake 语法
2.1 常见用法
SET(TARGET_NAME HELLO)
PROJECT(${TARGET_NAME})
SET(SRC_LIST main.c) // SRC_LIST 从名字可以看出对应的源文件的集合
# SET 更改生成的库文件路径,让文件在 lib 里面生成
SET(LIBRARY_OUTPUT_PATH ${HELLO_BINARY_DIR}/lib)
# MESSAGE 打印
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR})
MESSAGE(STATUS "This is OUTPUT dir " ${LIBRARY_OUTPUT_PATH})
# 生成可执行文件
ADD_EXECUTABLE(exe_name ${SRC_LIST})
2.2 语法简介
常用语法简介
① PROJECT 指令语法
// project_name:指定工程名称,可以不指定,默认值为 PROJECT
// [C/Java]:指定工程支持的语言,可以不指定,默认支持所有语言
PROJECT(project_name [C/Java])
跟随这个指令,对应有两个隐式变量
<project_name>_BINARY_DIR
<project_name>_SOURCE_DIR
// 两个隐式变量也可以固定写成如下格式,不受工程名称的影响
PROJECT_BINARY_DIR
PROJECT_SOURCE_DIR
举个栗子
// 指定 project_name 为 HELLO
PROJECT(HELLO)
// 对应两个隐式变量,受工程名称的影响
HELLO_BINARY_DIR
HELLO_SOURCE_DIR
② SET 指令语法
// 有点复杂,暂时只需要知道 SET 指令可以用来显式的定义变量即可
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
举个栗子
// 多个源文件之间用空格隔开
SET(SRC_LIST main.c xxx.c)
③ MESSAGE 指令语法
// 用于向终端输出用户定义的信息
// 三种类型:SEND_ERROR(产生错误,生成过程被跳过)、STATUS(输出前缀为-的信息)、FATAL_ERROR(立即终止所有 cmake 过程)
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
④ ADD_EXECUTABLE 指令语法
// 用于生成可执行文件
// xxx:指定生成的可执行文件的名称
// [SHARED|STATIC]:指定生成动态库还是静态库,默认是 STATIC,生成静态库
// ${...}:源文件,这里引用大括号中声明的变量的值
ADD_EXECUTABLE(xxx [SHARED|STATIC] ${SRC_LIST})
2.3 语法规则
1.变量使用 ${} 方式取值,但是在 IF 控制语句中直接使用变量名
2.指令(参数1 参数2 …),参数使用括号括起来,参数之间使用空格或分号隔开
SET(SRC_LIST main.c xxx.c)
或
SET(SRC_LIST main.c; xxx.c)
3.指令是大小写无关的,参数和变量是大小写相关的,但推荐全部使用大写
4.${…} 可以写在双引号之间
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
或
MESSAGE(STATUS "This is BINARY dir ${HELLO_BINARY_DIR}")
5.工程名和可执行文件名没有关系
// project_name 和 xxx 没有任何关系
PROJECT(project_name)
ADD_EXECUTABLE(xxx ${SRC_LIST})
6.源文件名称带空格,使用时可以使用双引号引起来
7.源文件名称使用时可省略后缀名(不推荐省略,可能真的有个不带后缀名的同名文件存在)
SET(SRC_LIST main.c)
或
SET(SRC_LIST main)
8.清理工程
// 对可构建结果进行清理
make clean
9.内部构建和外部构建
内部构建:在代码文件所在目录构建,生成的中间文件和可执行文件和原有文件混在一起
外部构建:新建一个目录进行构建,中间文件和可执行文件会生成在新建目录中,不会和原有文件混在一起
举个栗子
// 在 CMakeLists.txt 中通过 SET 指令指定可执行文件的生成目录
SET(LIBRARY_OUTPUT_PATH ${HELLO_BINARY_DIR}/lib)
// 在 CMakeLists.txt 所在目录新建一个 build 目录,然后进入
mkdir build && cd build
// 开始构建
cmake ..
// 实际构建
make
小结
- PROJECT 指令,指定工程名称,不指定默认为 PROJECT
- MESSAGE 指令,用于向终端输出用户定义的信息
- ADD_EXECUTABLE 指令,用于指定生成的可执行文件的名称