Makefile学习记录 |
您所在的位置:网站首页 › subst 命令 › Makefile学习记录 |
最近又把之前的makefile重新看了一遍,在日常还是用的很广泛的,因此记录一下,方便以后查阅 1、编译过程我觉得要学习Makefile就必须仔细了解编译过程,不清楚这个编译过程就不知道makefile在说什么东西,特别是对于习惯了从win平台用ide来写代码的人来说,另外就是需要了解一点点的shell知识。 关于编译过程,我总结如下图所示 主要是下面的四个阶段构成,可以把这四个过程使用gcc展示出来,可以更深刻的认识一下 使用下面的代码进行测试 #include int add(int a, int b); int minus(int a, int b); int main() { int a = 30; int b = 5; int c; c = add(a, b); printf("a+b = %d\n", c); c = minus(a, b); printf("a-b = %d\n", c); return 0; } int add(int a, int b) { return a+b; } int minus(int a, int b) { return a-b; }可以线使用预处理看一下 gcc -E main.c加上 -o指定输出文件 gcc -E main.c -o main.i 可以看到就是吧stdio.h加进来的样子(实际情况一般不需要看预处理的文件!) 查看汇编程序:gcc -S main.c -o main.s 生成汇编程序,不过实际情况也一般不需要,这里可以看到汇编还是文本,是可以直接打开的 下面看第三阶段,生成机器指令gcc -c main.c -o main.o 这个时候已经是二进制指令了,无法打开 当然我们也可以直接输出可执行文件gcc main.c -o main ,这个输出的main就直接是可执行文件了,可以尝试执行一下,结果如下所示! 回顾一下上面的过程 这里需要注意这四条语句不是相互独立的,比如直接说最后一条语句,生成可执行文件,是经过了生成.i .s .o的这几个过程的,只是他的文件没有输出出来罢了! 下面将上面的程序做一点小改动,将add 和 minus函数单独放到一个源文件中去,那我们就需要同时编译多个文件 gcc main.c add.c minus.c -o main运行结果如下,可以看到是正常的 2、编译静态库并使用编译静态库的规则如下所示 编译成 .o 的文件gcc -c [.c] -o [自定义文件名] gcc -c [.c] [.c] ... 编静态库ar -r [lib自定义库名.a] [.o] [.o] ... 链接成可执行文件gcc [.c] [.a] -o [自定义输出文件名] gcc [.c] -o [自定义输出文件名] -l[库名] -L[库所在路径]下面将上面程序依赖的两个文件加入编成静态库,如下所示 3、编译动态库并使用编译静态库的规则如下所示 编译二进制.o文件 gcc -c -fpic [.c/.cpp][.c/.cpp]... 编库 gcc -shared [.o][.o]... -o [lib自定义库名.so] 链接库到可执行文件 gcc [.c/.cpp] -o [自定义可执行文件名] -l[库名] -L[库路径] -Wl,-rpath=[库路径]但是这里要注意,如果按照跟我一样的下面方式进行操作 这样会直接提示找不到动态库,因为系统寻找动态库是需要指定一下路径的,不然只会在默认的路径下去找,因此需要首先 sudo vim .bashrc在末尾加上这个路径 之后source一下 source .bashrc这样之后再次运行就不会报错了 4、makefile实现makefile的基本格式 targets : prerequisties [tab键]command用中文翻译一下就是: 目标: 生成目标需要的文件或者是目标(目标套娃) [tab键]执行的命令伪目标,伪目标的格式如下 .PHONY : clean为什么要有伪目标这个概念,意思就是不管有没有clean这个文件,当运行make clean的时候就是运行clean的命令,不然的话,还是用上面的程序进行实验: #include int add(int a, int b); int minus(int a, int b); int main() { int a = 30; int b = 5; int c; c = add(a, b); printf("a+b = %d\n", c); c = minus(a, b); printf("a-b = %d\n", c); return 0; } int add(int a, int b) { return a+b; } int minus(int a, int b) { return a-b; }这里要注意:当只有一个文件的时候可以不编写makefile,直接make这个文件就是用gcc编译了 这样如果我们不使用伪目标,当有一个clean.c的文件或者clean的可执行文件,就回去执行clean这个文件而不是我们准备好的makefile命令 1、makefile变量 1、定义变量直接用=的形式就可以,当然这个=有几种变化的形式,比如下面使用变量表示源文件和.o文件的位置 src := main.c obj := objs/main.o bin := main几种 = 的介绍 := 立即赋值运算符 用于在定义变量时立即求值 该值在定义后不再更改 即使在后面的语句中重新定义了该变量?= 默认赋值运算符 如果该变量已经定义,则不进行任何操作 如果该变量尚未定义,则求值并分配+= 累加 2、使用变量使用$() 或者是 ${}的方式来实现 $(bin) : $(obj) gcc $(obj) -o $(bin) $(obj) : $(src) gcc -c $(src) -o $(obj) .PHONY : clean clean: rm -rf *.o main执行如下所示: 3、一些预定义变量,可以用预定义变量来提高效率 $@: 目标(target)的完整名称 $ |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |