Makefile常用语法汇总

######################################################################################
ver 0.1     2016-4-13 初稿
ver 0.2     2016-5-6  增加自定义调试输出和函数调用使用注意事项
######################################################################################
#    Makefile就是对多个文件关系的描述(生成规则),格式如下
#    target ... : prerequisites ...
#    TAB command
#    说明几点:
#    1.目标文件target(可以是一个,也可以是多个)信赖于prerequisites中的文件或目标,
#    其生成规则定义在command中。
#    2.当依赖中的文件在目标文件之后有修改的话就执行command命令,关心的是modify time。
#                            command
#    3. [prerequisites] ------------> [target]
#    4. make默认把第一个不是以.开头的目标当成终极目标,终极目标可以认为是依赖关系树的树根
#    5. make的工作方式:
#        1>读入所有的include
#        2>读入被inlude的其它Makefile
#        3>初始化文件中的变量
#        4>推导隐晦规则,分析所有规则
#        5>为所有的目标创建依赖关系树
#        ----------------------------
#        6>根据依赖关系决定哪些目标要重新生成
#        7>执行对应的生成命令
######################################################################################

### include指令
##开头可以使用include来引用其它.mk文件中常用的公共部分,可以使用-I或--include-dir指定搜索文件的路径


### 变量
## 1.使用变量代替硬编码,make中的变量可类比c中的宏
## 2.变量定义:
##     =定义的变量值可以是之前未定义的; 
##    :=定义的值必须是之前定义过的,否则认为是空
##    ?=表示如果变量没有定义过才进行定义,否则什么都不做
##    +=追加定义,如果之前没有定义过+= -> =;如果之前定义过则继承
## 3.系统变量MAKELEVEL会随着嵌套递增
## 4.变量替换:$(var:a=b) 把var中的a替换为b
##             $(foo:%.o=%.c) 把foo中有的.o替换为.c
## 5.目标变量:prog: CFLAGS = -g, 变量CFLAGS会作用到由这个目标所引发的所有规则中去
## 6.模式变量:%.o:CFLAGS = -o,把变量定义在符合这种模式的所有目标上
CC = gcc
RM = rm
CFLAGS = -Wall -I ./include/ -I /usr/local/mysql/include/
LDFLAGS = -L /usr/local/mysql/lib/ -lpthread -lmysqlclient
TARGET = test


### 分支
##ifeq|ifneq、ifdef|ifndef、else、和endif
ifeq ($(CC), gcc)
    #@echo "you are useing gcc!" 必须注释此行,不然就报错,说明在makefile读入的时候已经把分支处理了;
endif


### 函数
## $(funname arg1,arg2,...)
## 1. make中函数的调用方式和变量替换方式类似
## 2. 常用的函数有:wildcard filter subst
SRCS = $(wildcard *.c)
OBJS = $(subst .c,.o,$(SRCS))
##说明:
##参数间以逗号分隔,函数名和参数间以空格分隔。一定不能在,和.o之间加空格,否则输出可能和预期相驳。下面就是错误多添加空格以后的输出
##Makefile:8: "SRCS is"common.c main.c tcptunnel.c udptunnel.c
##Makefile:11: "OBJS is" common .o main .o tcptunnel .o udptunnel .o


### 目标或依赖的搜索路径
## 1.使用VPATH指定依赖文件的搜索路径,多个目录之间用:分隔; 如果不指定的话,make只认得当前目录:(
VPATH = ./include
## 2.还可以使用关键字vpath更灵活的指定,%表示匹配零个或若干个字符
##所有的.c在当前目录查找
vpath %.c ./
##清除上面的设置
vpath %.c
##清除所有的vpath设置
vpath


##反斜线表示换行,没有反斜线结尾且第二行以TAB开头的都被认为是SHELL命令
$(TARGET): $(OBJS)
    $(CC) $(LDFLAGS) -o test $(OBJS)


### 隐晦规则
##make会自动把.c当成是.o的依赖,并推导出对应的生成命令,这就是“隐晦规则”
json.o : json.h
#hashfunc.o : hashfunc.h


