1.make学习笔记

1.学习makefile

make---->自动确定工程的那部分源程序文件需要重新编译,编译多个源文件;

用法:make [options] [target] ...
-f filename    -C -e  -k -s -S 
makefile----自动化编译
  • 实例1:
all:main.c foo.c foo1.c foo2.c   //all生成二进制的目标文件,后面为其依赖的文件,如果main.c foo.c foo1.c...中任何一个文件的修改日期比all文件日期新,或者all不存在,那么依赖关系发生;
	gcc main.c foo1.c foo2.c foo.c -o all            #生成目标all(可执行文件)的方法或命令;
  • 实例2:
    如果工程中某几个C文件被修改,只需编译被修改的C文件;
    如果头文件被改变,则需要引用几个头文件的C文件,并连接目标程序;
all:作为最终执行目标;
all:main.o  kbd.o util.o
		gcc -o all main.o kbd.o utils.o
	main.o:main.c defs.h
		gcc -c main.c
	kbd.o:kbd.c def.h 
		gcc -c kbd.c
.....
	clean:   #clean伪目标
		rm all main.o kbd.o.....utils.o 	
#clean作用删除make中生成过程文件
  • 语法规则:
	target : prerequistes  #all为目标文件名,prerequistes为依赖的文件,command命令行(bash命令)
		command
	或者是
	targets:prerequisites; command #command如果与prerequisites在一行,可以用分号分隔;
		command  #command支持正则表达式;

2.通配符

  • 通配符也可以在目标文件中使用
print:*.c #生成的目标文件为print,其依赖所有的*.c文件
	lpr -p $?  #$?是一个自动化变量,表示所有比目标新的依赖文件的集合
	touch print
  • 通配符也可以使用在变量中: objects=.o #不会展开,其变量值就是.o
    如果让其展开即所有的.o文件名的集合,需这样写: objects:=$(wildcard *.o) #其中wildcard是makefile的关键字;

3.伪目标

伪目标并不是一个文件,而只是一个标签;为防止与文件名重名的这种情况,可以是使用一个特殊标记".PHONY"来显示的指明一个目标是伪目标,向make说明不管有没有这个文件,这个目标都是伪目标;
执行时 make clean;

.PHONY:clean
clean:
	rm all main.o kbd.o....

伪目标也可以作为默认目标,只要将它放在第一个;一口气生成多个目标;伪目标总会被执行的;

all:prog1 prog2  #makefile中的第一个目标会被作为其默认目标;
.PHONY:all
prog1: prog1.o utils.o
	cc -o prog1 util.s
prog2: prog2.o
	cc -o prog2 prog2.o  #all总会比其三个目标新,在进行make重新编译时,其他三个目标规则就会宗被决议

4.多目标

多个目标同时依赖于同一个文件;
使用一个自动化变量“$@”,意味着目前规则中所有的目标的集合;

bigoutput littleoutput: text.g
	generate text.g -$(subst output,,$@)>;$@
#等价于:
bigoutput:text.g
	generate text.g -big>;bigoutput
littleoutput:text.g
	generate text.g -litter >;bigoutput
#其中-$(subst output,,$@)中的$表示指向一个makefile的函数,函数名为subst,后面为参数,subst函数时截取字符串的以上,$@表示目标的集合; $@依次取出目标,并指向命令;

5.makefile特征:

make会按照顺序一条一条的执行命令,所有命令以tab开头,除非紧跟依赖规则后面;
----->如果要让上一条的命令结果应用在下一条命令,需要使用分号分割这两条命令

exec:
	- cd /home
	pwd	#输出makefile所在目录,即./
exec:
	cd /home;pwd #输出/home
  • 每当命令执行完毕后,make会自动检测它们的返回码;
    命令前加"-",标记为不管命令是否出错都认为是成功的。

6.变量

在使用变量时应加入"$“符号,最后使用()或{}把遍历包括起来;如果使用真实的”$“字符,那么需要”$$"来表示;

objects=program.o foo.o utils.o
program:$(objects)
	cc -o program $(objects)
	$(objects):defs.h   #这个变量又依赖defs.h文件;

?= 若未初始化,则赋值; 若初始化,则不会赋值;

FOO?=bar
等价于:
ifeq ($(origin FOO),undefined)  #ifeq判断语句
	FOO=bar
endif

7.makefile常用的字符串函数调用

  • $(<function arguments) 函数中参数可以使用变量,函数和变量的括号最好一样;
  • 字符串替换:
    $(subst ee,EE,feet on the street)
    模式替换函数patsubst、查找字符串函数findstring、过滤函数filter
sources:=foo.c bar.c baz.s ugh.h
source:$(sources)
	cc $(filter %.c %.s,$(sources)) -o foo #其中%.c %.s为模式过滤 输出foo.c bar.c baz.s

反过滤函数filter-out、排序函数sort(遇见相同函数则删除)、取单词函数ward 、 取单词串函数wordlist
单词个数统计函数words、首单词函数firstword

8.文件名操作函数

取目录函数dir(取出最后一个反斜杠前)、取文件名函数notdir、取后准名函数suffix、取前缀函数basename、
加后缀函数addsuffix、加前缀函数addprefix、
$(addsuffix .c, foo bar hello)

  • 循环函数:foreach函数$(foreach (var),(list),(text)),有点向C中的for循环;
names:=a b c d
files:=$(foreach n,$(names),$(n).o)   #$(files)的值为a.o b.o c.o d.o
  • 条件判断语句:ifeq、ifneq、ifdef(是否为空)、ifndef
  • 条件判断函数:$(if ,,);

9.隐式规则

make预先约定好的规则;make的隐士规则功能会自动推导这两个目标的依赖目标和生成命令

foo:foo.o bar.o
	cc -o foo.o bar.o $(CFLAGS) $(LDFLAGS)  #隐士规则基本上使用了一些预先设置的变量;可以改变这些值;
#完全没必要写成:
foo.o:foo.c
	cc -c foo.c $(CFLAGS)
bar.o:bar.c
	cc -c bar.c $(CFLAGS)

使用"-R"或"–no-builtin-variable"参数来取消所定义的变量对隐士规则的作用;

  • makefile的隐士规则中常用的变量:
    一种是和命令相关的"CC",
    AR、AS、CC、CXX、CO、CPP、TEX、RM等等
    一种是和参数相关的,“CFLAGS”;

10.模式规则

  • 最少在规则的目标中要包含"%“符号;
    “%.c” 表示以.c结尾的文件名
    “s.%.c” 表示以s.开头,以.c结尾的文件名
    如果目标中模式的”%“决定了依赖目标中”%"的样子
%.o:%.c;<command....>  指出了从所有的.c文件生成相应的.o文件的规则;
  • makefile自动化变量21个:
    字母"D"表示Directory ; "F"表示File; $(<)要比$<好;
    $@、$%、$<、$?、$^、$+=、$-=;

猜你喜欢

转载自blog.csdn.net/qq_42698422/article/details/106719285