cmake
auggie

linux 简介

1.1 目录结构

  • bin:存储二进制指令
  • sbin:只能 sudo 的指令
  • etc:配置文件
  • dev:IO 设备,需要被挂载
  • mnt:IO 设备被 mount 的文件夹
  • home:除了 root 之外,其他用户的目录
  • proc:存储 linux 运行时的进程
  • tmp:临时文件
  • usr:存放文虎自己安装的文件,program files
  • var:存放程序和日志文件

1.2 文件指令

  • 命令 [option] [object]

  • pwd:print current working directory

  • ls:list

  • cd:change directory

  • mkdir:make directory,创建文件夹

    • -p:创建多层不存在的文件夹
  • touch:创建文件

  • rm:删除文件或文件夹

  • cp:复制文件或文件夹 cp [src] [dest]

    • -r 递归复制,文件夹
  • mv:移动文件

  • time:time [指令] 用于计时

g++

switch user do: sudo (root do)

1
2
3
4
5
sudo yum update
# 安装 gcc g++ gdb
sudo yum install build-essential gdb
# 安装 cmake
sudo yum install cmake
1
2
3
4
5
6
7
sudo yum install -y http://mirror.centos.org/centos/7/extras/x86_64/Packages/centos-release-scl-rh-2-3.el7.centos.noarch.rpm

sudo yum install -y http://mirror.centos.org/centos/7/extras/x86_64/Packages/centos-release-scl-2-3.el7.centos.noarch.rpm

sudo yum install devtoolset-9-gcc-c++

source /opt/rh/devtoolset-9/enable

gcc

编译过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 预处理
# -E 仅对文件进行预处理
# 将 include 展开为代码
g++ -E t.cpp -o t.i

# 编译
# -S 产生汇编语言文件
# 中间代码生成,汇编文件
g++ -S t.i -o t.s

# 汇编
# -c 源代码 -> 机器语言的目标代码
# 二进制文件
g++ -c t.s -o t.o

# 链接
# 生成可执行文件
g++ t.o -o t