### 自动生成依赖
## 1.手动添加依赖的.h没有维护性,可以利用gcc -MM选项自动生成除了标准库头文件以外的所有依赖文件
%.d : %.c
    @set -e; rm -rf $@; $(CC) -MM $(CFLAGS) $< > $@.$$$$;\
    sed 's, \($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\
    rm -f $@.$$$$
## 2..o的生成依赖于他的规则,导致依赖关系.d(dependency)的生成,最后再把依赖关系导入,从而迂回地实现让make自己生成规则
parseconf.o : parseconf.d
include parseconf.d


### 显式规则
##显式说明文件的依赖和生成规则,这种称为“显式规则”
wj.o : wj.c wj.h
    $(CC) $(CFLAGS) -c wj.c


##main.o和javasniff.o都依赖于com_adt_AdtSniff.h文件,可以使用“多目标规则”
#main.o: com_adt_AdtSniff.h
#javasniff.o:javasniff.c com_adt_AdtSniff.h
#   $(CC) $(CFLAGS) -c javasniff.c

#### 多目标
###“多目标规则”
## 1. 针对每个目标复用相同的命令使得编写效率大大提高
## 2. 命令对每个目标执行一次,其中可能用到的特殊变量:$@ 表示目标引用; $< 表示依赖引用
main.o javasniff.o:com_adt_AdtSniff.h
    $(CC) $(CFLAGS) -c $(subst .o,.c,$@)

### 静态模式规则
## 1.静态模式可以更容易更灵活的编写规则
## 2. <targets ...>: <target-pattern>: <prereq-pattern ...>
##    TAB <commands ...>
#main.o javasniff.o : %.o: %.c
#   $(CC) $(CFLAGS) $< -o $@

### 模式规则
## %.o:%.c <command>
##关于静态模式规则和普通的模式规则说明几点:
##1.静态模式规则只能用在规则中明确指出的那些文件的重建过程中,不能用在除此之外的任何文件的重建过程中
##2.静态模式规则对指定的每一个目标来说是唯一的,如果一个目标存在于两个规则,并且这两个规则都定义了命令, make 执行时就会提示错误
##3.非静态模式规则可被用在任何和它相匹配的目标上,当一个目标文件同时符合多个目标模式时,make将会把第一个目标匹配的模式规则作为重建它的规则
##4.Makefile中明确指定的模式规则会覆盖隐含模式规则


### 伪目标
## 1.伪目标不是一个文件,只是一个标签
## 2.伪目标一般不会成为其它目标的依赖,所以一般必须显式指出这个目标
## 3.伪目标可以有自己的依赖文件,一般用于默认目标同时生成多个目标文件
## 4.PHONY用来防止当伪目标和文件名重名时无法执行目标对应命令的情况发生
.PHONY: clean print
clean:

### 命令
## 1.以TAB开头的行会被认定为命令,注释前面也是不能加TAB的
## 2.make -n会显示所要执行的命令但不实际执行,可用于调试
## 3.@会抑制命令本身的显示; make -s会全面禁止命令的显示
## 4.如果想让上一条的命令影响下一条,应该把两条命令放一行并用';'隔开
## 6.make会检测每个命令的返回码,如果有错则终止执行当前规则,这将有可能导致所有规则的执行,-会ignore命令返回的错误; 
    @-$(RM)  $(TARGET) $(OBJS)


### 通配符
## 1.在规则中使用*会自动展开如下
print: *.c
    @echo $?
    @echo SRCS:$(SRCS)
## 2.变量中使用的话不会自动展开,需要借助wildcard函数实现
#objects = *o                  ###ERROR
#objects := $(wildcard *.o)    ###RIGHT


### 嵌套执行
## $(MAKE) -C subdir
## 1.大工程中每个功能模块分别放到不同的目录中,每个目录中都有一个独立的Makefile文件,这样更有利于后期维护
## 2.被export的变量可以传入到子Makefile中,SHELL和make参数MAKEFLAGS没有该限制; 指定-e的变量会覆盖子Makefile

### 打印自定义调试信息
##1. 输出打印信息的方法是: $(warning xxxxx),$(error xxxxx)
##2. 输出打印变量值的方法是:$(warning  $(XXX))
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值