个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创Linux环境基础开发工具使用(2)
收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌
目录
1. Linux项目自动化构建工具-make/Makefile
1. Linux项目自动化构建工具-make/Makefile
1.1背景:
1. 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
2. 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
3. makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
4. make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
5. make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
1.2 示例代码:
我们在Linux环境中新建一个proc.c文件,写入以下代码并保存:
#include <stdio.h>
int main()
{
printf("hellolinux!");
printf("hello make");
printf("hello makefile");
return 0;
}
我们再创建一个makefile文件,写入代码:
然后make直接运行:
这里直接我们使用make直接编译了代码,形成了可执行程序
proc: 后面的一行内容是依赖文件 另起一行的内容是依赖关系
依赖方法可以是任意指令:
如何清理项目:
.PHONY(让依赖方法忽略掉时间比,对应的方法总能执行) + 对应的方法(rm -f proc)
1.3 依赖关系
上面的文件 proc它依赖proc.o,proc.o 它依赖proc.s,proc.s它依赖proc.i,proc.i它依赖 hello.c
1.4 依赖方法:
gcc proc.* -option proc.* ,就是与之对应的依赖方法
1.4 补充:
% : makefile语法中的通配符
%.c : 当前目录下所有.c文件,展开到依赖列表中
gcc -c $< 依赖关系 : 右侧的依赖文件一个一个的交给gcc -c选项,形成同名文件
1. proc: proc.o
proc : 这是一个目标(target),表示要生成的最终可执行文件的名称。
proc.o : 这是目标的依赖文件(dependency),表示生成 proc 需要的对象文件(.o 文件)。在这个例子中,proc 依赖于 proc.o。
2. gcc proc.o - o proc
这条命令在 proc.o 目标被创建后执行,目的是将对象文件链接成可执行文件。
gcc : 使用 GCC 编译器。
proc.o : 作为输入的对象文件。
- o proc : 指定输出文件的名称为 proc。因此,执行这条命令后会生成一个名为 proc 的可执行文件。
3. % .o : % .c
这是一个模式规则(pattern rule),用于定义如何从 C 源文件生成对应的对象文件。
% .o : 表示任意对象文件(以.o 结尾)。
% .c : 表示与之对应的 C 源文件(以.c 结尾)。
例如,如果有一个源文件 example.c,那么这条规则会自动应用,生成 example.o。
4. gcc - c $ <
这是模式规则中的命令,用于编译 C 源文件为对象文件。
gcc - c $ < :
-c : 选项告诉编译器只编译源文件,而不进行链接。生成的结果是目标文件(.o 文件)。
$ < : 这是一个自动变量,代表当前规则的第一个依赖文件。在这个规则中,它将是匹配的.c 文件。例如,如果正在处理 example.c,那么 $ < 将会被替换为 example.c,所以执行的命令为 gcc - c example.c。
1.bin = proc
bin : 这是一个变量,定义了最终生成的可执行文件的名称为 proc。在后面的规则中,可以使用 $(bin) 来引用这个变量。
2.src = proc.o
src : 这是另一个变量,定义了生成可执行文件所需的对象文件(在这里是 proc.o)。同样,可以在后面的规则中使用 $(src) 来引用这个变量。
3.$(bin) : $(src)
这是一个目标(target)定义,表示要生成的可执行文件 $(bin) 依赖于对象文件 $(src)。
$(bin) : 这将被替换为 proc。
$(src) : 这将被替换为 proc.o。
4.gcc $ ^ -o $@
这是目标 $(bin) 的命令行,负责将对象文件链接为可执行文件。
gcc : 使用 GCC 编译器进行链接。
$ ^ : 自动变量,代表当前目标的所有依赖文件(在这个例子中是 proc.o)。在只有一个依赖的情况下,它的值就是 proc.o。
- o $@ :
-o : 用于指定输出文件的名称。
$@ : 自动变量,代表当前目标的名称。在这个例子中,$@ 的值为 proc。
整体上,这一行的命令为 gcc proc.o - o proc,用于生成可执行文件 proc。
5.% .o : % .c
这是一个模式规则(pattern rule),用于定义如何从 C 源文件生成对应的对象文件。
% .o : 代表任意对象文件(以.o 结尾)。
% .c : 代表与之对应的 C 源文件(以.c 结尾)。
例如,如果有一个源文件 example.c,那么这条规则将应用,生成 example.o。
6.gcc - c $ <
这是模式规则的命令,负责编译 C 源文件为对象文件。
gcc - c $ < :
-c : 选项告诉编译器只编译源文件,而不进行链接,生成目标文件(.o 文件)。
$ < : 自动变量,代表当前规则的第一个依赖文件。在这个规则中,它将是匹配的.c 文件。例如,如果正在处理 example.c,那么 $ < 将会被替换为 example.c,所以实际执行的命令将为 gcc - c example.c。
1.5 实现原理:
1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“proc”这个文件,并把这个文件作为最终的目标文件。
3. 如果proc文件不存在,或是proc所依赖的后面的proc.o文件的文件修改时间要比proc这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成proc这个文件。
4. 如果proc所依赖的proc.o文件不存在,那么make会在当前文件中找目标为proc.o文件的依赖性,如果找到则再根据那一个规则生成proc.o文件。(这有点像一个堆栈的过程)
5. 当然,你的C文件和H文件是存在的啦,于是make会生成 proc.o 文件,然后再用 proc.o 文件声明make的终极任务,也就是执行文件proc了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
总结:
1. makefile文件,会被make从上到下开始扫描,第一个目标名,是缺省要形成的.如果我们想执行其他组的依赖关系和依赖方法,make name
2. make makefile在执行gcc命令的时候,如果发生了语法错误,就会终止推到过程
3. make解释makefile的时候,是会自动推导的,一直推导,推导过程不执行依赖方法,直到推导到依赖文件存在,然后在逆向执行所有的依赖方法
4. make默认只形成一个可执行程序
2. Linux第一个小程序-进度条
2.1: \r&&\n
回车(CR)
定义:回车是指将光标或打印头移到当前行的起始位置。它的控制字符表示为 \r。
用途:在某些情况下(如老旧的打印机和某些文本格式),回车用于将文本移动到行首,但不会换到下一行。
换行(LF)
定义:换行是指将光标移动到下一行的相同位置。其控制字符表示为 \n。
用途:换行通常用于开始一行新的文本。
2.2: 缓冲区概念
在 Linux 和其他操作系统中,缓冲区是用于临时存储数据的内存区域。它在数据传输或处理的过程中发挥着重要作用,能够提高系统的性能和效率。
缓冲区(Buffer)是计算机内存中的一块区域,用于暂时存放数据。在数据处理、传输或 I/O 操作中,缓冲区可以减少 CPU 等待 I/O 操作的时间,提高整体效率。
代码示例:
#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
sleep(3);
return 0;
}
1. 输出格式:这个程序在打印 "hello Makefile!" 后添加了换行符(\n)。
2. 缓冲行为:
printf 默认使用行缓冲,这意味着输出将被缓存在内部,直到遇到换行符、缓冲区满或显式刷新(如使用 fflush)时才会显示。由于输出中包含换行符,因此在 sleep(3) 之前,信息会立即被打印到终端。
3. 结果:程序会在终端上立即显示 hello Makefile!,然后暂停 3 秒后退出。
#include <stdio.h>
int main()
{
printf("hello Makefile!");
sleep(3);
return 0;
}
1. 输出格式:此程序在打印 "hello Makefile!" 时没有添加换行符。
2. 缓冲行为:
由于没有换行符,printf 将使用行缓冲,但输出不会立即显示,因为没有触发输出的条件。
在 sleep(3) 期间,程序仍然会在缓冲区中保存输出,而不会将其显示到终端。
3. 结果:在 3 秒后,程序将退出。取决于环境的实现(例如某些 IDE 或终端模拟器),可能会在程序结束时输出 hello Makefile!,但在 3 秒内不会看到任何输出。这可能会让用户感觉程序没有任何反应。
#include <stdio.h>
int main()
{
printf("hello Makefile!");
fflush(stdout);
sleep(3);
return 0;
}
1. 输出格式:与第二个代码片段一样,没有换行符。
2. 缓冲行为:
在调用 fflush(stdout) 后,程序会强制刷新标准输出缓冲区,将任何已缓存的内容立即输出到终端。
因此,尽管没有换行符,printf 的内容会在 sleep(3) 之前被显示。
3. 结果:程序将立即显示 hello Makefile!,然后在 3 秒后退出。通过使用 fflush,程序的行为与第一个代码片段类似,输出将及时呈现给用户。
总结:
第一个代码片段:由于使用了换行符,输出立即显示,之后程序暂停 3 秒。
第二个代码片段:没有换行符,输出在程序结束时才显示,造成用户认为程序没有响应。
第三个代码片段:使用了 fflush(stdout) 强制刷新,确保输出在 3 秒的等待之前显示。
2.3 进度条代码
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int i = 0;
char bar[101]; // 只需 100 个字符 + 1 个结束符
memset(bar, 0, sizeof(bar)); // 初始化数组
const char* label = "|/-\\"; // 动画字符
while (i <= 100) {
// 使用 `i` 作为进度条的填充字符数
printf("[%-100s][%d%%][%c]\r", bar, i, label[i % 4]);
fflush(stdout);
// 在这里更新进度条
if (i < 100) {
bar[i] = '#'; // 更新当前进度位置
}
usleep(100000); // 睡眠 100 毫秒
i++; // 更新进度
}
// 输出完成后的进度条
printf("[%-100s][100%%][✔️]\n", bar);
return 0;
}
输出当前状态:
printf("[%-100s][%d%%][%c]\r", bar, i, label[i % 4]); :
% -100s:格式化字符串,显示当前 bar 的内容(最多 100 个字符,左对齐)。
% d % %:输出当前进度百分比 i,并显示 % %作为百分号。
% c:输出当前动画字符。
\r:回到当前行的开头,允许在同一行更新输出。
fflush(stdout); :确保缓冲区的内容立即输出到终端,而不是等到缓冲区满或程序结束。
效果展示:
3. 使用git命令行
3.1 安装git
yum install git
3.2 git三板斧
这里就拿我Linux上传gitee代码为例:
3.2.1 git add
3.2.2 git commit
git commit -m "这里写备注(也就是你做了什么)"
3.2.3 git push
push之后,我们就成功将我们今天的linux2上传到了gitee
大家在尝试之前一定要确保: 1. 你在gitee上已经创建好了项目 2. 你上传的文件是你gitee创建项目的克隆(这个大家不要着急下面有相关讲解)
4. 使用gitee创建项目
4.1 注册账号:
登录gitee官网直接跟流程注册就行
gitee官网 -- Gitee - 基于 Git 的代码托管和研发协作平台
4.2 创建项目:
点击加号新建仓库
前面的仓库名称和介绍大家可以根据自己项目取名
一般我们都会选择开源,然后自己选择语言,模板和许可证可以不填,模板方面选择Readme文件,最后分支一个一般使用单分支模型
最后点击创建即可
4.3 下载到本地:
点击自己已将创建好的仓库,右上角有克隆/下载的方块
点击复制你仓库的地址
创建好一个放置代码的目录.然后使用命令
git clone [你自己仓库的地址]
5. Linux调试器-gdb使用
5.1 使用背景:
程序的发布方式有两种,debug模式和release模式
Linux gcc / g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 - g 选项
5. 2使用方法:
gdb binFile 退出: ctrl + d 或 quit
调试命令:
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
n 或 next:单条执行。
s或step:进入函数调用
break(b)行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
p 变量:打印变量值。
set var:修改变量的值
continue(或c):从当前位置开始连续而非单步执行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X行号:跳至X行
breaktrace(或bt):查看各级函数调用及参数
info(i) locals:查看当前栈帧局部变量的值
quit:退出gdb
5.3 实例展示: