lin*_*lof 31 makefile gnu-make
GNU Make手册的4.13节描述了所谓的双冒号规则:
双冒号规则是在目标名称后面用'::'而不是':'编写的规则.当同一目标出现在多个规则中时,它们的处理方式与普通规则不同.
当目标出现在多个规则中时,所有规则必须是相同的类型:所有规则或所有双冒号.如果它们是双冒号,则每个都是独立的.如果目标比该规则的任何先决条件更旧,则执行每个双冒号规则的命令.如果该规则没有先决条件,则始终执行其命令(即使目标已存在).这可能导致执行任何,任何或所有双冒号规则.
具有相同目标的双冒号规则实际上彼此完全分离.每个双冒号规则都是单独处理的,就像处理具有不同目标的规则一样.
目标的双冒号规则按它们在makefile中出现的顺序执行.但是,双冒号规则确实有意义的情况是执行命令的顺序无关紧要的情况.
双冒号规则有点模糊,通常不太有用; 它们为用于更新目标的方法根据导致更新的先决条件文件而不同的情况提供了一种机制,这种情况很少见.
每个双冒号规则应指定命令; 如果没有,则使用隐式规则(如果适用).请参阅使用隐式规则部分.
我有点单独理解本节每个句子的含义,但我仍然不清楚双冒号规则是什么.至于是罕见的,我还没有看到任何的开源项目,其Makefile文件并没有开头
all::
Run Code Online (Sandbox Code Playgroud)
因此:Makefile中双冒号规则的目的是什么?
Wil*_*per 16
每个::规则都是独立处理的,因此它可以更简单.例如,单个规则:
libxxx.a : sub1.o sub2.o
ar rv libxxx.a sub1.o
ar rv libxxx.a sub2.o
Run Code Online (Sandbox Code Playgroud)
可以用两个更简单的规则代替:
libxxx.a :: sub1.o
ar rv libxxx.a sub1.o
libxxx.a :: sub2.o
ar rv libxxx.a sub2.o
Run Code Online (Sandbox Code Playgroud)
像AutoMake这样的工具可以更容易地分出许多简单的规则,而不是几个复杂的规则.
发布了更多示例的一个很好的答案,然后删除,然后在这里找到:
感谢RK Owen的写作,以及Edward Minnix再次找到它!
有三种情况,双冒号是有用的:
示例.c文件:
c@desk:~/test/circle$ cat circle.c
#include <stdio.h>
int main (void)
{
printf("Example.\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Makefile使用:
c@desk:~/test/circle$ cat Makefile
# A makefile for "circle" to demonstrate double-colon rules.
CC = gcc
RM = rm -f
CFLAGS = -Wall -std=c99
DBGFLAGS = -ggdb -pg
DEBUGFILE = ./debug
SRC = circle.c
circle :: $(SRC)
$(CC) $(CFLAGS) -o $@ -lm $^
circle :: $(DEBUGFILE)
$(CC) $(CFLAGS) $(DBGFLAGS) -o $@ -lm $(SRC)
.PHONY : clean
clean :
$(RM) circle
Run Code Online (Sandbox Code Playgroud)
结果:
c@desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
make: *** No rule to make target 'debug', needed by 'circle'. Stop.
c@desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
c@desk:~/test/circle$ vim circle.c
c@desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
c@desk:~/test/circle$ vim debug
c@desk:~/test/circle$ make circle
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
Run Code Online (Sandbox Code Playgroud)
下面的例子解释了这种情况:a.config文件是从a.cfg获得的,而a.cfg又是从a.cfg1获得的(a.cfg是中间文件).
c@desk:~/test/circle1$ ls
a.cfg1 log.txt Makefile
c@desk:~/test/circle1$ cat Makefile
CP=/bin/cp
%.config:: %.cfg
@echo "$@ from $<"
@$(CP) $< $@
%.cfg: %.cfg1
@echo "$@ from $<"
@$(CP) $< $@
clean:
-$(RM) *.config
Run Code Online (Sandbox Code Playgroud)
结果(因为%.config规则是终端,make禁止从a.cfg1创建中间a.cfg文件):
c@desk:~/test/circle1$ make a.conf
make: *** No rule to make target 'a.conf'. Stop.
Run Code Online (Sandbox Code Playgroud)
没有%.config的双冒号,结果是:
c@desk:~/test/circle1$ make a.config
a.cfg from a.cfg1
a.config from a.cfg
rm a.cfg
Run Code Online (Sandbox Code Playgroud)
c @ desk:〜/ test/circle3 $ cat Makefile
CP=/bin/cp
a.config::
@echo "Always" >> $@
a.config::
@echo "Always!" >> $@
clean:
-$(RM) *.config
Run Code Online (Sandbox Code Playgroud)
结果:
c@desk:~/test/circle3$ make a.config
c@desk:~/test/circle3$ cat a.config
Always
Always!
c@desk:~/test/circle3$ make a.config
c@desk:~/test/circle3$ cat a.config
Always
Always!
Always
Always!
Run Code Online (Sandbox Code Playgroud)
正如文档所说,双冒号规则很少有用.它们是一种很好的,没有命名复合虚假目标的单个目标的方法(如all::),但在这个角色中并不是必需的.我只能在必要时形成一个人为的例子:
假设您有一个日志文件L,它与其他几个日志文件L1,L2,....连接起来.您可以制定一些双冒号规则,例如:
L :: L1
cat $< >> $@ && rm $<
L :: L2
cat $< >> $@ && rm $<
Run Code Online (Sandbox Code Playgroud)
现在在GNU make中,你当然会使用$^这种魔法,但它被列为GNU make的功能选项卡上的灵感功能.
| 归档时间: |
|
| 查看次数: |
14166 次 |
| 最近记录: |