Linux编译器-gcc/g++使用 make/makefile最基础的功能

发布于:2024-06-22 ⋅ 阅读:(79) ⋅ 点赞:(0)

一.引例:

C语言

下面代码可能编不过去
在这里插入图片描述
因为编译器的版本没达到,需要手动改版本
在这里插入图片描述
默认形成的可执行文件是a.out
在这里插入图片描述
也可以更改形成的文件名-o 是object的意思,后缀随便加

gcc test.c -o my.exe -std=c99

在这里插入图片描述

C++

C++文件后缀不仅仅有.cpp和.cc,还有很少见到的.cxx
gcc不能编译C++的代码,但g++能编译C的代码

g++ test.cpp -o my.exe -std=c++11

二.程序翻译的过程

在这里插入图片描述

预处理

预处理把头文件直接展开,10来行变成800多行
在这里插入图片描述
Linux里面有库才能使用头文件,并且预处理之后文件展开的位置能之间看到库存在哪
在这里插入图片描述
预处理阶段宏会被替换,注释也被去掉
在这里插入图片描述

条件编译

引例:同样一种软件,有社区版,专业版,免费版。
那么维护代码的时候需要维护几份源代码?
维护一份代码即可,怎么做到的?
以以下代码为例
在这里插入图片描述
运行就会发现只打印了部分
在这里插入图片描述
预处理就被裁了
在这里插入图片描述
然后再做一下改变V1随便给个值

#include <stdio.h>                                                                                                
  2 #define V1 1                               
  3                                            
  4 int main()                                 
  5 {                                          
  6 #ifdef V1                                  
  7     printf("功能1\n");                     
  8 #elif V2                                   
  9     printf("功能1\n");                     
 10     printf("功能2\n");                     
 11 #else                                      
 12     printf("功能1\n");                     
 13     printf("功能2\n");                     
 14     printf("功能3\n");                     
 15 #endif                                     
 16     return 0;                              
 17 }    

运行
在这里插入图片描述
其中#ifdef #elif 等就是条件编译
这样裁剪可以定义出不同版本的软件
宏也可以在外面定义

gcc -D V1=1 proj.c -o filename

在这里插入图片描述

编译

gcc -S test.i -o test.s -std=c99

很明显,就是汇编语言
在这里插入图片描述

汇编

gcc -c test.s -o test.o

就是.obj结尾的文件
在这里插入图片描述
形成二进制的目标文件
在这里插入图片描述
还是运行不了
在这里插入图片描述

链接

gcc test.o -o my.exe

就可以直接运行了
在这里插入图片描述

三.链接–动静态链接

链接是什么?

程序与库结合的过程
引例:从零开始写代码,假设设计一个printf函数,设计好了大半个月过去了,效率比较低,所以语言设计者把一些公共的方法抽取出来,放进自己的标准库
下面的指令是查看文件掉用了哪些动态库

ldd filename

在这里插入图片描述
查看画横线的文件,没形成C语言库之前就是C语言的源代码,被顶级程序员打包成库
在这里插入图片描述
我们怎么知道C标准库里面有什么?所以就有一批对应的头文件,方便调用
在这里插入图片描述
所以安装开发环境:安装C标准库 + C头文件

动静态库

在这里插入图片描述

为什么要有库?

让个开发站在巨人的肩膀
提高开发效率

怎么办?

故事:

在这里插入图片描述 在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
故事来到第二阶段:张三去不了网吧了(无法调用动态库),计划不能完整的执行了
在这里插入图片描述
第三阶段:
在这里插入图片描述

总结:所有动态链接都需要跑到库中执行,然后返回,静态链接不需要

证明:

C动态库,是默认提供的
gcc默认形成的可执行程序,默认采用动态链接
在这里插入图片描述
ls命令也是同理
在这里插入图片描述
要是删掉的话,就相当于上述故事中的警察查封网吧,大部分指令都运行不了了
静态库的位置,以.a结尾
在这里插入图片描述

优缺点

下面的指令是查看文件详细信息

file filename

在这里插入图片描述
动态库与动态链接的优缺点:
1.不能丢失(网吧不能去了就玩不了)
2.节省资源(网吧的电脑共用)
静态库与静态库的优缺点:
1.一旦形成就与库无关(自己有电脑就不用去网吧了)
2.浪费资源(自己的电脑自己用)
验证:
查看静态库的指令(mytest-static是形成test.c静态库的名称,名字随便取)

gcc -o mytest-static test.c -static -std=c99

会发现运行不了,找不到C语言的静态库
在这里插入图片描述
是因为默认情况下,Linux上一般静态库都是默认没有安装的
yum安装即可

sudo yum install -y glibc-static libstdc++-static

对比一下:
在这里插入图片描述
文件大小上静态比动态大很多
在这里插入图片描述

静态链接的应用场景

提高可移植性,比如直接把二进制代码从这个A机器到B机器,跨平台性提高,不依赖动态库,不用做过多的环境监测

四.make/makefile

原理:

make是一个命令
makefile是一个文件
创建makefile和创建普通文件的命令是一样的

touch makefile

以下代码为例
在这里插入图片描述
效果就是下面
在这里插入图片描述
在这里插入图片描述

关于依赖关系和依赖方法的理解,这里讲一个小故事:
月底了,身为大学生的你没钱了,拨通了父亲的电话:我是你儿子,然后你挂了电话。
我是你儿子这句话就表明了依赖关系,但是目的没达成,所以只有依赖关系没用
然后又打通电话:我是你儿子,没钱了打钱。你父亲就明白了
这就是表明了依赖关系又表明了依赖方法
发现在前面使用的时候,make是运行的第一段,make clean是第二段,同时make mytest也可以运行第一段
在这里插入图片描述
因为make是从上面向下运行的
在这里插入图片描述
把makefile反过来验证一下:
在这里插入图片描述
在这里插入图片描述
至于.PHONY是什么意思这里讲解一下:
以下面的makefile文件为例

mytest:test.c
	gcc -o mytest test.c                                                                                            
clean:
	rm -f mytest 

会发现第二次make的时候会说:此文件已经是最新的
在这里插入图片描述
但如果更改test.c的内容后,就可以再次make。
因为系统认为test.c已经编译过了,且没有最新的更改,所以没必要执行。
加了.PHONY后就可以一直执行

.PHONY:mytest                                                                                                     
mytest:test.c
	gcc -o mytest test.c
clean:
  	rm -f mytest

在这里插入图片描述
.PHONY:XXX
表示XXX对应的方法,总要被执行的
一般写makefile的时候,形成可执行程序,源代码没有更新,没有必要编译
清理项目希望是被总是执行的,因为有些文件想要清理干净

为什么makefile对最新的可执行程序,默认不想重新生成呢?

假设一个项目有两千个源文件,很小的一部分需要做改动,如果全部编译效率很慢。
提高编译效率

makefile怎么知道我的程序需要被编译了呢?

源文件的更改时间和可执行程序更改的时间是不一样的
源文件:
在这里插入图片描述
可执行文件:
在这里插入图片描述
对比可执行文件的最近修改时间和源文件最近的修改时间,判断谁最新?
以此来判断是否需要编译文件

在这里插入图片描述
.PHONY的意思是直接编,不用比较
平时在写VS的时候,有时候会出错,清理重新编译后,就可以执行。原因就是不同的环境更新时间的策略不一样。


网站公告

今日签到

点亮在社区的每一天
去签到