Linux部署c++开发环境

0

1编译器,调试器安装

1.1.1安装GCC,GDB

1
2
3
4
5
6
//使用apt包管理命令
sudo apt update
sudo apt install build-essential gdb
//使用yum包管理命令
sudo yum update
sudo yum install gdb

1.1.2安装成功确认

1
2
3
gcc --version
g++ --version
gdb --version

1.2.1CMake安装

1
sudo apt install cmake

1.2.2安装成功确认

1
cmake --version

2GCC编译器使用

2.1编译过程

2.1.1预处理

产生.i文件

1
g++ -E test.cpp -o test.i   //-E 指示编译器对输入文件预处理

2.1.2编译

产生.s文件

1
g++ -S test.i -o test.s    //-S 指示编译器为C++代码产生汇编文件后停止编译

2.1.3汇编

产生.o文件

1
g++ -c test.s -o test.o    //-c指示编译器仅将源代码编译为机器语言的目标代码

2.1.4链接

产生bin文件

1
g++ test.o -o test        //-o指示编译器生成的文件名

2.2g++的重要编译参数

2.2.1 -g 编译带调试信息的可执行文件

1
2
3
g++ -g test.cpp
//-g 选项告诉 GCC 产生能被 GNU 调试器GDB使用的调试信息,以调试程序。
//产生带调试信息的可执行文件test

2.2.2 -o[n] 优化源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
g++ -o2 test.cpp
/*
所谓优化,例如省略掉代码中从未使用过的变量、直接将常量表达式用结果值代替等等,这些操作
会缩减目标文件所包含的代码量,提高最终生成的可执行文件的运行效率。
-O 选项告诉 g++ 对源代码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。 -O2
选项告诉 g++ 产生尽可能小和尽可能快的代码。 如-O2,-O3,-On(n 常为0–3)
-O 同时减小代码的长度和执行时间,其效果等价于-O1
-O0 表示不做优化
-O1 为默认优化
-O2 除了完成-O1的优化之外,还进行一些额外的调整工作,如指令调整等。
-O3 则包括循环展开和其他一些与处理特性相关的优化工作。
选项将使编译的速度比使用 -O 时慢, 但通常产生的代码执行速度会更快。
使用 -O2优化源代码,并输出可执行文件
*/

2.2.3 -l和-L 指定库文件 | 指定库文件路径

1
2
3
4
5
6
7
8
9
10
g++ -L/home/bing/mytestlibfolder -lmytest test.cpp
/*
-l参数(小写)就是用来指定程序要链接的库,-l参数紧接着就是库名
在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接
链接glog库
g++ -lglog test.cpp
如果库文件没放在上面三个目录里,需要使用-L参数(大写)指定库文件所在目录
-L参数跟着的是库文件所在的目录名
链接mytest库,libmytest.so在/home/bing/mytestlibfolder目录下
*/

2.2.4 -I 指定头文件搜索目录

1
2
3
4
5
6
7
8
g++ -I/myinclude test.cpp
/*
-I
/usr/include目录一般是不用指定的,gcc知道去那里找,但 是如果头文件不在/usr/icnclude
里我们就要用-I参数指定了,比如头文件放在/myinclude目录里,那编译命令行就要加上-I/myinclude 参数了,如果不加你会得到一个”xxxx.h: No such file or directory”的错
误。-I参数可以用相对路径,比如头文件在当前 目录,可以用-I.来指定。上面我们提到的–cflags参
数就是用来生成-I参数的。
*/

2.2.5 -wall 打印警告信息

1
2
//打印出gcc提供的警告信息
g++ -Wall test.cpp

2.2.6 关闭警告信息

1
2
//关闭所有警告信息
g++ -w test.cpp

2.2.7 -std=c++11 设置编译标志

1
2
//使用 c++11 标准编译 test.cpp
g++ -std=c++11 test.cpp

2.2.8 -D 定义宏

1
2
3
4
//在使用gcc/g++编译的时候定义宏
//常用场景:
//-DDEBUG 定义DEBUG宏,可能文件中有DEBUG宏部分的相关信息,用个DDEBUG来选择开启或关闭
DEBUG

示例代码

1
2
3
4
5
6
7
8
9
10
11
// -Dname 定义宏name,默认定义内容为字符串“1”
#include <stdio.h>
int main()
{
#ifdef DEBUG
printf("DEBUG LOG\n");
#endif
printf("in\n");
}
// 1. 在编译的时候,使用gcc -DDEBUG main.cpp
// 2. 第七行代码可以被执行

3实战g++编译

最初的目录结构

目录结构

3.1直接编译

简单编译,运行

