Match anything pattern rule with dependency - makefile

File Name: Makefile.mk
%: foo
#echo %: $# with foo
foo:
#echo foo
Run
$ make -f Makefile.mk test
Output:
foo
%: Makefile.mk with foo
%: test with foo
I am running this in GNU Make 3.81 version.
I Don't understand, why file name also printed(%: Makefile.mk with foo).
Can some one please explain me?

This is because of how makefiles are remade. That is to say that
Sometimes makefiles can be remade from other files
and
If a makefile can be remade from other files, you probably want make to get an up-to-date version of the makefile to read in
so
after reading in all makefiles, make will consider each as a goal target and attempt to update it.
Which then matches against your match-anything rule and triggers the way you see.
If you add an explicit Makefile.mk: ; target to your makefile it will override the match-anything target and prevent this.

Related

Patterns in makefile targets

Makefile:
%_file:
touch $#
foo_%: %_file
bar: foo_bar
Results:
>make foo_bar
make: *** No rule to make target 'foo_bar'. Stop.
>make bar
make: *** No rule to make target 'foo_bar', needed by 'bar'. Stop.
I have intentionally omitted adding .PHONY rules because I know the prerequisites of phony rules are always interpreted as literals. I do not see any reason that make foo_bar or make bar should not run without error. What am I missing?
You have a dependency between foo_% and %_file, but you have defined any rules on how to build foo_%. So when you run:
make foo_bar
Make figures out it first needs to build bar_file, but can't find any rules for building foo_bar. If you were to write instead:
%_file:
touch $#
foo_%: %_file
cp $< $#
bar: foo_bar
Then running make foo_bar would result in:
touch bar_file
cp bar_file foo_bar
rm bar_file
To clarify #larsks answer, the GNU make manual says:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.
So your pattern rule:
foo_%: %_file
does not create a pattern rule, it deletes a (non-existent anyway) pattern rule.
If you want a pattern rule it must have a recipe.

Make target with optional wildcard dependency doesn't update when dependency does

I'm using a makefile to build some documents from markdown. Since I have various possible outputs, I'm using a pattern rule. And since the input documents may or may not have associated tables, they have a wildcard dependency for csv files with the same stem filename:
tables = $(wildcard $*_*.csv)
%.docx: %.md $(tables)
#echo building $#
#touch $#
This works fine the first time:
$ touch thing.md
$ touch thing_table.csv
$ make thing.docx
building thing.docx
$ ls thing.docx
thing.docx
However, if the table file is updated, make still thinks everything's up to date:
$ touch thing_table.csv
$ make thing.docx
make: `thing.docx' is up to date.
I think this must have something to do with the order in which make evaluates things, but I don't understand it well enough to figure out how to make this work.
I can do sort of what I want to do using a more "literal" pattern rule:
%.docx: %.md %_*.csv
#echo building $#
#touch $#
But of course this fails in the absence of appropriately-named csv files:
$ rm thing.docx thing_table.csv
$ make thing.docx
make: *** No rule to make target `thing.docx'. Stop.
Is there a way to specify a target dependency such that if a target is foo.docx the dependencies would be foo_*.csv, but have those dependencies be optional (i.e. the target still works if the files don't exist) AND have it appropriately update if those optional dependencies change?
Ok, it looks like secondary expansion will work here:
.SECONDEXPANSION:
%.docx: %.md $$(wildcard $$*_*.csv)
#echo building $#
#touch $#

Specify all Makefile targets as .PHONY with wildcard

All targets in my Makefile aren't real files, is it valid to specify just .PHONY: %. Or should I list all targets?
You need to list all the targets that are meant to be phony targets as prerequisites of the .PHONY target instead of just writing .PHONY: %.
.PHONY: % doesn't do what you think it does (i.e., turning every target into a phony target).
As an example, consider the following makefile:
.PHONY: %
foo:
#echo creating $#
#touch $#
For this makefile above:
$ make
creating foo
$ make
make: 'foo' is up to date.
Therefore, the target foo is not turned into a phony target by having .PHONY: % in your makefile. Otherwise, foo's recipe would have been executed, since phony targets are always outdated.

How to determine if Make target is a PHONY?

I have a make target that depends on a variable, which contains both PHONY and real targets.
This target needs to depend only on the real targets in the variable.
How can I test a variable to determine if it is a PHONY or not, so I can filter them out?
(I can test for a file's existence inside the recipe, but I don't want my target to be triggered by execution of any of the PHONY targets.)
Thanks!
There is a way to do it, but I would strongly recommend against it. First of, phony targets can be also file targets. And there is no way to tell a phony file target from a non-phony file target.
It looks like the question implies that the phony targets the author wants to ignore are all non-file targets. In this case see the example below.
.PHONY: phony_target .FORCE
.FORCE:
ALL_TARGETS = phony_target file_target undetermined_target
-include detect_phony.inc
all: final_target
# All done
final_target: $(REAL_TARGETS)
# create $# triggered by $?
#touch $#
ifeq (,$(MAKE_RESTARTS))
# Generate the list of real file targets in make include file
detect_phony.inc: .FORCE
#echo 'REAL_TARGETS = ' `ls $(ALL_TARGETS) 2>/dev/null` > $# |:
endif
file_target:
touch $#
undetermined_target phony_target:
# process $#
clean:
rm -f file_target final_target
Here are the test results:
$make clean
rm -f file_target final_target
$ make
# create final_target triggered by
# All done
$ touch file_target
$ make
# create final_target triggered by file_target
# All done
$ make
# All done
As you can see it only triggers the final target when the file target is updated.
Before you criticize - Here are the flaws of this implementation:
make is always called twice, updating the generated detect_phony.inc include file at every run
if detect_phony.inc gets corrupted somehow, make execution will be locked by syntax errors, until you manually delete it.
it can't handle phony file targets as I mentioned before
if another generated include is added in this makefile that requires another restart before detect_phony.inc this functionality will break.
So it this method is hacky and has several gotchas. I would not use it in production environment. I would insist on changing the top level Makefile first.

How does % in Makefiles work?

I am trying to understand how makefiles work. If I try the following
1.out : 1.inp
cat 1.inp
it, works as expected (if 1.inp is newer as 1.out or if 1.out does not exist, the content of 1.inp is printed).
Then I need to do the following:
cat 1.inp
cat 2.inp
cat 3.inp
I thought that for that I can use
%.out : %.inp
cat $<
but it does not work. Can anybody please explain to me the use of %?
In your first makefile:
1.out: 1.inp
cat 1.inp
1.out is a target with a prerequisite 1.inp and a command cat 1.inp. This constitutes a rule for
making 1.out and if you run the makefile, specifying either no explicit target or the target 1.out, the
rule will be executed.
In your second makefile:
%.out: %.inp
cat $<
you have only expressed a pattern rule for making a target of the form something.out from a prerequisite of the form something.inp You have not specified any actual targets that the makefile can make.
You can specify 1.out as a target with a makefile like this:
%.out: %.inp
cat $<
1.out:
In that case 1.inp will be cat-ed when 1.inp is newer that 1.out
Or you can specify a phony target, e.g. all, that has prerequisite targets 1.out, 2.out, 3.out in a makefile like this:
.PHONY: all
%.out: %.inp
cat $<
all: 1.out 2.out 3.out
In this case each of 1.inp, 2.inp and 3.inp will be cat-ed when it is newer than the corresponding .out file.
Whenever make discovers that it has to make a target of the form something.out, it will recognize that the pattern rule is applicable and will execute the matching instance of the pattern rule.

Resources