What does a colon in makefile dependencies list means? [duplicate] - makefile

This question already has answers here:
Create rule in makefile for just a set of files
(2 answers)
Closed 5 years ago.
I'm working on a project using makefile. Some of the make rules have the following format:
a.o b.o c.o : %.o : %.c
gcc -c $< -o $#
What's the meaning of such a rule? I'm unable to find explanation in the official manual, but I guess it's used for applying pattern-matching on only the *.o files listed as targets. Is that correct?

Quoting from the GNU Make,
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.
The syntax for static pattern rules:
targets : target-pattern: prereq-patterns …
recipe
…
Pattern rule is mentioned as % in the target. It matches any target ends with .o here a.o, b.o and c.o.
Here ‘$<’ is the automatic variable that holds the name of the prerequisite and ‘$#’ is the automatic variable that holds the name of the target.
a.o b.o c.o : %.o : %.c
gcc -c $< -o $#

Related

Makefile: Pattern rule that can ignore directories

I am trying to have a Makefile rule that can generate an object file from a source file in a directory that is specified explicitly.
exe: foo.o bar.o
foo.o: path/to/foo.c
%.o: %.c
echo Making $# from $<
This example will find it needs to make "exe", then search to make "foo.o". The "foo.o" search will try pattern rules with stem "foo" and fail to use the rule because "foo.c" doesn't exist. I want to find a way to have it see that "foo.o" can be compiled from "path/to/foo.c" using the pattern rule.
In my case it doesn't make sense for me to have the rule be "%.o: path/to/%.c" because the path should be specified for each target that needs the source to be located in another directory.
The pattern rule works for "bar.o" being made from "bar.c" within the same directory and I want to keep that working.
The solution I am going with for now is:
define c-to-o-command
echo Making $# from $<
endef
exe: foo.o bar.o
foo.o: path/to/foo.c
$(c-to-o-command)
%.o: %.c
$(c-to-o-command)
This has a drawback that the command for the pattern rule is not visible in the Makefile at the same place. It also will need to be expanded for other pattern rules that may need to have this "out of path" dependency.

Producing object files with GNU make when sources are of different extensions [duplicate]

This question already has answers here:
In gnu make, can the prerequisites in a static pattern rule have different suffixes
(3 answers)
Closed 4 years ago.
Suppose I have three source files: file3.c, file2.c, file3.s which are all not of the same extension. I want to compile it into object files: file1.o, file2.o, file3.o which are of the same pattern.
OBJ = file1.o file2.o file3.o
all: $(OBJ)
#Here I am in the stuck
$(OBJ) : %.o : %.c #or %.s
$(CC) $(CFLAGS) -c $< -o $#
How to do this using pattern rules in GNU make?
The recipe for generating .o files can be made common for both .c and .s files this way:
OBJ = file1.o file2.o file3.o
.PHONY: all
all: $(OBJ)
.SECONDEXPANSION:
%.o: $$(wildcard $$*.c) $$(wildcard $$*.s)
$(CC) $(CFLAGS) -c $< -o $#
The prerequisite, which may end with .c or .s, is determined by secondary expanding the stem (i.e.: $*) and the wildcard built-in function for the filenames resulting from concatenating the stem with the corresponding "extensions" .c and .s.
The "or" is implemented by taking advantage of the fact that the wildcard built-in function is expanded to nothing (as opposed to be expanded to the provided pattern, like the Bash shell does) if the pattern is not matched (i.e.: if there is no filename that matched the pattern provided to wildcard).

What is the semantics of '%' in Makefile?

