Makefile 易忘规则记录

Makefile 易忘规则记录

主要用于记录一些Makefile中容易忘记的规则等

粗略规则

target... : prerequisites ...
[tab] command
...

易忘规则

伪目标声明

.PHONY: clean
clean:
[tab] rm ./*.o

自动推导

a.o 的缺省依赖 a.c

注释

Makefile 中只有行注释

p := /home/wangha    #注释

当注释以上面方式时,要注意,p实际上为'/home/wangha ',后面是携带着空格的

命令

命令的执行必须以[TAB]开头,除非命令是紧跟在依赖规则的';'后面的

引用其他Makefile

include <filename1> <filename2> #允许使用通配符
-include <*.h> # 忽略无法读取的文件

指定目录搜寻头文件或依赖文件

VPATH = src:../others # src和../others

vpath的三种用法

  1. vpath <pattern> <directories>

    为符合pattern的文件在directories上也进行搜索

  2. vpath <pattern>

    清除符合pattern的文件的搜索目录

  3. vpath

    清除所有已被设置好的文件搜索目录

多目标中的$> $@

$> 表示多目标中对应的依赖

$@ 表示多目标中对应的目标

替换

source = foo.c bar.c
include $(source:.c=.d) # 转化为foo.d bar.d
include $(source:%.c=%.d) # 静态模式的转换

命令执行

exec:
[TAB] :cd /home/abc; pwd # 只有在一行时才会有效
exec2: 
[TAB] : cd/home
[TAB] : pwd # 依旧是Makefile的目录下

忽略ERROR

方式一:

-command 加上'-'后,不管出错与否,继续执行

方式二:

全局忽略,make的参数中加'-i'或者'--ignore-errors'

嵌套执行的变量传递

export <var1 ...>;

仅仅局限于传递到下层的Makefile

如果传递所有变量 则只需要export即可

等于号

= 普通的定义变量,但存在着递归定义的问题

:= 修复了递归定义问题,但前面的变量不能使用后面的变量,如

a := $(b) a.o #a的实际值是a.o
b := b.o

?= 例如b?=bar,如果b已经定义过了,则什么也不做

变量嵌套

x = $(y)
y = z
z = Hello
a := $($(x))

此处a应该为Hello,自行推导

override的使用

在make的时候,会指定一些参数,在Makefile中对这些变量赋值是会被忽略的,如果希望修改,则需要使用override,语法i如下

override <var1>; =<value>;
override <var1>; +=<more>;
override define foo
bar
endef

define的使用

define double-echo
echo abc
echo $(abc)
endef

局部变量

a  := bar.c
tmp : a:=foo.c
tmp : $(a)
[TAB] gcc -o b.o $(a) #在tmp的范围内,a为foo.c

模式变量

%.o : CFLAGS = -O

使用时

a.o: a.c
[TAB] : $(CC) $(CFLAGS) a.o a.c

上述例子为,给所有的 .o 文件,在编译时候,自动添加-O

条件关键词

  1. ifeq

    ifeq (<arg1>, <arg2>)
    ifeq '<arg1>' '<arg2>'
    ifeq "<arg1>" "<arg2>"
    ifeq "<arg1>" '<arg2>'
    ifeq '<arg1>' "<arg2>"
    
  2. ifneq

    用法同上

  3. ifdef

    foo =
    ifdef foo
        frobozz = yes
    else
        frobozz = no
    endif
    

    上述例子,由于foo没有赋值,故 frobozz为no

  4. ifndef

    用法同上

函数的调用

$(func-name argus)

例子:将空格全部转换为','

comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))

foreach函数

$(foreach <var>,<list>,<text>)

功能:对list中的每一个赋值给var,并执行text

例子:

names := a b c d
files := $(foreach n,$(names), $(n).o)

files 的值为a.o b.o c.o d.o

if函数

$(if <condition>,<then-part>)
$(if <condition>,<then-part>,<else-part>)

返回值,如果 <condition> 为真(非空字符串),那个 <then-part> 会是整个函数的返回值,如果 <condition> 为假(空字符串),那么 <else-part> 会是整个函数的返回值。如果 <else-part> 没有被定义,那么,整个函数返回空字串。

call函数

$(call <expression>,<parm1>,<parm2>,...,<parmn>)

返回值: <expression> 的返回值就是 call 函数的返回值

例子 foo=a b

reverse =  $(1) $(2)
foo = $(call reverse,a,b)

origin函数

$(origin <variable>)

功能:告诉你这个变量是哪里来

返回值:

undefined: 如果 <variable> 从来没有定义过

default: 如果 <variable> 是一个默认的定义,比如“CC”这个变量

environment: 如果 <variable> 是一个环境变量,并且当Makefile被执行时, -e 参数没有被打开。

file: 如果 <variable> 这个变量被定义在Makefile中。

command line: 如果 <variable> 这个变量是被命令行定义的。

override: 如果 <variable> 是被override指示符重新定义的。

automatic: 如果 <variable> 是一个命令运行中的自动化变量。

常用于 :判断当前的这个变量到底来自于哪里

例子:

ifdef bletch
    ifeq "$(origin bletch)" "environment"
        bletch = barf, gag, etc.
    endif
endif

shell函数

调用/bin/sh来执行一些功能

contents := $(shell cat foo)

控制make的函数

$(error <text ...>)
$(warning <text ...>)

可用于检测Makefile运行时的信息,决定你继续执行OR报Error或者Warning和停止

例子,当发现有ERROR_001时,报错

ifdef ERROR_001
    $(error error is $(ERROR_001))
endif

make的退出码

0-succeed

1-error

2-如果你使用了make的“-q”选项,并且make使得一些目标不需要更新

指定Makefile

make -f 123.mk

指定目标

推荐采取以下方式

.PHONY: all
all: prog1 prog2 prog3 prog4

makefile中的目标生成参照规则

  • all:这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
  • clean:这个伪目标功能是删除所有被make创建的文件。
  • install:这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
  • print:这个伪目标的功能是例出改变过的源文件。
  • tar:这个伪目标功能是把源程序打包备份。也就是一个tar文件。
  • dist:这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。
  • TAGS:这个伪目标功能是更新所有的目标,以备完整地重编译使用。
  • check和test:这两个伪目标一般用来测试makefile的流程。

检查规则

-n: 不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。

-t: 这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。

-q: 这个参数的行为是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,其会打印出一条出错信息。

-W <file>: 这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件所发生的规则命令。

posted @ 2020-07-14 18:32  wangha  阅读(191)  评论(0编辑  收藏  举报