【Linux】gcc/g++配置
教育的目的是让学生们摆脱现实的奴役,而现在的年轻人正意图做着相反的努力,为了适应现实而改变自己。
前言
这是我自己学习Linux系统编程的第三篇笔记。后期我会继续把Linux系统编程笔记开源至博客上。
上一期笔记是关于Linux的Vim文本编辑器:
【Linux】Vim文本编辑器-CSDN博客
https://blog.csdn.net/hsy1603914691/article/details/147433554?spm=1001.2014.3001.5502
编译链接的过程
1. 编译链接的过程 : 预处理---> 编译---> 汇编---> 连接 。2. 预处理阶段 : 头文件展开 , 宏替换 , 去除注释 。3. 编译阶段 : 生成汇编语言 。4. 汇编阶段 : 生成二进制的目标文件。5. 链接阶段: 生成一个可执行程序。
1. 预处理指令:gcc -E xxx.c -o xxx.i
2. 编译阶段指令:gcc -S xxx.i -o xxx.s
3. 汇编阶段指令:gcc -c xxx.s -o xxx.o
4. 链接阶段指令:gcc xxx.o -o xxx
动静态库
1. 库分为动态库和静态库。
2. 在Linux下,动态库类型为libxxx.so,静态库类型为libxxx.a。
3. 使用动态链接需要动态库,使用静态链接需要静态库。
4. Linux一般只会存在动态库,静态库需要自己去下载安装。
5. 安装静态库的指令:sudo yum install glibc-static libstdc++-static -y
6. 静态库存在两个缺点,一个优点:
浪费空间(缺点) :静态库在使用时,会将库中被引用的代码完整地复制到最终生成的可执行文件中。如果多个程序都使用了同一个静态库,那么每个程序都会各自包含一份该库的副本。 更新困难(缺点) :静态库的代码是直接嵌入到可执行文件中的,因此在库被更新后,所有依赖该库的程序都需要重新编译并链接新的库版本,才能使用更新后的功能。- 不依赖库(优点)。
7. 动态库是共享的,一旦丢失,所有依赖动态库的程序都会出错。
动静态链接
1. 实际开发中,可能会存在多个 .c 文件,这些 .c 文件之间存在多种依赖关系,如函数调用等。但是每个 .c 文件都是独立进行编译产生对应数量的 .o 文件。所以为了满足这种依赖关系,则需要将这些 .c 文件产生的 .o 文件进行链接,从而形成一个可执行程序。这个链接的过程就是静态链接。
2. 动态链接编译时也会将每个 .c 文件编译为 .o 文件。但与静态链接不同,这些 .o 文件在链接阶段并不会直接包含库函数的具体实现,而是记录对动态链接库的引用。当程序运行时,操作系统的动态链接器会根据这些引用加载相应的动态库到内存,并完成符号解析和绑定,使得程序能够调用库中的函数。
3. gcc默认生成的可执行程序是通过动态链接的方式构建的;如果需要生成静态链接的可执行程序,则必须显式地使用gcc-static选项,强制链接器将所有依赖的库函数直接嵌入到最终的可执行文件中,从而避免运行时对动态库的依赖。
Make/Makefile
make/makefile定义
1. make是一个命令,makefile是一个文件。
2. make执行时,会自顶向下扫描makefile文件,并默认将makefile文件中定义的第一个目标作为最终构建的目标。如果需要构建其他特定的目标文件,则可以通过命令行显式指定目标名称,即使用 make targetfile 的方式来生成指定的目标。
3. makefile文件中的注释用 # 。
配置基本的makefile文件
vim makefile: 使用vim文本编辑器配置makefile文件。
- mytest:--->目标文件,1.c--->依赖文件列表
- gcc 1.c -o mytest --->依赖方法
- .PHONY:clean ---> 伪目标(伪目标的依赖方法总是会被执行)忽略对比时间
- clean:--->目标文件
- rm -f mytest--->依赖方法
1. 使用make命令时,初次运行会依据makefile中定义的规则编译第一个目标文件。后续执行make时,若该目标文件存在且其依赖的源文件未更新,则不会重新编译,直接认为目标文件是最新的。
2. 系统通过对比源文件Modify时间和可执行程序Modify时间,从而判断源文件是否更新。
3. 伪目标的依赖方法总是会被执行,因为其并不需要判断文件是否更新。
make自动推导机制
1. make会在当前目录下寻找名为Makefile或makefile的文件。如果找不到,会报错退出。
2. 在找到Makefile或makefile文件后,make会默认以文件中的第一个目标作为最终构建目标。
3. 如果目标文件不存在,make会尝试根据规则生成它;如果目标文件存在,但依赖文件比目标文件新,则认为目标文件已过期,需要重新生成。
4. 如果某个依赖文件不存在或过期,make会继续查找是否有规则可以生成该依赖文件,直到所有依赖都被满足。
5. 当所有依赖都满足时,make会执行与目标相关的命令来生成目标文件。
6. 如果某个依赖文件缺失且没有规则生成它,make会报错并退出。
配置通用的makefile文件
1. makefile文件中也可以定义变量,后面在使用变量时需要使用 $(variable) 的形式。
2. makefile文件中的命令执行后默认回显,如果不需要回显则在命令前面加上@。
BIN=mytest
SRC=$(shell ls *.c)
OBJ=$(SRC:.c=.o)
CC=gcc
RM=rm -f $(BIN):$(OBJ) $(CC) $(OBJ) -o $(BIN)
.PHONY:clean
clean:$(RM) $(OBJ) $(BIN)
编写系统程序---进度条
回车与换行
1. 回车:返回到这一行的行首。
2. 换行:直接跳到下一行,并不会回到行首。
3. C/C++中的\n兼具有回车和换行的功能。
缓冲区
1. 向显示器打印信息时,只有强制刷新或者程序运行结束之后才会执行。
2. \n兼具有强制刷新的功能。
3. fflush(stdout)函数可以强制刷新当前显示器。
完整代码
test.h
#include <stdio.h>
#include <unistd.h>void flush_progress(double total,double current);
test.c
#include "test.h"void flush_progress(double total,double current)
{char nums[1001]={0};double rate=(current*100/total); int num=(int)rate; int i=0; for(i=0;i<num;i++){ nums[i]='#'; } printf("[%-100s][%.2lf%%]\r",nums,rate);fflush(stdout);
}
main.c
#include "test.c"
double total=1024.0;
double speed=2.0;
double current=0;void download()
{while(current<=total){flush_progress(total,current); usleep(40000);current+=speed;}printf("\n");
}int main()
{download();return 0;
}
致谢
感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!