1
2
3
4
// 将 main.cpp src/Swap.cpp 编译为可执行文件
g++ main.cpp src/Swap.cpp -Ihead
// 运行a.out
./a.out

增加参数编译,运行

1
2
3
4
// 将 main.cpp src/Swap.cpp 编译为可执行文件 附带一堆参数
g++ main.cpp src/Swap.cpp -Ihead -std=c++11 -O2 -Wall -o b.out
// 运行 b.out
./b.out

3.2 生成库文件并编译

链接静态库生成可执行文件

1
2
3
4
5
6
7
8
9
10
// 进入src目录下
$cd src
// 汇编,生成Swap.o文件
g++ Swap.cpp -c -I../head
// 生成静态库libSwap.a
ar rs libSwap.a Swap.o
// 回到上级目录
$cd ..
// 链接,生成可执行文件:staticmain
g++ main.cpp -Ihead -Lsrc -lSwap -o staticmain

连接动态库生成可执行文件

1
2
3
4
5
6
7
8
9
10
11
// 进入src目录下
$cd src
// 生成动态库libSwap.so
g++ Swap.cpp -I../head -fPIC -shared -o libSwap.so
// 上面命令等价于以下两条命令
gcc Swap.cpp -I../include -c -fPIC
gcc -shared -o libSwap.so Swap.o
// 回到上级目录
$cd ..
// 链接,生成可执行文件:sharemain
g++ main.cpp -Ihead -Lsrc -lSwap -o sharemain

编译完成后的目录结构

目录结构

运行staticmain

1
2
// 运行可执行文件
./staticmain

运行sharemain

1
2
// 运行可执行文件
LD_LIBRARY_PATH=src ./sharemain

4GDB调试器

前言:

  • GDB(GNU Debugger)是一个用来调试C/C++程序的功能强大的调试器,是Linux系统开发 C/C++最常用的调试器

  • 程序员可以使用GDB来跟踪程序中的错误,从而减少程序员的工作量。

  • Linux 开发C/C++ 一定要熟悉 GDB

  • VSCode是通过调用GDB调试器来实现C/C++的调试工作的;

  • Windows 系统中,常见的集成开发环境(IDE),如 VS、VC等,它们内部已经嵌套了相应的调试 器

    GDB主要功能:

    • 设置断点(断点可以是条件表达式)
    • 使程序在指定的代码行上暂停执行,便于观察
    • 单步执行程序,便于调试
    • 查看程序中变量值的变化
    • 动态改变程序的执行环境
    • 分析崩溃程序产生的core文件

4.1常用调试命令参数

调试开始:执行gdb [exefilename] ,进入gdb调试程序,其中exefilename为要调试的可执行文件名

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
//以下命令后括号内为命令的简化使用,比如run(r),直接输入命令 r 就代表命令run
$(gdb)help(h) //查看命令帮助,具体命令查询在gdb中输入help + 命令
$(gdb)run(r) // 重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件)
$(gdb)start // 单步执行,运行程序,停在第一行执行语句
$(gdb)list(l) // 查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数)
$(gdb)set // 设置变量的值
$(gdb)next(n) // 单步调试(逐过程,函数直接执行)
$(gdb)step(s) // 单步调试(逐语句:跳入自定义函数内部执行)
$(gdb)backtrace(bt) // 查看函数的调用的栈帧和层级关系
$(gdb)frame(f) // 切换函数的栈帧
$(gdb)info(i) // 查看函数内部局部变量的数值
$(gdb)finish // 结束当前函数,返回到函数调用点
$(gdb)continue(c) // 继续运行
$(gdb)print(p) // 打印值及地址
$(gdb)quit(q) // 退出gdb
$(gdb)break+num(b) // 在第num行设置断点
$(gdb)info breakpoints // 查看当前设置的所有断点
$(gdb)delete breakpoints num(d) // 删除第num个断点
$(gdb)display // 追踪查看具体变量值
$(gdb)undisplay // 取消追踪观察变量
$(gdb)watch // 被设置观察点的变量发生修改时,打印显示
$(gdb)i watch // 显示观察点
$(gdb)enable breakpoints // 启用断点
$(gdb)disable breakpoints // 禁用断点
$(gdb)x // 查看内存x/20xw 显示20个单元,16进制,4字节每单元
$(gdb)run argv[1] argv[2] // 调试时命令行传参
$(gdb)set follow-fork-mode child// Makefile项目管理:选择跟踪父子进程(fork())

Tips:

  1. 编译程序时需要加上-g,之后才能用gdb进行调试:gcc -g main.c -o main
  2. 回车键:重复上一命令

4.2调试test项目

5CMake

-------------本文结束感谢您的阅读-------------