目录
Linux的编译器-gcc/g++
问题一:gcc有时候为什么不能编译带有for循环的c语言源文件?
问题二:gcc中c++源文件的后缀是什么?
问题三:gcc能编译c++的源文件文件吗?
问题四:如何查看自己是否拥有g++?如何安装g++?
再次理解程序的翻译过程
动态链接和静态链接
Linux项目自动化构建工具-Makefile
Linux的编译器-gcc/g++
基本概念:gcc是专门用来编译c语言的,g++可以编译c++或c语言
问题一:gcc有时候为什么不能编译带有for循环的c语言源文件?
答:gcc版本过低会不支持for循环等c99标准下的内容
解决方式:gcc 源文件名 -std=c99(-std=c99是为了让gcc支持c99中的语法)
此外,gcc还可以指定编译生成的可执行程序文件名:gcc -o 自定义名称 源文件 -std=c99
问题二:gcc中c++源文件的后缀是什么?
答:.cc、.cpp、.cxx,不能
问题三:gcc能编译c++的源文件文件吗?
答:不能,c++的源文件只能由g++来编译
指令:g++ -o my.exe test.cc -std=c++11
此外,g++也支持编译c语言的源文件,所以:g++ -o my.exe test.c -std=c99
问题四:如何查看自己是否拥有g++?如何安装g++?
答:g++ --version查看g++版本,sudo yum install -y gcc-g++指令进行g++的安装
再次理解程序的翻译过程
过程 | gcc命令 | 说明 |
预处理 | gcc -E test.c -o test.i | 宏替换、去注释、头文件展开、条件编译 |
编译 | gcc -S test.i -o test.s | 将源代码翻译成汇编语言 |
汇编 | gcc -c test.s -o test.o | 汇编语言变为机器码,生成目标文件 |
链接 | gcc test.c -o my.exe | 目标文件和库函数结合,生成形成可执行程序 |
- -E:从现在开始进行程序的翻译,预处理完成就停下
- -S:从现在开始进行程序的编译,编译完成就停下
- -c:从现在开始进行程序的翻译,汇编完成就停下
1、gcc -E test.c -o test.i:将源文件预处理后的结果放入test.i文件
2、gcc -S test.i -o test.s:将test.i文件编译后的结果放入test.s文件
3、gcc -c test.s -o test.o:将汇编语言转换为机器码,然后放入test.o文件
动态链接和静态链接
基本概念:两种不同的链接方式,用于将程序中使用的函数库与程序本身结合起来
动态链接:
- 特点:告诉了程序目标库的地址,使用该库中的内容时回去该库中调用
- 优点:节省资源
- 缺点:多个程序共享动态库,一旦动态库缺失,所有动态链接这个库的程序都无法执行了
静态链接:
- 特点:在编译时就把库中的方法拷贝到程序中,之后就不再与库产生任何联系了
- 优点:浪费资源
- 缺点:一旦形成与库无关
在Linux系统中,.so
文件是动态链接库 .a
文件是静态库,且默认情况下linux不会安装静态库
Linux项目自动化构建工具-Makefile
基本概念:会不会makefile,从侧面说明了一个人是否具备完成大型Linux工程的能力,一个工程中的源文件不计其数,它们按照类型、功能、模块分别放在若干个目录中,makefile中定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
优点:自动化编译,一旦写好,只需要一个make命令,整个工程就会进行编译,提高开发效率
主要组成部分:依赖关系 + 依赖方法
Makefile文件:
hello: hello.ogcc hello.o -o hellohello.o: hello.sgcc -c hello.s -o hello.ohello.s: hello.igcc -S hello.i -o hello.shello.i: hello.cgcc -E hello.c -o hello.i .PHONY:clean
clean:rm -f hello.i hello.s hello.o hello
- hello依赖hello.o、hello.o依赖hello.s、hello依.s赖hello.i、hello.i依赖hello.c
make的工作原理(只输入make命令):
- make会进入makefile文件
- 进入makefile后先去找第一个目标文件(找到hello并视其为最终要完成的目标文件)
- 若它不存在或它所依赖的文件的更新过,就会重编译该执行文件从而生成(更新)目标文件
- 若所依赖文件也不存在,make会尝试在后续文件列表中找到生成该文件的指令并执行
- make会一层层的去找文件的一依赖关系,直到最终编译出第一个目标文件
- 在寻找过程中,如果出现错误(最后被依赖的文件找不到)make就会直接退出并报错,对于所定义的命令的错误,若编译不成功,make不会理会
注意事项:
1、make是一个解释makefile中指令的指令工具、makefile是文件,它还可以写成Makefile
2、默认情况make会从上至下在makefile中读取目标文件,并优先选择第一个目标文件为生成对象
3、目标文件:后的内容是一个文件列表,文件列表可以为空,可以是多文件
4、程序会根据依赖关系执行依赖方法
5、.PHONY修饰的目标文件,该目标文件在每次make时一定会执行(mytest如果没被.PHONY修饰则在第二次make时会报错,如果有修饰则不会报错每次都会编译)
6、依赖方法前最好有一个tab留出空间,便于与依赖关系区分
7、目标文件是指需要被构建的最终产物或中间产物(:前的文件名)
7、make会依据目标文件中的依赖关系,进行自动推导,帮助我们执行所有相关的依赖方法
8、@和^最后会自动转化为目标文件和依赖文件列表中的文件
9、makefile也支持变量名表示文件,类似于宏定义不需要变量类型,$(变量名)提取变量
10、如果不想执行make打印出依赖方法的语句,可以在这些语句前加@
11、依赖方法后还可以跟shell命令,在命令前加上@就不会显示该命令(其余功能有待学习)
常见功能:
1、将test.c编译成目标文件mytest:
2、清除编译后的无用文件:
问题一:为什么makefile对最新的可执行程序,默认不重新形成?
答:提高编译效率,对源代码进行简单更改甚至没有更改,再次编译全部全代码浪费资源
问题二:如何做到问题一?
答:对比可执行文件最近一次的修改时间和源文件最新的修改时间,前者大于后者就重编译
touch源文件但是不对源文件进行修改也会更新源文件的修改时间,此时源文件的修改时间大于源文件此时可以再次make:
修改makefile后make指令无法执行成功的解决办法之一:
- 查看可执行程序和源文件的修改时间
- touch 源文件,再次执行make
~over~