What's meaning of two colons in one Makefile rule [duplicate] - makefile

This question already has an answer here:
Why does this MakeFile rule have two colons?
(1 answer)
Closed 3 years ago.
I know the rule syntax should be in below format:
targets : prerequisites
recipe
…
However, I see below snippet in slave.mk.
$(addprefix $(DEBS_PATH)/, $(SONIC_COPY_DEBS)) : $(DEBS_PATH)/% : .platform
$(HEADER)
$(foreach deb,$* $($*_DERIVED_DEBS), \
{ cp $($(deb)_PATH)/$(deb) $(DEBS_PATH)/ $(LOG) || exit 1 ; } ; )
$(FOOTER)
There are two ':' in the first line. Why?

That is the syntax for Static Pattern Rules:
Static pattern rules are rules which specify multiple targets and construct the prerequisite names for each target based on the target name. They are more general than ordinary rules with multiple targets because the targets do not have to have identical prerequisites. Their prerequisites must be analogous, but not necessarily identical.
Here is the syntax of a static pattern rule:
targets …: target-pattern: prereq-patterns …
recipe
…
The targets list specifies the targets that the rule applies to.

Related

What's the meaning of targets in a Makefile that start with a ., and how is it different/similar to suffix rules?

In a Makefile, I saw this:
all: .made
# ... some other code
.made: $(Program) bashbug
#echo "$(Program) last made for a $(Machine) running $(OS)" >.made
Is the .made rule a suffix rule as per: https://www.gnu.org/software/make/manual/make.html#Suffix-Rules?
Also, are all rules with targets that have a . in front suffix rules?
Otherwise, what is the significance of targets that start with .? It seems like there's a significance as per this in https://www.gnu.org/software/make/manual/make.html#How-Make-Works:
By default, make starts with the first target (not targets whose names
start with ‘.’).
But its significance is not mentioned.
Also, if it is a suffix rule, how come .made can be used as a prerequisite in the all rule? (It's not mentioned that the targets of suffix rules can be used as prerequisites in other rules.)
P.S.: This question is related to but different from what is the meaning for . (dot) before the target in makefile. This question asks explicitly for the difference between a target with . and a target of a suffix rule.
Is the .made rule a suffix rule
No, because .made is not a "known suffix".
Also, are all rules with targets that have a . in front suffix rules?
No, only those where the word after the dot is a "known suffix":
Your first two questions are answered by https://www.gnu.org/software/make/manual/make.html#Suffix-Rules:
Suffix rule definitions are recognized by comparing each rule’s target against a defined list of known suffixes. When make sees a rule whose target is a known suffix, this rule is considered a single-suffix rule. When make sees a rule whose target is two known suffixes concatenated, this rule is taken as a double-suffix rule.
In your example .made is an actual filename. Your Makefile has a rule for it that creates/updates the file:
#vvvv
.made: $(Program) bashbug
#echo "$(Program) last made for a $(Machine) running $(OS)" >.made
# ^^^^^
All pretty normal; it would work the same way with any other name.
The only significance of the leading dot is that it makes the file "hidden" by convention, i.e. ls won't show it (without specifying -a), plain * won't match it, etc.

Makefile - require all pattern matches

I'm trying to write a rule that will call my checking script on the output of each stage of my program, generating that output if it does not already exist using my %.output : %.input rule.
I tried check : $(wildcard stage[1234].output) but this causes the rule to require only those matching output files that already exist.
I could just define a variable like TARGETS = stage1.output stage2.output ..., but is there a way to generate all possible matches of a pattern and then require them?
for the %.output : %.input rule to apply, you need both
a goal that requires an intermediate that matches the pattern %.output
a corresponding %.input file - either preexisting or a rule to build it
If your stage*.input files already exist, you can use:
INPUTS=$(wildcard stage[1234].input)
TARGETS=$(INPUTS:%.input=%.output)
check: $(TARGETS)
If your stage*.input files don't exist but are expected to be built from similar pattern rules, reapply the same principle.
If your stage*.input are produced from more complicated means, but assuming that their name can be generated by the application of a substitution pattern simply apply that pattern. In your example it would be something like:
L:= 1 2 3 4
TARGETS=$(L:%=stage%.output)
If you want analogue of seq Unix utility in Make, here it is:
seq = $(if $(word $1,$2),$2,$(call seq,$1,$2 $(words $2 1)))
$(info seq(10)=$(call seq,10))
stage_sount:=7
stages:=$(patsubst %,stage%.output,$(call seq,$(stage_sount)))
$(info stages=$(stages))
all:
Output:
$ make
seq(10)= 1 2 3 4 5 6 7 8 9 10
stages=stage1.output stage2.output stage3.output stage4.output stage5.output stage6.output stage7.output
make: Nothing to be done for 'all'.

Makefile : create rules from a list of patterns

In my directory, I have many files named
A.xxx A01.xxx A02.xxx A03.xxx
B.xxx B01.xxx
Z......
I would like to create rules like
A.yyy : A.xxx
command type 1
A01.yyy : A01.xxx A.xxx
command type 2
B.yyy : B.xxx
command type 1
B01.yyy : B01.xxx B.xxx
command type 2
Z01.yyy: Z01.xxx
command type 3
Can someone give me an hint ?
I tried something like this (it seems ok for command 1 an 3, but in command 2 , I don't see how to put the second perequisit)
list:= A B
source=$(wildcard *.xxx)
compi:=$(patsubst %.xxx, %.yyy, $(source))
list_pattern=$(addsuffix %, $(list))
list_yyy=$(addsuffix .yyy, $(list))
list_nb_yyy=$(filter $(list_pattern), $(compi))
%.yyy:%xxx
#echo $# - $+ - command 3
all: $(compi)
.SECONDEXPANSION:
$(list_yyy): $$(patsubst %.yyy, %.xxx, $$#)
#echo $# - $+ - command 1
$(list_nb_yyy): $$(patsubst %.yyy, %.xxx, $$#)
#echp $# - $+ - command 2
Two important parts of the documentation that you should read include:
8.9 The eval Function
The eval function is very special: it allows you to define new makefile constructs that are not constant; which are the result of evaluating other variables and functions. The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax. The expanded results can define new make variables, targets, implicit or explicit rules, etc.
10.5.4 How Patterns Match, particularly the shortest stem rule:
It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically). If more than one pattern rule has the shortest stem, make will choose the first one found in the makefile.
The shortest stem rule will make it difficult to have 3 different pattern rules for A.yyy, A01.yyy and Z01.yyy respectively. However, with the eval function you can use the information available in the list variable to generate non-pattern rules for A.yyy and B.yyy, and the correct pattern rules for the other targets (assuming that the decision is made on the prefix of the name):
list:= A B
source=$(wildcard *.xxx)
compi:=$(patsubst %.xxx, %.yyy, $(source))
all: $(compi)
define LIST_RULE
$(1).yyy: $(1).xxx
#echo $$# - $$+ - command 1
$(1)%.yyy: $(1)%.xxx $(1).xxx
#echo $$# - $$+ - command 2
endef
$(foreach l,$(list),$(eval $(call LIST_RULE,$(l))))
%.yyy: %.xxx
#echo $# - $+ - command 3
Note that the fallback solution (command 3) won't be selected for A01.yyy and B01.yyy because the pattern rule in the LIST_RULE template leads to a shorter stem (01 instead of A01 or B01)

GNU make - transform every prerequisite into target (implicitly)

I have another make-like tool that produces an XML as an artifact after parsing my makefile which I'll then further process with Python.
It'd simplify things for me - a lot - if I could have make consider every single prerequisite to be an actual target because then this other tool
will classify each and every file as a "job".
This is a fragment of my makefile:
.obj/eventlookupmodel.o: C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h \
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h \
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h \
...
I'd want for make to think I have a dummy rule for each prerequisite such as below:
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h:
#echo target pre= $#
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h:
#echo target pre=$#
C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp :
#echo target pre=$#
C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h:
#echo target pre=$#
I don't care about the exact form of the rule just that each file is considered an actual target.
My method of passing in this rule would be by setting the MAKEFILES variable like so
make all MAKEFILES=Dummy.mk
with Dummy.mk containing this rule so that I do not modify the makefiles.
I've tried the following so far.
Dummy.mk:
%.h:
#echo header xyz = $#
%:
#echo other xyz= $#
This partially works.
I run make all --trace --print-data-base MAKEFILES=Dummy.mk and I can see that
make does "bind" the %.h: rule to the header files. In the --print-data-base section, I see that rule being assigned to the header files.
C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef.h:
# Implicit rule search has been done.
# Implicit/static pattern stem: 'C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef'
# Last modified 2016-05-27 12:39:16
# File has been updated.
# Successfully updated.
# recipe to execute (from '#$(QMAKE) top_builddir=C:/Users/User1/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/ top_srcdir=C:/Users/User1/Desktop/A/HMI_FORGF/ -Wall CONFIG+=release CONFIG+=qnx_build_release_with_symbols CONFIG+=rtc_build -o Makefile C:/Users/User1/Desktop/A/HMI_FORGF/src/HmiLogging/HmiLogging.pro
', line 2):
#echo header xyz = $#
However, I do NOT see the "echo header xyz $#"-rule being executed.
Regarding the %: rule, it is neither executed for the .cpp files nor "bound" to them in the --print-data-base section.
However, it is bound and executed for existing targets which have no suffix i.e.
all: library binary
binary: | library
ifs: | library
For the %: rule, the reason for this behavior is because of 10.5.5 Match-Anything Pattern Rules: If you do not mark the match-anything rule as terminal, then it is non-terminal. A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.
If I make it non-terminal - no double colon - then the rule doesn't apply to built-in types like .cppunless I un-define the built-in rules that negate my intended %: rule.
If I make it terminal, "it does not apply unless its prerequisites actually exist". But a .h or .cpp doesn't technically have prerequisites; can I just create a dummy file and have that as its prerequisite?
NOTE: This has NOTHING to do with gcc -M generation. Yes the -M option would help in the specific case of header and source files but this question is for more generic targets and prerequisites that already exist in the makefile when make is launched.
This may take a few iterations. Try:
%.h: null
#echo header xyz = $#
%: null
#echo other xyz= $#
null:
#:
Try generating static pattern rules for the header files. See one of the answers to Make ignoring Prerequisite that doesn't exist.
Static pattern rules only apply to an explicit list of target files like this:
$(OBJECTS): %.o: %.c
*recipe here*
where the variable OBJECTS is defined earlier in the makefile to be a list of target files (separated by spaces), for example:
OBJECTS := src/fileA.c src/fileB.c src/fileC.c
Note that you can use the various make utility functions to build that list of target files. For example, $(wildcard pattern), $(addsuffix), etc.
You should also ensure that the recipe "touches" the header file to change the timestamp.
I've found that using static pattern rules instead of pattern rules fixes problems where make doesn’t build prerequisites that don’t exist, or deletes files that you want.
Here is an example of using wildcard to copy files from one directory to another.
# Copy images to build/images
img_files := $(wildcard src/images/*.png src/images/*.gif src/images/*.jpg \
src/images/*.mp3)
build_images := $(subst src/,$(BUILD_DIR)/,$(img_files))
$(build_images): $(BUILD_DIR)/images/% : src/images/%
mkdir -p $(dir $#)
cp -v -a $< $#
There are other make functions like addprefix that could be used to generate a more complex file specification.

Understanding pattern rules

I am trying to wrap my head around pattern rules and how they function. I am using this article for reference which states
A pattern rule is a concise way of specifying a rule for many files at
once. The rule will depend on the file names, but usually it depends
on them in a simple way. You specify a pattern by using the %
wildcard. When present in the dependency list, % matches any string of
any length; when present in the list of targets, % stands for the
string that % in the dependency list matched.
The following pattern rule will take any .c file and compile it into a
.o file:
%.o: %.c $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)
(This assumes that you have the variables CC, CFLAGS, and INCLUDES
defined to be something suitable. Makepp will guess a value for CC and
CFLAGS.)
The first line of the rule says that it applies to every possible
input file that matches the pattern %.c. These .c files can be
transformed into the corresponding .o file using the specified
actions.
The action of rule is quite similar to the other actions we've seen
previously, except that it uses automatic variables. An automatic
variable is a variable whose value is automatically set by makepp
depending on the rule that it appears in. Some useful automatic
variables are:
$(input)
The name of the first input file. In this rule, this would be the file that matches the %.c pattern. $(dependency) is a synonymn for $(input). In older makefiles, you will also see the cryptic symbol $< used as well.
$(output)
The name of the first output file. In this rule, this would be the file that matches the %.o pattern. $(target) and $# are synonymns.
$(inputs)
The name of all explicitly listed input files. In this case, since there is only one, $(inputs) is equivalent to $(input). $(dependencies) and $^ are synonymns.
$(outputs)
The name of all explicitly listed targets. In this case, since there is only one, $(outputs) is equivalent to $(output). $(targets) is a synonymn for $(outputs).
Here are the questions that I have:
1 ) Suppose I have 2 files FileA.c and FileB.c. When I apply the above mentioned pattern rule how would that apply to the above two files. The example given only deals with one file.
2) Whats the difference between the automatic variable input and inputs
A pattern rule will be applied to each target file that matches the rule that make needs to build.
So if you need to build both FileA.o and FileB.o (because they are both listed as prerequisites of some other target (e.g. FileBin: FileA.o FileB.o) that rule will be run twice, once for each.
Take the rule
FileBin: FileA.o FileB.o
#echo '$$input = $(input)'
#echo '$$inputs = $(inputs)'
When run that would output
$input = FileA.o
$inputs = FileA.o FileB.o
It should also be pointed out that input and output are makepp variable names and not valid for GNU make itself.

Resources