makefile规则

makefile中的规则

概述

规则的通常形式:shell

target: <normal-prerequisites> | <order-only-prerequisites> <; commands>
    <commands>

makefile的构成主体是各类规则。不管是什么形式的规则,都会描述一个三元组:目标、必要条件、命令。一个规则能够同时描述一个或者多个甚至无数个工做目标(实际上是无数个规则构成的模式),多目标的规则能够视为多个规则的叠加描述,均可拆分红单一工做目标的规则。工做目标是某个文件名,或者某个“动做”,但不能为空。必要条件也能够是具体的文件或者“动做”,能够为空。命令是发生更新时交给子shell执行的命令,能够多条,每条交给一个shell,若是要把全部的命令都给一个shell执行,要把它们整成一行或用连行符号\数据库

目标和必要条件中的变量会当即扩展,而命令不会扩展。(make会在全部的变量和命令都被加载到数据库以后,在将要执行命令以前扩展命令中的变量。)若是在定义了.SECONDEXPANSION这个目标,以后的规则中的必要条件都会进行两次扩展。第二次扩展发生在make读入全部的变量和规则以后,在执行规则以前。函数

当make读入makefile后,须要根据必要条件的类型和时间戳与目标的时间戳,决定是否采起更新动做(把命令交给子shell执行)。
必要条件分为两种:
普通必要条件。更新目标以前先更新普通必要条件。只要该必要条件的时间戳大于或等于目标的时间戳(尚不存在的文件时间戳能够认为是负无穷或者某个古老的时间点),就会致使更新动做;
“order-only“必要条件,(只执行一次的必要条件,|以后的必要条件)。Make要更新这个必要条件时会检查是否存在该文件,若是存在,就不会继续更新这个必要条件(无论他的时间戳)也不会所以更新目标;若是不存在,则检查在这次执行make的过程当中是否执行过以该必要条件为目标的规则,若是没有则执行一次,不然结束对此必要条件的更新。ui

下面是常常用到的例子,跟新目标文件之间要求目标文件夹已存在,但总不能每条跟新目标文件的规则里都执行mkdir -p,这样虽然也能干活,但看着难受。更好的办法是让目标文件order-only依赖与文件夹,而后针对文件夹的更新动做是mkdir -p,这样mkdir就只执行一次了。unix

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)

$(OBJS): | $(OBJDIR)
$(OBJDIR):
    mkdir $(OBJDIR)

具体规则,指定具体的工做目标,若是必要条件中有时间戳靠后的文件,则执行命令。这是最多见的规则。模式规则中,目标使用的是通配符而不是具体的文件名,这让make对与模式相符的工做目标应用该规则。隐含规则能够是模式规则,也能够是内置于make的后缀规则。code

具体规则

具体规则以特定的文件做为工做目标和必要条件。每一个规则能够由多个工做目标。意味着每一个工做目标都依赖后面的必要条件。
规则没必要一次性定义彻底。每当make看到一个工做目标,就会将该工做目标和必要条件加入依存图。若是工做目标已经存在,任何额外的必要条件会被添加到依存图中。若是一个工做目标屡次制定了命令(不是一次命令由多条命令组成),则取最后一次命令做为更新动做,忽略以前的命令,make会给出警告。orm

假想工做目标:工做目标能够不是真实的文件,表示一个动做,成为假想工做目标。它老是未更新的,很“旧”,因此每次该规则的命令都会被执行。为了防止该动做可能与某个文件重名,可用.PHONY:声明。get

模式规则

背景:it

  • 在包含不少文件的大型程序中,手动指定每条规则将会不切实际。并且,这些命令极可能是重复的代码,若是修改某处可能引发多处修改,产生难以维护的问题。
  • 许多程序在读取输入文件以及产生输出文件时都会依照惯例。

模式

模式规则中的百分号字符%大致上等效于unix中的星号*,它能够表明任意多个字符。百分比字符能够放在模式的任何地方,但只能出现一次。当make搜索要使用的模式规则时,它首先会查找符合的模式规则工做目标,将百分号表明的部分替换到必要条件中来检查模式规则的必要条件。编译

例如:

%: %.mod
    $(COMPILE.mod) -o $@ -e $@ $^

%: %.cpp
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

%: %.sh
    cat $< >$@
    chmod a+x $@

静态模式规则

静态模式规则与通常模式规则的惟一差异是指定了工做目标的匹配集合。

$(OBJECTS): %.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@

后缀规则

后缀规则是旧时没有模式规则时的替代品,已弃用。

隐含规则

隐含规则是内置于make的模式规则。要查看make内置了那些规则,可使用-p, --print-data-base命令显示。此命令还能够看到内置的变量定义。

当make检查一个工做目标时,若是找不到它的具体规则,就会使用隐含规则。
使用不带命令的模式规则能够屏蔽相应的隐含规则。

例如:

hello:
hello: hello.c

都会自动执行相应的编译过程。

%: %.o

能够屏蔽从.o文件连接可执行程序的规则。

杂项

规则中可使用shell的模式匹配,而其余地方要使用wildcard函数。

规则中的必要条件没必要一次描述彻底,能够分为屡次,可是对于同一规则的命令,只取最后一次描述中的命令。好比:

hello : hello.c
    echo hello
    
hello : include.h
    gcc -o hello hello.c

以hello为目标的规则中有两个必要条件hello.cinclude.h,此规则的命令只有gcc -o hello hello.c

相关文章
相关标签/搜索