Makefile基础知识点及其简单运用

#Makefile的编译规则1)在Makefile 中#的相当于注释,转意字符是\,\可以用来换行,Makefile对缩进有要求
(2)Makefile中的完整语句的格式(简写隐式转换)
targets : prerequisites
    command
argets:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;
prerequisites:是我们的依赖文件,要生成 targets 需要的文件或者是目标。可以是多个,也可以是没有;
command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。

简单举个例子:
#Makefile的简写命令
test:test.c
	gcc -o	test test.c
#作用生成一个可执行test文件,依赖于test.c,规则是gcc -o test test.c
总的来说就是:1.生成目标 2.依赖文件 3.编译规则

(3)Makefile的完整语句的格式(完整)
main:main.o test1.o test2.o
	gcc main.o test1.o test2.o -o main
main.o:main.c test.h
	gcc -c main.c -o main.o
test1.o:test1.c test.h
	gcc -c test1.c -o test1.o
test2.o:test2.c test.h
	gcc -c test2.c -o test2.o
解释:
## 1
main是生成的目标
main的生成依赖于main.o test1.o test2.o
规则是:gcc main.o test1.o test2.o -o main
## 2
main.o 是生成目标
main.o的生成依赖于main.c test.h 
规则是:gcc -c main.c test.h
## 3
test1.o是生成目标
test1.o的生成依赖于test1.c test.h
规则是:gcc -c test1.c test.h
## 4
test2.o是生成目标
test2.o的生成依赖于test2.c test.h
规则是:gcc -c test1.c test.h
注意:Makefile有严格依赖关系,生成的文件必定是依赖于另外一个文件,依赖的文件生成来自于之后。
	相当于先写结果,然后写过程
注意:-o后面的是编译后生成的文件名


(4)清除工作目录中的过程文件(位指令的定义和使用规则.PHONY:伪指令)
.PHONY:clean #这一句加不加都无所谓(前提是当前目录没有名为clean的文件)
clean:
	rm -rf *o
	rm -rf test
注意:实际上是没有clean这个指令的,这是弄的伪指令
 	 使用make的时候这句不会执行(前提是没有其他的目标文件或者其他的目标文件依赖于clean)
 	 使用make clean 才会执行我清除指令
 	 我们可以仿照上面定义更多的位指令也没问题,执行伪指令的方式是make 位指令
 	  就会根据相应的规则执行相关命令。
	-rf的作用就是不管能不能执行,接着往下走不报错,执行完这条位指令

(5)通配符(* [] ?[]的用法:
	gcc -c test1.c test2.c test3.c -o test1.o test2.o test3.o
	实际可以写做:gcc -c test[1-3].c -o test[1-3].o
 *的用法(%的用法和*差不多的):
 	gcc test1.c test2.c test3.c -o test
 	实际可以写做:gcc *.c -o test
 ?的用法:
 	gcc test1.c test2.c test3.c -o test
	实际上可以写做:gcc test?.c -o test
拓展:
	wildcarb:展开通配符,不能用来展开还不存在的东西,不同于依赖
	$^:在当前整个一段有效语句中对应的依赖文件
	$@:在当前整个一段有效语句中对应的目标文件
实例:
** 1 假设当前目录中只存在test.c 文件和Makefile文件
	obj=$(wildcard *.o)
	test:$(obj)
		gcc $^ -o $@
	test:test.o
		gcc -c $^ -o $@
	上面会直接报错,为什么,因为会先执行wildcard *.o但是此时文件.o是不存在的。
	
假如这样就可以:
	obj=$(wildcard *.c)
	test:$(obj)
		gcc $^ -o $@
		这样就不会报错,因为.c是存在的;这里我用了一下隐式规则(gcc -o 和gcc -c -o)。

看到这里应该发现了规律:
$^和$@到底是指什么?
	好吧上面挨着的例子实际上等于:
	obj=(wildcard *.c)
	test:$(obj)
		gcc  $(obj) -o test
$@:一条完整语句中的的目标文件
$^: 一条完整语句中的依赖文件


(6)变量的定义和使用(赋值,引用)
前面其实已经创建了变量
再写个例子:
			obj=$(test.c)
			test:$(obj)
				gcc test.c -o test
		实际上等于:
				test:test.c
					gcc test.c -o test

变量的基本赋值:
			简单赋值(:=),需要和$()一起用才能明显看出效果,什么是简单赋值,
			从什么时候开始引用,就从什么时候替换,替换变量即使在将来改变,
			也不会改变已经被替换了的变量改变.
			举个例子:
				x:=tes
				y:=$(x)t
				x:=new
				test:
					@echo "y=$(y)"
					@echo "x=$(x)"
			输入:
				make test
				打印结果:
						y=test
						 x=new
						
			
			总结:简单理解为不是赋值变量,是赋值变量所代表的东西
				
			递归赋值(=),需要$()才能明显看出效果,不截断,持续替代
			举个例子:
				x=tes
				y:=$(x)t
				x:=new
				test:
					@echo "y=$(y)"
					@echo "x=$(x)"
				输入:
					make test
					打印结果:
					y=newt
					x=new
			总结:简单理解就是赋值变量,而不是赋值变量所代表的东西

		 条件赋值(?=),在前面是否已经赋值,如果已经赋值,那么?=就不赋值了,否则将会赋值
		 举个例子:
		 	x=test
		 	x?=new
		 	y?=no
		 	test:
		 		@echo "x=$(x)"
		 		@echo "y=$(y)"
		 	输入:
		 		make test
		 		打印结果:
		 			x=test
		 			y=no
		总结:前面赋值了,后面就不赋值了,如果前面没赋值,就从这里开始赋值
		
		追加赋值(+=),就是当前的加上要追加的内容赋值给当前的变量
		举个例子:
			x=test
			y:=$(x)
			x+=$(y)
			test:
				@echo "x=$(x)"
			输入:
				make test
				打印结果:
					x=test test
		总结:就相当于加法其他语言的+=运算规则
	
(7)
$@	表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,
	也成为静态的库文件),那么它代表这个文档的文件名。在多目标模式规则中,
	它代表的是触发规则被执行的文件名。
	
$%	当目标文件是一个静态库文件时,代表静态库的一个成员名。
$<	规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,
	则它代表由隐含规则加入的第一个依赖文件。
	
$?	所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。

$^	代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,
	它所代表的只能是所有的库成员(.o 文	件)名。
	一个文件可重复的出现在目标的依赖中,变量“$
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值