g++ 重要的编译参数

  • -g:产生带调试信息的可执行文件
  • -O[n] 优化源代码
  • -l 指定文件,用于链接
  • -L 指定文件路径 (默认:/lib /usr/lib /usr/local/lib
  • -I 指定头文件的搜索目录
  • -Wall 打印警告信息
  • -w 关闭警报信息
  • -std=c++[x]
  • -o 指定输出名
  • -D 定义宏

直接编译

1
g++ main.cpp /src/swap.cpp -Iinclude

mian.cpp 中使用了 swap.cpp 中的函数

生成静态库文件并编译

1
2
3
4
5
6
7
8
9
10
11
# 生成 .o 文件
g++ Swap.cpp -c -I../include

# 生成静态库文件 LibSwap.a
ar rs libSwap.a Swap.o

# 链接静态库
g++ mian.cpp -lswap -L./src -Iinclude -o static_main

# 运行文件
./static_main

生成动态库文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 生成动态库文件 libSwap.so
# -shared 生成动态库文件
g++ swap.cpp -I../include -fPIC -shared -o libSwap.so

# 生成 .o 文件
# g++ Swap.cpp -I../include -c -fPIC
# g++ -shared -o libSwap.so Swap.o

# 使用动态库编译
g++ main.cpp -Iinclude -lswap -Lsrc -o dyna_main

# 运行可执行文件
# 需要先指定动态库文件的搜索路径
# LD_LIBRARY_PATH=[dir] ./[bin]
LD_LIBRARY_PATH=src ./dyna_mian

GDB 调试器

GDB(GNU Debugger) 是一个调试 C/C++ 程序的调试器

  • 设置断点
  • 单步执行程序,便于调试
  • 查看程序中的变量值的变化

常用的调试命令参数

gdb [exefilename],exefilename 为可执行文件名

  • run(r):重新开始运行程序

  • start:单步执行,运行程序

  • list:查看源代码,list-x 从第 x 行开始查看代码,list+func 查看 func 函数

  • set:设置变量的值

  • next:单步调试,逐过程,函数直接执行

  • step:单步调试,逐语句,跳入函数体内部

  • finish:结束当前函数的执行

  • continue(c):继续执行

查看:

  • print(p): print [var] 输出 var 的值
  • display:display [var] 一直监视 var 的值
  • list(l):显示当前附近的代码

添加断点:

  • break:break [n](b [n]) 在第 n 行添加断点

  • info breakpoints (i b) 查看全部的断点信息

  • quit 结束 gdb

在 g++ 编译的时候,需要加入 -g 指令才能使用 gdb 调试

enter 键,重复执行上一次的命令

ctrl + l 清屏

vscode

使用命令行打开 vscode:code [filedir]

常用快捷键

  • 切换文件:strl + p
  • 打开命令面板:ctrl + shift + p
  • 打开终端:ctrl + `
  • 关闭侧边栏:ctrl + b
  • 变量同一重命名:F2
  • 转到定义出:F12
  • 格式化代码:ctrl + shift + F

cmake

  • 是什么是 cmake
  • 语法特性介绍
  • 重要指令和 cmake 常用变量
  • cmake 编译工程

CMake 是什么

  • CMake 是一个跨平台的安装编译工具,可以使用简单的语句来描述所有平台的安装(编译过程)
image-20220315140635766
为什么 CMake 跨平台

通过 CMakeList 构建不同平台的 build tool

基本语法介绍

  • 基本语法格式:指令(参数1 参数2)
    • 参数使用()
    • 参数之间使用空格或分号
  • 类似于 redis ,指令是不区分大小写的,参数和变量是区分的
  • 变量使用 ${} 方式取值,到那时在 IF 语句中是直接使用变量名取值的

重要的指令

  • cmake_minimum_required 指定 CMake 的最小版本要求
    • cmake_minimum_required(VERSION 2.8.3)
  • project 定义工程名称,并可指定工程指定的语言
    • project(HELLOWORLD)
  • set 显示定义变量
    • set(SRC swap.cpp hello.cpp)
  • include_directories 向工程添加特定的头文件的搜索路径
    • include_directories(/usr/include ./include)
  • link_directories 向工程添加多个特定的库文件搜索路径
    • linkdirectories(/usr/lib/ ./lib)
  • add_library 生成库文件
    • add_library(libname [SHARED|STATIC] src1 src2)
    • add_library(hello SHARED ${SRC})
  • add_compile_options 添加编译参数
    • add_compile_options(-Wall -std=c++14 -o2)
  • add_executable 生成可执行文件,编译 mian.cpp 生成可执行文件 main
    • add_executable(mian mian.cpp)
  • target_link_libraries 为 target 添加需要连接的共享库 相当于 -l 参数
    • target_link_libraries(mian hello) 将 hello 动态库链接到 mian 中
  • add_subdirectory 向当前工程添加源文件的子目录
    • add_subdirectory(src) src 文件夹中必须存在一个 CMakeList.txt
  • aux_source_directory 发下一个目录下所有的源文件并将列表存储在一个变量中,这个指令临时用来自动构建源文件列表 ????不懂

CMake 常用变量

  • CMAKE_C_FLAGS gcc 编译选项
  • CMAKE_CXX_FLAGS g++ 编译选项
1
2
# 在 CMAKE_CXX_FLAGS 编译选项后追加 -std=c++11
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
  • CMAKE_BUILD_TYPE 编译类型(debug, release)
1
2
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_TYPE Release)

CMake 编译工程

CMake 目录结构:项目主目录存在 CMakeLists.txt

两种方式设置编译规则:

  1. 包含源文件的子文件夹包含 CMakeLists.txt 文件,主目录的 CMakelists.txt 通过 add_subdirectory 添加子目录即可
  2. 包含源文件的子文件夹未包含 CMakeLists.txt 文件,子目录的编译规则体现在主目录的 CMakeLists.txt 中

编译流程

  • 手动编写 CMakeLists.txt
  • 执行命令 cmake PATH 生成 Makefile (PATH 是顶层 CMakeLists.txt 所在的目录)
  • 执行命令 make 进行

构建的两种方式

  • 内部构件,在当前文件夹下,执行 make 命令。杂乱无章
  • 外部构建 推荐,创建 build 文件夹,编译上级目录的 CMakeLists.txt 文件

CMake 实战

image-20220315155252463

两个工程的结构

构建 proj1

g++ helloworld.cpp -o helloworld

  1. 编写 CMakeLists.txt
1
2
3
4
5
6
7
8
# 指定版本号
cmake_minimum_required(VERSION 2.8)

# 指定工程文件名
project(HELLOWORLD)

# 等价于 g++ helloworld.cpp -o helloworld_cmake
add_executable(helloWorld_cmake helloworld.cpp)
  1. 内部构建在 bash 中

    1. cmake . 构建 Makefile
    2. make make Makefile
  2. 外部构建在 bash 中

    1. mkdir build
    2. cd build
    3. cmake .. 在 build 文件夹构建上一级目录的 CMakeLists.txt
    1
    2
    3
    4
    5
    6
    7
    # 在 build 文件夹中构建
    mkdir build
    cd build
    # 生成 Makefile
    cmake ..
    # make Makefile make 是编译的过程
    make

image-20220315161112258

外部构建

构建 proj2

g++ main.cpp ./src/swap.cpp -I ./include -o main

1
2
3
4
5
6
7
8
9
cmake_minimum_required(VERSION 2.8)

project(SWAP)

# 包含头文件搜索路径 -I 选项
include_directories(./include)

# 类似于 g++ main.cpp ./src/swap.cpp
add_executable(main_cmake main.cpp ./src/swap.cpp)

实战 proj3

image-20220315164644371

g++ main.cpp src/Gun.cpp src/Solider.cpp -I ./include/ -o main

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required(VERSION 2.8)

project(GO)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -Wall -std=c++11")

# 包含头文件
include_directories(include)

add_executable(main_cmake main.cpp src/Gun.cpp src/Solider.cpp)

GDB

launch.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"version": "0.2.0",
"configurations": [

{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
// ***** 可执行文件路径
"program": "${workspaceFolder}/build/main_cmake",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
// ***** 指向 Task.json 中的 Build
"preLaunchTask": "Build"
}
]
}

Tasks.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"version": "2.0.0",
"options": {
// cd ./build
"cwd": "${workspaceFolder}/build"
},
"tasks": [
{
// cmake ..
"type": "shell",
"label": "cmake",
"command": "cmake",
"args": [
".."
]

},
{
// make
"label": "make",
"group": {
"kind": "build",
"isDefault": true
},
"command": "make",
"args": [

]
},
{
"label": "Build",
"dependsOrder": "sequence",
"dependsOn": [
// 调用 cmake 和 make 命令
"cmake",
"make"
]
}
],
}

总结

常用 cmake 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 指定最小版本号
cmake_minimum_required(VERSION 2.8)

# 项目名称
project(GO)

# 包含头文件
include(./lib)

# 设置编译参数
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g")

# 设置编译模式 Debug | Release
set(CMAKE_BUILD_TYPE Debug)

# 编译
add_executable(main_cmake main.cpp [其他文件])