Linux中编译代码(gcc/g++),自动化构建(make/Makefile)

发布时间:2026/7/10 15:42:10

Linux中编译代码(gcc/g++),自动化构建(make/Makefile) 引言详细介绍Linux下代码是如何编译。详细介绍自动化构建make/Makefile的使用。一、简单认识gcc/ggccC编译器只能用来编译C语言的代码gC/C编译器都可以编译两者的使用完全一样下面以gcc来介绍。二、详细讲解可以先看一下这篇博客再看下面的内容。一篇文章带你搞懂编译和链接-CSDN博客编译可以分成三个步骤预处理有些书也叫预编译、编译、汇编三个过程。1.预处理头文件展开去注释宏替换条件编译对代码做裁减等等等等上面那篇博客有详细介绍语法code.c: 1 #includestdio.h 2 3 int main() 4 { 5 6 printf(hello word\n); 7 8 return 0; 9 } [zhangsanhcss-ecs-f571 dir1]$ vim code.c //写入代码 //对conde.c文件进行预处理操作-E是选项-o是重新命名为code.i [zhangsanhcss-ecs-f571 dir1]$ gcc -E code.c -o code.i [zhangsanhcss-ecs-f571 dir1]$ ll total 24 -rw-rw-r-- 1 zhangsan zhangsan 81 Aug 27 14:30 code.c -rw-rw-r-- 1 zhangsan zhangsan 16877 Aug 27 14:33 code.i [zhangsanhcss-ecs-f571 dir1]$-E程序开始翻译做完预处理就停止。可以用vim打开code.i文件看到里面的内容很长是把stdio.h这个文件给展开了。2.编译把C-汇编语言等等语法[zhangsanhcss-ecs-f571 dir1]$ gcc -S code.i -o code.s [zhangsanhcss-ecs-f571 dir1]$ ll total 28 -rw-rw-r-- 1 zhangsan zhangsan 81 Aug 27 14:30 code.c -rw-rw-r-- 1 zhangsan zhangsan 16877 Aug 27 14:33 code.i -rw-rw-r-- 1 zhangsan zhangsan 446 Aug 27 14:40 code.s [zhangsanhcss-ecs-f571 dir1]$-S编译到汇编语言就停止不进行汇编和链接可以打开code.s查看里面是汇报语言3.汇编把汇编语言翻译成二进制文件o可重定位目标二进制文件语法[zhangsanhcss-ecs-f571 dir1]$ gcc -c code.s -o code.o [zhangsanhcss-ecs-f571 dir1]$ vim code.o-c把汇编语言翻译成二进制文件就停止可以用vim打开里面是乱码因为是二进制文件。注意该二进制文件不能直接运行只有声明没有定义还需要和库链接后才可以正常运行。4.链接形成可执行文件语法[zhangsanhcss-ecs-f571 dir1]$ gcc code.o -o code [zhangsanhcss-ecs-f571 dir1]$ ll total 44 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 14:48 code -rw-rw-r-- 1 zhangsan zhangsan 81 Aug 27 14:30 code.c -rw-rw-r-- 1 zhangsan zhangsan 16877 Aug 27 14:33 code.i -rw-rw-r-- 1 zhangsan zhangsan 1496 Aug 27 14:44 code.o -rw-rw-r-- 1 zhangsan zhangsan 446 Aug 27 14:40 code.s [zhangsanhcss-ecs-f571 dir1]$ ./code hello word [zhangsanhcss-ecs-f571 dir1]$可以看到代码正常运行。所以可以直接这样[zhangsanhcss-ecs-f571 dir1]$ gcc code.c -o code [zhangsanhcss-ecs-f571 dir1]$ ll total 16 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 14:54 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c [zhangsanhcss-ecs-f571 dir1]$ ./code hello word [zhangsanhcss-ecs-f571 dir1]$三、gcc其他选项•-E 只激活预处理,这个不生成文件需要把它重定向到⼀个输出文件里面(.i)•-S 编译到汇编语言.s不进行汇编和链接•-c 编译到目标代码.o•-o 文件内容输出到后面的文件中•-static 此选项对生成的文件采用静态链接•-g 生成调试信息。GNU调试器可利用该信息。•-shared 此选项将尽量使用动态库所以生成文件比较小但是需要系统有动态库.•-O0•-O1•-O2•-O3编译器的优化选项的4个级别-O0表示没有优化,-O1为缺省值-O3优化级别最高•-w 不生成任何警告信息。•-Wall 生成所有警告信息。四、自动化构建•一个工程中的源文件不计数其按类型、功能、模块分别放在若干个目录中makefile定义了一系列的规则来指定哪些文件需要先编译哪些文件需要后编译哪些文件需要重新编译甚至于进行更复杂的功能操作•makefile带来的好处就是⸺“自动化编译”一旦写好只需要一个make命令整个工程完全自动编译极大的提高了软件开发的效率。• make是⼀个命令工具是一个解释 makefile 中指令的命令工具⼀般来说大多数的IDE都有这个命令比如Delphi的makeVisualC的nmakeLinux下GNU的make。makefile 成为了一种在工程方面的编译方法。•make是⼀条命令makefile是⼀个文件两个搭配使用完成项目自动化构建。这里推荐使用Makefile作为文件名。1.基本使用Makefile文件中1 code:code.c 2 gcc -o code code.c直接输入make来运行Makefile文件中的内容。zhangsanhcss-ecs-f571 dir1]$ make gcc -o code code.c [zhangsanhcss-ecs-f571 dir1]$ ll total 20 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 15:11 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 32 Aug 27 15:11 Makefile [zhangsanhcss-ecs-f571 dir1]$ ./code hello word2.依赖关系和依赖方法上面的Makefile文件中code是目标文件后面的内容是依赖文件列表也就是说code依赖code.c依赖方法就是下面一行的语句语法规定以Table键开始3.详细学习Makefile的语法3.1先看一个小案例Makefile中的内容Makefile 1 code:code.o 2 gcc code.o -o code 3 code.o:code.s 4 gcc -c code.s -o code.o 5 code.s:code.i 6 gcc -S code.i -o code.s 7 code.i:code.c 8 gcc -E code.c -o code.i使用make[zhangsanhcss-ecs-f571 dir1]$ vim Makefile [zhangsanhcss-ecs-f571 dir1]$ make gcc -E code.c -o code.i gcc -S code.i -o code.s gcc -c code.s -o code.o gcc code.o -o code [zhangsanhcss-ecs-f571 dir1]$ ll total 48 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 15:42 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 16875 Aug 27 15:42 code.i -rw-rw-r-- 1 zhangsan zhangsan 1496 Aug 27 15:42 code.o -rw-rw-r-- 1 zhangsan zhangsan 446 Aug 27 15:42 code.s -rw-rw-r-- 1 zhangsan zhangsan 149 Aug 27 15:42 Makefile [zhangsanhcss-ecs-f571 dir1]$可以看到make会根据Makefile中的依赖关系进行推导直到推导出目标文件可以看到是一个栈的结构称之为推到栈。先根据依赖方法入栈然后依次出栈3.2PHONY项目清理Makefile 1 code:code.c 2 gcc -o code code.c 3 4 .PHONY:clean 5 clean: 6 rm -f code• 工程是需要被清理的• 像clean这种没有被第一个目标文件直接或间接关联那么它后面所定义的命令将不会被自动执行不过我们可以显示要make执行。即命令⸺“make clean”以此来清除所有的目标文件以便重编译。• 但是一般我们这种clean的目标文件我们将它设置为伪目标,用 .PHONY修饰,伪目标的特性是总是被执行的。[zhangsanhcss-ecs-f571 dir1]$ make clean rm -f code [zhangsanhcss-ecs-f571 dir1]$ ll total 8 -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 65 Aug 27 16:10 Makefile [zhangsanhcss-ecs-f571 dir1]$为什么第一次的make后面不需要跟东西呢而clean 需要make clean因为make默认执行前面第一个命令Makefile文件Makefile 1 .PHONY:clean 2 clean: 3 rm -f code 4 5 eode:code.c 6 gcc -o code code.c 7make默认执行第一个命令[zhangsanhcss-ecs-f571 dir1]$ make rm -f code为什么PHONY总是被执行.PHONY: 让make忽略源文件和可执行目标文件的Modify时间对比默认是根据时间对比文件内容不变就只执行一次。而.PHONY可以让make忽略源文件和可执行目标文件的Modify时间对比4.实用语法得会1.在依赖语句前面加上可以使语句不用回显。code:code.c gcc -o code code.c .PHONY:clean clean: rm -f code没有回显[zhangsanhcss-ecs-f571 dir1]$ vim Makefile [zhangsanhcss-ecs-f571 dir1]$ ll total 20 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 16:32 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 82 Aug 27 16:32 Makefile2.可以定义变量Makefile文件1 BINcode 2 SRCcode.c 3 4 5 $(BIN):$(SRC) #提取内容 6 gcc -o code code.c 7 8 .PHONY:clean 9 clean: 10 rm -f $(BIN) 11 12可以正常运行[zhangsanhcss-ecs-f571 dir1]$ make [zhangsanhcss-ecs-f571 dir1]$ ll total 20 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 16:42 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 121 Aug 27 16:41 Makefile [zhangsanhcss-ecs-f571 dir1]$依赖关系也可以替换1 BINcode 2 SRCcode.c 3 4 5 $(BIN):$(SRC) #提取内容 6 gcc -o $ $^ #对应目标文件^对应源文件,$取里面的内容 7 8 .PHONY:clean 9 clean: 10 rm -f $(BIN)[zhangsanhcss-ecs-f571 dir1]$ make [zhangsanhcss-ecs-f571 dir1]$ ll total 20 -rwxrwxr-x 1 zhangsan zhangsan 8360 Aug 27 16:49 code -rw-rw-r-- 1 zhangsan zhangsan 76 Aug 27 14:53 code.c -rw-rw-r-- 1 zhangsan zhangsan 181 Aug 27 16:48 Makefile当有多个源文件时创建100个源文件[zhangsanhcss-ecs-f571 dir1]$ touch src{1..100}.c自动获取.c为后缀的文件2 SRC$(shell ls *.c)最佳实践用这个3 SRC$(wildcard *.c) #wildcard函数获取当前目录下的所有的.c源文件实用语法4 OBJ$(SRC:.c.o) #语法把文件的.c后缀改成.o后缀处理多个.c文件时先统一处理成.o文件最后再一起链接。Makefile文件中的内容1 BINcode 2 SRC$(wildcard *.c) 3 OBJ$(SRC:.c.o) 4 5 $(BIN):$(OBJ) 6 gcc -o $ $^ 7 echo -----$^ to $---- 8 %.o:%.c #可以展开文件 9 gcc -c $ #可以依次取出源文件 10 echo .....$- to $.....最终模式1 BINcode 2 SRC$(wildcard *.c) 3 OBJ$(SRC:.c.o) 4 CCgcc 5 Echoecho 6 Rmrm -rf 7 8 9 $(BIN):$(OBJ) 10 $(CC) -o $ $^ 11 $(Echo) linking $^ to $ ... done 12 %.o:%.c #可以展开文件 13 $(CC) -c $ #可以依次取出源文件 14 $(Echo) compling $ to $ ... done 15 16 .PHONY:clean 17 clean: 18 $(Rm) $(BIN) $(OBJ)5.细节make的执行规则是只生成所有目标对象中的第一个当然make会根据语法规则递归生成第一个目标对象的所有依赖对象后再回头生成第一个目标对象生成后退出。make在执行makefile规则中根据语法规则会分析目标对象与依赖对象的时间信息判断是否在上一次生成后源文件发生了修改若发生了修改才需要重新生成。makefile中的伪对象表示对象名称并不代表真正的文件名与实际存在的同名文件没有相互关系因此伪对象不管同名目标文件是否存在都会执行对应的生成指令。伪对象的作用有两个1. 使目标对象无论如何都要重新生成。2. 并不生成目标文件而是为了执行一些指令。makefile中使用 .PHONY 来声明伪对象 .PHONY: clean。makefile文件中保存了编译器和链接器的参数选项并且描述了所有源文件之间的关系。make程序会读取makefile文件中的数据然后根据规则调用编译器汇编器链接器产生最后的输出。Makefile里主要包含了五个东西显式规则、隐晦规则、变量定义、文件指示和注释。显式规则说明了如何生成一个或多个目标文件。make有自动推导的功能所以隐晦的规则可以让我们比较粗糙地简略地书写makefile比如源文件与目标文件之间的时间关系判断之类。在makefile中可以定义变量当makefile被执行时其中的变量都会被扩展到相应的引用位置上通常使用 $(var) 表示引用变量。文件指示。包含在一个makefile中引用另一个makefile类似C语言中的include;注释makefile中可以使用 # 在行首表示行注释。默认的情况下make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件。

相关新闻