文章目录
- 1->编译器gcc/g++
- 1.1 基础知识
- 1.2 gcc编译选项
- 1.2.1 预处理(进行宏替换/去注释/条件编译/头文件展开等)
- 1.2.2 编译(生成汇编)
- 1.2.3 汇编 (生成机器可识别代码)
- 1.2.4 链接(生成可执行文件或库文件)
- 1.3 动态链接和静态链接
- 1.4 动态库和静态库
- 1.5 gcc其他常用选项---了解即可
- 2->自动化建构make/Makefile
- 2.1 对make和Makefile的理解
- 2.2 Makefile文件
- 2.3 make是如何工作的
- 结尾
1->编译器gcc/g++
1.1 基础知识
预处理:进行宏替换/去注释/条件编译/头文件展开等
编译:生成汇编
汇编:生成机器可识别代码
链接: 生成可执行文件或库文件
1.2 gcc编译选项
格式:
gcc[选项]要编译的文件[选项]目标文件1.2.1 预处理(进行宏替换/去注释/条件编译/头文件展开等)
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。预处理指令是以#号开头的代码行。
• 实例: gcc -E hello.c -o hello.
gcc-E hello.c-o hello.i选项 “-E” ,该选项的作用是让 gcc 在预处理结束后停止编译过程。
选项 “-o” 是指目标文件,“.i” 文件为已经过预处理的C原始程序。
1.2.2 编译(生成汇编)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
用户可以使用 “-S” 选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
• 实例:
gcc-S hello.i-o hello.s1.2.3 汇编 (生成机器可识别代码)
汇编阶段是把编译阶段生成的 “.s” 文件转成目标文件
读者在此可使用选项 “-c” 就可看到汇编代码已转化为 “.o” 的二进制目标代码了
• 实例:
gcc-c hello.s-o hello.o1.2.4 链接(生成可执行文件或库文件)
链接阶段本质是将.o文件合并
• 实例:
gcc hello.o-o hello1.3 动态链接和静态链接
在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个.c文件会形成一个.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接。
静态链接的缺点很明显:
浪费空间:因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;
更新比较困难:因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。
动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。动态链接其实远比静态链接要常用得多。
1.4 动态库和静态库
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件,如下所示。gcc hello.o -o hello
gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。
注意:
Linux下,动态库XXX.so,静态库XXX.a
Windows下,动态库XXX.dll,静态库XXX.lib
动静态库对比:
1.动态库形成的可执行程序体积一定很小
2.可执行程序对静态库的依赖度小,动态库不能缺失
3.程序运行,需要加载到内存,静态链接的,会在内存中出现大量的重复代码。
4.动态链接,比较节省内存和磁盘资源。
1.5 gcc其他常用选项—了解即可
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统有动态库.
-O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。
2->自动化建构make/Makefile
2.1 对make和Makefile的理解
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
2.2 Makefile文件
myproc:myproc.c//依赖关系gcc-o myproc myproc.c//依赖方法.PHONY:clean//伪目标clean://依赖关系rm-f myproc//依赖方法依赖关系:上面的文件myproc,它依赖myproc.c
依赖方法:gcc -o myproc myproc.c ,就是与之对应的依赖关系
项目清理:
工程是需要被清理的
像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。
2.3 make是如何工作的
myproc:myproc.o gcc myproc.o-o myproc myproc.o:myproc.s gcc-c myproc.s-o myproc.o myproc.s:myproc.i gcc-S myproc.i-o myproc.s myproc.i:myproc.c gcc-E myproc.c-o myproc.i.PHONY:clean clean:rm-f*.i*.s*.o myproc编译:
$ make gcc-E myproc.c-o myproc.i gcc-S myproc.i-o myproc.s gcc-c myproc.s-o myproc.o gcc myproc.o-o myproc在默认的方式下,也就是我们只输入make命令。那么:
1.make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2.如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到 myproc 这个文件,并把这个文件作为最终的目标文件。
3.如果 myproc 文件不存在,或是 myproc 所依赖的后面的 myproc.o 文件的文件修改时间要比 myproc 这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成 myproc 这个文件。
4.如果 myproc 所依赖的 myproc.o 文件不存在,那么 make 会在当前文件中找目标为 myproc.o 文件的依赖性,如果找到则再根据那一个规则生成 myproc.o 文件。(这有点像一个堆栈的过程)
5.当然,你的C文件和H文件是存在的啦,于是 make 会生成 myproc.o 文件,然后再用 myproc.o 文件声明 make 的终极任务,也就是执行文件 hello 了。
6.这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7.在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8.make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
结尾
uu们,本文的内容到这里就全部结束了,道尔在这里再次感谢您的阅读!
👀【关注】跟随我一起深耕技术领域,见证每一次成长。 ❤️【点赞】让优质内容被更多人看见,让知识传递更有力量。 ⭐【收藏】把核心知识点存好,在需要时随时查、随时用。 💬【评论】分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主“一键四连”哦! |
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!