Linux环境基础开发工具使用(2)

个人主页:C++忠实粉丝**
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创**

Linux环境基础开发工具使用(2)

收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

[1. Linux项目自动化构建工具-make/Makefile](#1. Linux项目自动化构建工具-make/Makefile)

1.1背景:

[1.2 示例代码:](#1.2 示例代码:)

[1.3 依赖关系](#1.3 依赖关系)

[1.4 依赖方法:](#1.4 依赖方法:)

[1.4 补充:](#1.4 补充:)

[1.5 实现原理:](#1.5 实现原理:)

[2. Linux第一个小程序-进度条](#2. Linux第一个小程序-进度条)

[2.1: \r&&\n](#2.1: \r&&\n)

[2.2: 缓冲区概念](#2.2: 缓冲区概念)

[2.3 进度条代码](#2.3 进度条代码)

[3. 使用git命令行](#3. 使用git命令行)

[3.1 安装git](#3.1 安装git)

[3.2 git三板斧](#3.2 git三板斧)

[3.2.1 git add](#3.2.1 git add)

[3.2.2 git commit](#3.2.2 git commit)

[3.2.3 git push](#3.2.3 git push)

[4. 使用gitee创建项目](#4. 使用gitee创建项目)

[4.1 注册账号:](#4.1 注册账号:)

[4.2 创建项目:](#4.2 创建项目:)

[4.3 下载到本地:](#4.3 下载到本地:)

[5. Linux调试器-gdb使用](#5. Linux调试器-gdb使用)

[5.1 使用背景:](#5.1 使用背景:)

[​5. 2使用方法:](#5. 2使用方法:)

[5.3 实例展示:](#5.3 实例展示:)


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文件,写入以下代码并保存:

cpp 复制代码
 #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 操作的时间,提高整体效率。

代码示例:

cpp 复制代码
#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 秒后退出。

cpp 复制代码
#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 秒内不会看到任何输出。这可能会让用户感觉程序没有任何反应。

cpp 复制代码
#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 进度条代码

cpp 复制代码
#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

cpp 复制代码
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 下载到本地:

点击自己已将创建好的仓库,右上角有克隆/下载的方块

点击复制你仓库的地址

创建好一个放置代码的目录.然后使用命令

cpp 复制代码
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 实例展示:

相关推荐
Octopus20771 小时前
【Linux】vim的使用
linux·笔记·学习·vim
一个假的前端男1 小时前
VMware安装CentOS 9 及mysql的安装
linux·运维·centos
北京迅为2 小时前
【北京迅为】iTOP-4412全能版使用手册-第七章 Android 4.4系统编译
linux·嵌入式硬件·4412开发板
大风吹PP凉2 小时前
47小型项目的规划与实施
linux·运维·服务器
金鸣科技官方QQ2 小时前
高效制作定期Excel报表:自动化与模板化的策略
运维·自动化·excel
Bio Coder3 小时前
shell查看服务器的内存和CPU总量
运维·服务器·内存·cpu
ccnnlxc3 小时前
shell编程第四天(day036)
linux·运维·服务器
基极向上的三极管3 小时前
【Linux学习】【Ubuntu入门】1-10 ubuntu文件权限
linux·ubuntu
滴水之功3 小时前
VMware ubuntu创建共享文件夹与Windows互传文件
linux·ubuntu
Jolen_xie3 小时前
Ubuntu下用Docker部署群晖系统---Virtual DSM --zerotier实现连接
linux·ubuntu·docker