首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成文件中的双冒号规则是什么?

生成文件中的双冒号规则是什么?
EN

Stack Overflow用户
提问于 2011-10-25 14:45:52
回答 5查看 23.5K关注 0票数 44

4.13 GNU制作手册部分描述了所谓的双冒号规则:

双冒号规则是在目标名称之后用“::”而不是“:”编写的规则。当同一目标出现在多条规则中时,它们的处理方式与普通规则不同。 当一个目标出现在多个规则中时,所有规则都必须是相同的类型:所有普通的,或所有的双冒号。如果它们是双冒号,那么它们中的每一个都是独立的.如果目标早于该规则的任何先决条件,则执行每个双冒号规则的命令。如果该规则没有先决条件,则始终执行它的命令(即使目标已经存在)。这可能导致执行任何、任何或所有双冒号规则. 具有相同目标的双冒号规则实际上是完全独立的。每个双冒号规则被单独处理,就像处理不同目标的规则一样. 目标的双冒号规则按照它们在makefile中出现的顺序执行。然而,在双冒号规则真正有意义的情况下,执行命令的顺序并不重要。 双冒号规则有点模糊,而且通常不太有用;它们提供了一种机制,用于更新目标的方法因导致更新的前提文件不同而不同,而且这种情况非常罕见。 每个双冒号规则都应该指定命令;如果不指定,则在应用时将使用隐式规则。参见使用隐式规则的一节。

我有点摸索这一节每句话的意思,但我仍然不清楚双冒号规则是干什么用的。至于很少,我还没有看到任何开放源码项目的Makefile没有开始。

代码语言:javascript
复制
all::

因此:在Makefiles中双冒号规则的目的是什么?

EN

回答 5

Stack Overflow用户

发布于 2014-09-19 21:05:26

规则是独立处理的,所以它可以更简单。例如,单一规则:

代码语言:javascript
复制
libxxx.a : sub1.o sub2.o
    ar rv libxxx.a sub1.o
    ar rv libxxx.a sub2.o

可以用两个更简单的规则来代替:

代码语言:javascript
复制
libxxx.a :: sub1.o
    ar rv libxxx.a sub1.o

libxxx.a :: sub2.o
    ar rv libxxx.a sub2.o

与一些复杂的规则相比,像AutoMake这样的实用程序更容易抛出许多简单的规则。

更多的例子给出了一个很好的答案,然后取下来,然后在这里找到:

https://web.archive.org/web/20180122002430/http://owen.sj.ca.us/~rk/howto/slides/make/slides/makecolon.html

感谢R.K.欧文写了这本书,爱德华·明尼克斯又找到了它!

票数 25
EN

Stack Overflow用户

发布于 2015-11-01 20:02:30

有三种情况下,双冒号是有用的:

  1. 在编译规则之间进行替换,基于哪种先决条件比目标更新。下面的示例基于http://books.gigatux.nl/mirror/cinanutshell/0596006977/cinanut-CHP-19-SECT-3.html的“示例19-3.双冒号规则”

示例.c文件:

代码语言:javascript
复制
c@desk:~/test/circle$ cat circle.c 
#include <stdio.h>

int main (void)
{
  printf("Example.\n");
  return 0;
}

使用Makefile:

代码语言:javascript
复制
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

结果:

代码语言:javascript
复制
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
  1. 制作模式规则终端。

下面的示例解释了这种情况: a.config文件是从a.cfg获得的,而后者又是从a.cfg1 (a.cfg是中间文件)获得的。

代码语言:javascript
复制
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

结果(因为%.config规则是终端的,所以要阻止从a.cfg1创建中间a.cfg文件):

代码语言:javascript
复制
c@desk:~/test/circle1$ make a.conf
make: *** No rule to make target 'a.conf'.  Stop.

如果没有%.config的双冒号,结果是:

代码语言:javascript
复制
c@desk:~/test/circle1$ make a.config
a.cfg from a.cfg1
a.config from a.cfg
rm a.cfg
  1. 制定一个总是执行的规则(对于干净的规则有用)。规则不能有先决条件!

C@desk:~/test/圆形3$ cat Makefile

代码语言:javascript
复制
CP=/bin/cp  
a.config::  
    @echo "Always" >> $@  

a.config::  
    @echo "Always!" >> $@  

clean:  
    -$(RM) *.config  

结果:

代码语言:javascript
复制
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!
票数 11
EN

Stack Overflow用户

发布于 2011-10-25 14:50:21

对于非递归的makefile和像clean这样的目标,它们非常方便。也就是说,单个.mk文件可以将自己的命令添加到其他地方已经定义的clean目标中。

文档给出了答案:

双冒号规则有点模糊,而且通常不太有用;提供了一种机制,用于更新目标的方法因导致更新的前提文件不同而不同,而且这种情况很少见。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7891097

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档