Googling doesn't help much in understand how the % variable is being used in the Makefile snippet below.
_OBJ = a.o b.o c.o
OBJ = $(patsubst %,$(OBJDIR)/%,$(_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(INC)
$(CC) -c -o $# $< $(CFLAGS)
Can anybody please help me out? Does it mean that if there are five .c files present under $(SRCDIR), that many *.o rules are being populated behind the scene?
That is an "implicit rule". The % makes the word $(OBJDIR)/%.o a pattern. It tells make that if it's trying to build a target and the name of the target matches that pattern (where the % can substitute for one or more characters--any characters), AND that a file that matches the pattern $(SRCDIR)/%.c (where the % here has the same value as in the target) either already exists or can be built, then make can use this recipe to build that target.
So, if make wants to build a file foo/bar.o and the variable OBJDIR has the value foo, then this pattern foo/%.o will match that file with the % matching bar (this is called the stem in the GNU make documentation).
Then if SRCDIR has the value blah and make can find (or create) a file named blah/bar.c, then this implicit rule can be used to build the target foo/bar.o by running this recipe ($(CC) -c -o $# $< $(CFLAGS)).

GNU Makefile - Pattern rule with multiple targets with one dependency ignores all targets but the first

I want to make a language depend target. In Particular: I have one source-file and I want to create different Objects which where add to the corresponding language folder. That single source file will differ in the C-Flags, the compiler will get. As long as I used it in a static way, it works quite fine.
de/info.o en/info.o es/info.o : info.c
$(ECHO) (DEP) $< for $#
Now I thought, it would be great if it is a bit more dynamic, in case i'll add a new language depending file. So I used a wildcard as followed:
de/%.o en/%.o es/%.o : %.c
$(ECHO) (DEP) $< for $#
But now it just make the first target and ignores the rest. The Make-Debug prints the following thing:
Successfully remade target file `de/info.o'.
Considering target file `en/info.o'.
File `en/info.o' was considered already.
Just in case: No, the objects do not exist. So there is no target, but an existing dependencie, so make should execute the rules.
EDIT: Found a solution for that Problem.
define FOO
$(1)/%.o : %.c
$(ECHO) $$< for $(1)
endef
$(foreach lang,$(LANGUAGE_LIST), $(eval $(call FOO,$(lang))))
Inspired by: http://www.gnu.org/software/make/manual/make.html#Eval-Function
Pattern rules work differently than implicit rules. While an implicit rule such as
a b c: d
command
is equivalent to the longer notation
a: d
command
b: d
command
c: d
command
this does NOT hold for pattern rules. Pattern rules with multiple targets are explicitly required to build all of their targets in a single invocation of command. Thus you would have to write
$ cat GNUmakefile
all: de/x.o en/x.o es/x.o
de/%.o: %.c
#echo $# from $<
en/%.o: %.c
#echo $# from $<
es/%.o: %.c
#echo $# from $<
$ gmake
de/x.o from x.c
en/x.o from x.c
es/x.o from x.c
The relevant documentation is found in 10.5.1 Introduction to Pattern Rules of the GNU make manual:
Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets. When searching for a pattern rule to match a target, the target patterns of a rule other than the one that matches the target in need of a rule are incidental: make worries only about giving a recipe and prerequisites to the file presently in question. However, when this file’s recipe is run, the other targets are marked as having been updated themselves.

Force make not to re-order pre-requisites in automatic variable expansion

Here a is my makefile (GNU make) to compile a small OCaml program:
SUFFIXES:=
OCAML=ocamlopt
LD=ocamlopt
OFLAGS=
.PHONY: all clean
all: playground
playground.cmx: playground.ml lstream.cmi
playground: lstream.cmx playground.cmx
%.cmi: %.ml
$(OCAML) $(OFLAGS) -c $<
%.cmx: %.ml
$(OCAML) $(OFLAGS) -c $<
%: %.cmx
$(LD) -o $# $^
playground uses functions from the Lstream module. In this case, the ocaml linker requires the files to link to be specified in order of dependency (eg: ocamlopt -o playground lstream.cmx playground.cmx).
Despite the fact that I defined the playground rule's dependencies in the right order,
make consistently re-orders them and executes ocamlopt -o playground playground.cmx lstream.cmx which causes a linker error.
Is there a way to enforce the correct behaviour ? I would like to avoid specifying the link command explicitely and let make infer it from the dependencies.
Implicit rules always force the pattern matching prerequisite to be first, regardless of the order in which they're defined elsewhere. This is almost always what you want, because in most rules the pattern matching prerequisite is special.
For example when compiling an object file the prerequisites consist of one source file and a bunch of header files; the source file is special and needs to be listed on the command line. Make ensures that for a pattern rule %.o : %.c (for example) the prerequisite matching %.c is first in the list, and so is assigned to the $< automatic variable, and it can be treated differently.
In any event the short answer is no, you cannot modify this behavior. An implicit rule % : %.cmx matching a target playground will always force the prerequisite playground.cmx to be listed first in the prerequisite list. The other prerequisites will maintain their order.
If you really need the prerequisites to maintain their order then I recommend using a static pattern rule:
TARGETS = playground
$(TARGETS) : % :
$(LD) -o $# $^
(you can also use a "match anything" pattern rule but this can be a real performance degrader). Here since you have no pattern in the prerequisite list, nothing will be reordered.

Resources