
Linux工具文章目录Linux工具前言gcc一、背景知识二、使用介绍1.预处理2.编译3.汇编4.链接三、动静态库与动静态链接1.动静态链接2.动静态库自动化构建-make/Makefile一、基本介绍二、使用1.展示2.具体分析3. 【.PHONY:】的细节部分三、进阶多文件编译四、细节前言上次我们详细讲了vim编辑器但是当你想运行该代码你必须编译该代码。所以我接下来会详细介绍vim的编译器gccg。同时一个工程中的源文件不计其数其按类型、功能、模块分别放在若干个目录中如果一个个都用gcc来编译效率太过低下这时就需要makefile来工作。makefile 定义了一系列的规则来指定哪些文件需要先编译哪些文件需要后编译哪些文件需要重新编译甚至于进行更复杂的功能操作。gcc一、背景知识我们知道对于一段程序来说其编译过程分为四个阶段1. 预处理进行宏替换/去注释/条件编译/头文件展开等)2. 编译生成汇编)3. 汇编生成机器可识别代码4. 链接生成可执行文件或库文件)。每个阶段都生成不同文件而gcc的工作就是将这些文件分阶段处理的过程。二、使用介绍基本的格式格式gcc [选项] 要编译的文件 [选项][指定生成的目标文件]1.预处理预处理功能主要包括宏定义文件包含条件编译去注释等。预处理指令是以 #号开头的代码行。实例:gcc –E hello.c –o hello.i选项 “-E”, 该选项的作用是让 gcc 在预处理结束后停止编译过程。选项 “-o” 是指目标文件“.i” 文件为已经过预处理的 C 原始程序。2.编译在这个阶段中gcc 首先要检查代码的规范性、是否有语法错误等以确定代码的实际要做的工作在检查无误后gcc 把代码翻译成汇编语言。用户可以使用 “-S” 选项来进行查看该选项只进行编译而不进行汇编生成汇编代码。实例:gcc –S hello.i –o hello.s3.汇编汇编阶段是把编译阶段生成的 “.s” 文件转成目标文件读者在此可使用选项 “-c” 就可看到汇编代码已转化为 “.o” 的二进制目标代码了实例:gcc –c hello.s –o hello.o4.链接在成功编译之后就进入了链接阶段。实例:gcc hello.o –o hello注意日常中我们想快速使用可以直接格式gcc 要编译的文件 [-o][指定生成的目标文件]./目标文件便可以快速进行编译工作以此来运行代码。三、动静态库与动静态链接1.动静态链接在我们的实际开发中不可能将所有代码放在一个源文件中所以会出现多个源文件而且多个源文件之间不是独立的而会存在多种依赖关系如一个源文件可能要调用另一个源文件中定义的函数但是每个源文件都是独立编译的即每个*.c文件会形成一个*.o文件为了满足前面说的依赖关系则需要将这些源文件产生的目标文件进行链接从而形成一个可以执行的程序。这个链接的过程就是静态链接。静态链接的缺点很明显浪费空间因为每个可执行程序中对所有需要的目标文件都要有一份副本所以如果多个程序对同一个目标文件都有依赖如多个程序中都调用了printf()函数则这多个程序中都含有printf.o所以同一个目标文件都在内存存在多个副本更新比较困难因为每当库函数的代码修改了这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是在可执行程序中已经具备了所有执行程序所需要的任何东西在执行的时候运行速度快。动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独立部分在程序运行时才将它们链接在一起形成一个完整的程序而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。当然动态链接比静态链接启动速度更慢。2.动静态库我们的C程序中并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。静态库是指编译链接时把库文件的代码全部加入到可执行文件中因此生成的文件比较大但在运行时也就不再需要库文件了。其后缀名一般为 “.a”所以速度快。动态库与之相反在编译链接时并没有把库文件的代码加入到可执行文件中而是在程序执行时由运行时链接文件加载库这样可以节省系统的开销。因此速度减慢。动态库一般后缀名为 “.so”, 如前面所述的 libc.so.6 就是动态库。注意3. gcc 默认生成的二进制程序是动态链接的这点可以通过file命令证明。4. gcc 在编译时默认使用动态库。完成了链接之后gcc 就可以生成可执行文件如下所示。gcc hello.o –o hello5. 当然你想强行使用静态库也行。后置加stastic前提是你得有静态库。自动化构建-make/Makefile一、基本介绍makefile 带来的好处就是 ——“自动化编译”一旦写好只需要一个 make 命令整个工程完全自动编译极大的提高了软件开发的效率。make 是一个命令工具是一个解释 makefile 中指令的命令工具一般来说大多数的 IDE 都有这个命令比如Delphi 的 makeVisualC 的 nmakeLinux 下 GNU 的 make。可见makefile 都成为了一种在工程方面的编译方法。会不会写makefile从一个侧面说明了一个人是否具备完成大型工程的能力。二、使用1.展示make 是一条命令makefile 是一个文件两个搭配使用完成项目自动化构建。如上图所示makefie是一个文件我们往里面写入我们的命令再通过make就可以执行该指令。从而进行编译操作。2.具体分析1.对于makefile文件里这个我们取名为依赖关系。即tt.exe的形成依赖于tt.c。冒号左边的tt.exe取名为目标文件右边的tt.c取名为依赖文件列表。而这个被我们取名为依赖方法即tt.exe怎么得到tt.c。注意依赖方法的编写必须以Tab键的空格行后编写这是硬性要求。2.我们再使用make时可能会发生一种现象当我们不断make后发现无法执行命令。那是因为我们的项目没有清理对于vs有我们的清理解决方案但是在Linux下我们都得自己构建这时就需要伪目标 .PHONY。其作用为如果目标不是一个真实存在的文件只是一个操作名比如清理、安装需要声明为伪目标避免和目录下同名的文件冲突比如存在文件 clean 时make clean 会失效明确告诉 make这不是生成文件只是执行对应命令。此时你就可以清理文件了从而不断make。3. 【.PHONY:】的细节部分由.PHONY:修饰的目标文件总是可执行的clean由于被其修饰所以可以不断进行操作原因我们知道.C文件总是在.exe文件生成之前就有系统根据这个来裁定.C文件是否被修改如果.C文件在.exe文件之后那么说明文件修改。而我们的.PHONY:的功能其实就是忽视这个时间比较使用场景我们的.exe文件也可以进行.PHONY:这样就可以无限make但是如果代码没有被修改我们还进行make操作就会造成资源浪费。所以我们最后对没有资源分配的指令进行修饰。注意这里如果.C文件你修改里面的内容和属性那样也会造成时间变化从而可以进行make命令即编译操作。三、进阶这里我们只是知道makefile的基本功能并没有看出其的简便性下面我来介绍指令来看看其的高效。在上文中我们发现进行make操作时其会自动复述指令。在前面加上就可以只执行内容。定义变量你可以定义变量名这样就不用不断的改依赖方法只需要改变变量的值就行了。替换当你写依赖关系时可以使用$来进行替换。等价于$ : 等价于目标文件。$^:等价于依赖文件列表。多文件编译获取多个文件使用wildcard 函数获取当前所有.c文件名。将SRC的所有同名.c 替换成为.o 形成⽬标⽂件列表展开文件-%.c 展开当前目录下所有的.c文件。%.o: 同时展开所有的同名.o文件$对展开的依赖.c 文件一个一个的交给 gcc。就是不断的对.C文件编译生成.O文件。传递给OBJ。整体介绍这份Makefile用于自动化编译当前目录下所有.C语言源码文件它会自动查找目录内全部.c文件先将每个源码编译生成对应的.o目标文件再把所有目标文件链接成名为tt.exe的可执行程序同时提供clean伪目标执行清理命令可以一键删除所有生成的.o文件和tt.exe程序方便工程清理使用make命令即可自动完成编译make clean完成清理。四、细节细节 1依赖关系必须存在依赖文件列表可以为空细节 2依赖方法可以是任何 shell 命令细节 3clean 目标只是利用 make 的自动推导的能力让他执行了 rm 命令在构建工程的视角看起来就是清理项目清理项目本质就是删除不需要的临建文件细节 4make 命令后面可以跟 “目标名”后面跟谁就解析谁的依赖关系和依赖方法make 默认只会推导一条完整的推导链路make 默认只会推导第一个依赖关系对应的推导链