目录
Linux编译器-gcc/g++使用
1.背景知识
Linux中头文件的目录在
Linux 库
条件编译的典型应用
2.gcc如何完成
动态库 vs 静态库
debug && release
Linux项目自动化构建工具-make/Makefile
背景
用法
特殊符号
Linux编译器-gcc/g++使用
1.背景知识
- 预处理(去注释,头文件展开,条件编译,宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 连接(生成可执行文件或库文件)
Linux中头文件的目录在
/usr/include/
可如下进行查看
Linux 库
Linux中:.so(动态库) .a(静态库) .iso(镜像文件的后缀)
windows:.dll(动态库) .lib(静态库)
动态库就像一个网吧,所有人都可以去上网,也就是一个共享库,因此动态库不能缺失,一旦对应的动态库缺失,影响的不止一个程序,可能导致很多程序都无法正常运行。
静态库就像一个电脑店,每个人需要上网时,买一台电脑回家,也就是编译器使用静态库进行静态链接的时候,会将自己的方法拷贝到目标程序,该程序以后不再依赖静态库
在Linux中库有自己的命名规则
libname.so.XXX //红色部分为库名字,需要去掉前缀后缀
在编译型语言,安装开发包,就是下载安装 对应的头文件+库文件,而方法的实现就是在库当中。库其实就是把源文件(.c)经过一定的编译,然后打包,只给一个文件即可,不用提供太多的文件。--这样做也可以达到隐藏源文件的目的
头文件提供方法的声明,库文件提供方法的实现+我们自己写的代码 ==>> 软件
条件编译的典型应用
我们安装软件通常有社区版和开发版,根据不同的编译条件,裁剪掉社区版不需要的功能即可
2.gcc如何完成
编译的c语言的代码,会自己链接c库
gcc 选项
- -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
- -S 编译到汇编语言不进行汇编和链接
- -c 编译到目标代码
- -o 文件输出到 文件
- -static 此选项对生成的文件采用静态链接
- -g 生成调试信息。GNU 调试器可利用该信息。
- -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
- -O0
- -O1
- -O2
- -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
- -w 不生成任何警告信息。
- -Wall 生成所有警告信息。
格式
gcc [选项] 要编译的文件 [选项] [目标文件]
gcc -E mycode.c -o mycode.i //只进行预处理
- -E 告诉gcc,从现在开始进行程序的翻译,将预处理工作做完就停下来,不要往后走了。
- -o 后面跟要形成的文件,否则会直接输出在屏幕上
gcc -S mycode.i -o mycode.s
- -S 从现在开始进行程序的翻译,将编译的工作做完就停下来
gcc -c mycode.s -o mycode.o
-c 从现在开始进行程序的翻译,将汇编的工作做完就停下来,mycode.o是可重定位目标二进制文件,简称目标文件,即windows下的obj的文件,该文件虽然已经是二进制了,但是还不能独立执行,需要经过链接才能执行
gcc mycode.o -o mytest
将可重定向目标二进制文件 和 库进行链接形成可执行程序
//PS 上述选项通过 Esc 按键进行记忆
那么上述.o和库是如何链接的 ?
gcc编译的时候,默认使用动态链接,如果要按照静态链接的方式,进行形成可执行程序,需要添加 -static 选项
安装c语言静态库
yum install -y glibc-static
安装c++语言静态库
yum install -y libstdc++-static
- 如果我们没有静态库,但是我们要-static是不行的
- 如果我们没有动态库,只有静态库,不加-static ,gcc能找到静态库,gcc默认优先动态链接,-static的本质是:改变优先级
- 不一定是纯的全部动态链接或者静态链接,一般是混合的
动态库 vs 静态库
动态库因为是共享库,因此可以有效的节省资源(磁盘空间,内存空间,网络空间)【优点】,动态库一旦缺失,会导致整个程序都无法运行【缺点】
静态库,不依赖库,一旦形成可执行程序,可以独立运行【优点】,体积大,比较消耗资源【缺点】
debug && release
gcc默认形成的是release版本,-g 以debug版本
debug版本可以被追踪调试,因为形成可执行程序的时候,添a加了debug信息。
可执行程序形成的时候,不是无序的二进制构成,有自己的二进制格式--ELF格式
Linux项目自动化构建工具-make/Makefile
背景
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的
- 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂 的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命 令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
- make是一条命令,makefile是一个当前目录下的文件,两个搭配使用,完成项目自动化构建。
用法
在当前目录下创建一个makefile文件
mycode:mycode.c //依赖关系,mycode.c 编译成mycode
gcc -o mycode mycode.c //依赖方法,怎么编译
clean: //清理,:右边没有东西表示不依赖任何文件
rm -f mycode
为了更好的理解编译过程,上述依赖关系/依赖方法可细写成
mycode:mycode.o
gcc -o mycode mycode.o
mycode.o:mycode.s
gcc -c mycode.s -o mycode.o
mycode.s:mycode.i
gcc -S mycode.i -o mycode.s
mycode.i:mycode.c
gcc -E mycode.c -o mycode.i
clean:
rm -f mycode.i ……
//编译 ,make会自动推导makefile中的依赖关系栈式结构
make
//清理
make clean
- make一般自顶向下匹配,如果将clean放到前面,make将执行清理工作,所以一般不将clean放到前面
- make之后,如果代码未修改,重复make不会再编译,以此来提高编译效率,那make是怎么做到的呢?一定是源文件形成可执行文件,也就是说先有源文件,才有可执行文件,一般而言源文件的修改时间 比 可执行文件要早的!!如果我们更改了源文件,历史上还有可执行文件,那么源文件的最近修改时间,一定要比可执行程序要新!因此,只需要比较可执行程序的最近修改时间 和 源文件的最近修改时间 .exen 新于 .c 就不需要重新编译,反之就需要重新编译
要时make每次都编译,可以在makefile文件中
.PHONY:伪文件
.PHONY:mycode //让对应的依赖关系总是被执行
mycode:mycode.c //依赖关系,mycode.c 编译成mycode
gcc -o mycode mycode.c //依赖方法,怎么编译
clean: //清理,:右边没有东西表示不依赖任何文件
rm -f mycode
不过一般依赖关系不用伪文件修饰, 伪文件用来修饰clean,即
.PHONY:clean
clean: //清理,:右边没有东西表示不依赖任何文件
rm -f mycode
特殊符号
mycode:mycode.c
gcc -o $@ $^ //$@表示依赖关系左边的内容,$^表示依赖关系右边的内容
如果不想make的时候,界面回显依赖方法,可将依赖方法前+@ ,如
mycode:mycode.c //依赖关系,mycode.c 编译成mycode
@gcc -o mycode mycode.c //依赖方法,怎么编译