Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are double-colon rules in a Makefile for?

Section 4.13 of the GNU Make manual describes the so-called double-colon rules:

Double-colon rules are rules written with ‘::’ instead of ‘:’ after the target names. They are handled differently from ordinary rules when the same target appears in more than one rule.

When a target appears in multiple rules, all the rules must be the same type: all ordinary, or all double-colon. If they are double-colon, each of them is independent of the others. Each double-colon rule's commands are executed if the target is older than any prerequisites of that rule. If there are no prerequisites for that rule, its commands are always executed (even if the target already exists). This can result in executing none, any, or all of the double-colon rules.

Double-colon rules with the same target are in fact completely separate from one another. Each double-colon rule is processed individually, just as rules with different targets are processed.

The double-colon rules for a target are executed in the order they appear in the makefile. However, the cases where double-colon rules really make sense are those where the order of executing the commands would not matter.

Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.

Each double-colon rule should specify commands; if it does not, an implicit rule will be used if one applies. See section Using Implicit Rules.

I kinda grok the meaning of each sentence of this section individually, but it's still not clear to me what double-colon rules are for. As for being rare, I have not yet seen any open-source project whose Makefile did not begin with

all:: 

Therefore: What's the intended purpose of double-colon rules in Makefiles?

like image 939
lindelof Avatar asked Oct 25 '11 14:10

lindelof


People also ask

What does double colons mean?

The double colon ( :: ) may refer to: an analogy symbolism operator, in logic and mathematics. a notation for equality of ratios. a scope resolution operator, in computer programming languages.

What does colon mean in makefile?

In the first line, the list of target names is terminated by a colon. This, in turn, is followed by the dependency list, if there is one. If several targets are listed, this indicates that each such target is to be built independently using the rule supplied.

What are makefile rules?

A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.

What is $@ in makefile?

The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.


2 Answers

Each :: rule is processed independently, so it can be simpler. For example, the single rule:

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

can be replaced with two simpler rules:

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

Utilities like AutoMake have an easier time spitting out many simple rules than a few complex ones.

A great answer with more examples was posted, then taken down, then found here:

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

Thanks to R.K. Owen for writing it, and Edward Minnix for finding it again!

like image 191
William H. Hooper Avatar answered Oct 02 '22 15:10

William H. Hooper


There are 3 situations where the double colon are useful:

  1. Alternate between the compile rules based on which prerequisite is newer than the target. The following example is based on "Example 19-3. Double-colon rules" from http://books.gigatux.nl/mirror/cinanutshell/0596006977/cinanut-CHP-19-SECT-3.html

Sample .c file:

c@desk:~/test/circle$ cat circle.c  #include <stdio.h>  int main (void) {   printf("Example.\n");   return 0; } 

Makefile used:

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 

Outcome:

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. Make a pattern rule terminal.

The following example explains this situation: the a.config file is obtained from a.cfg, which in turn is obtained from a.cfg1 (a.cfg being the intermediate file).

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 

Outcome (as the %.config rule is terminal, make inhibits the creation of the intermediate a.cfg file from a.cfg1):

c@desk:~/test/circle1$ make a.conf make: *** No rule to make target 'a.conf'.  Stop. 

Without the double colon for the %.config, the outcome is:

c@desk:~/test/circle1$ make a.config a.cfg from a.cfg1 a.config from a.cfg rm a.cfg 
  1. Make a rule that executes always (useful for clean rules). The rule must not have prerequisites!

c@desk:~/test/circle3$ cat Makefile

CP=/bin/cp   a.config::       @echo "Always" >> $@    a.config::       @echo "Always!" >> $@    clean:       -$(RM) *.config   

Outcome:

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! 
like image 34
Costin Zanfir Avatar answered Oct 02 '22 14:10

Costin Zanfir