Makefile don't check dependency timestamps - makefile

I am writing a makefile like this
foo: bar
touch foo
but I want foo to be built only if it's missing, regardless of whether bar is newer than foo. Is that possible with make?

but I want foo to be built only if it's missing, regardless of whether bar is newer than foo
In this case use an order-only dependency:
foo: | bar
touch foo

To make a target if it does not exist:
foo:
touch foo
To make bar if it's out of date and then make foo if it does not exist:
foo: | bar
touch foo
Note that in the example in the GNU Make documentation that $(OBJDIR) does not depend on anything and only will be made if it does not exist.
PS: Some additional information on how order-only prerequisites work.
$ ls
Makefile
$ cat Makefile
foo1: bar
touch foo1
foo2: | bar
touch foo2
foo3:
touch foo3
$ make foo1 foo2 foo3
make: *** No rule to make target `bar', needed by `foo1'. Stop.
$ touch bar
$ make foo1 foo2 foo3
touch foo1
touch foo2
touch foo3
$ make foo1 foo2 foo3
make: `foo1' is up to date.
make: `foo2' is up to date.
make: `foo3' is up to date.
$ touch bar
$ make foo1 foo2 foo3
touch foo1
make: `foo2' is up to date.
make: `foo3' is up to date.
$ make foo1 foo2 foo3
make: `foo1' is up to date.
make: `foo2' is up to date.
make: `foo3' is up to date.

Related

Can a target's prerequisite without build rule have generated transitive prerequisites?

I have the following Makefile:
.PHONY: all
all: foo qux
foo: bar
cp bar foo
qux: bar
cp bar qux
-include bar.d
clean:
rm -f foo qux
which includes a generated bar.d file:
bar: baz
I'd like to be able to run the rules for foo and qux whenever bar or baz is changed.
Without surprise, it works well when I change bar, but when I change baz, I get the following message:
make: Nothing to be done for 'all'.
If I change the contents of bar.d to the following, I get the expected behaviour:
foo: baz
qux: baz
But it would be easier for me not to have to duplicate the $x: baz rule for every target that depends on bar.
Is there a solution that does not involves changing baz.d?
Since there is no recipe for bar, Make's actions are correct; yes, baz has changed, but there is no way to bring bar up to date, therefore no point in rebuilding the targets that depend on bar.
You can get the behavior you want by adding an "update" recipe to the rule:
bar: baz
#touch $#

Make extra newline in prerequisite in define recipe

I am trying to create a Makefile which uses a recipe created using the define syntax. However, I have run into a problem where Make believes that the last prerequisite has a newline appended to it, resulting in a "no rule found" error. A minimal working example is given below, the problem is triggered by trying to make the foo/bar target.
foo:
mkdir foo
define FIZZ
foo/bar: foo
touch foo/bar
endef
$(call FIZZ)
The exact error message is
make: *** No rule to make target 'foo
', needed by 'foo/bar'. Stop.
I have tried versions 4.1 and 4.2.1 of GNU Make.
Can anyone tell me what I am doing wrong (or is this a bug)?
What you are trying to do here is expand the variable FIZZ to inject the
definition of the target foo/bar (its prerequisites and recipe) into the
expanded makefile. $(call FIZZ) is not the tool for that:
$(call variable,param,param,...)
may behave surprisingly if the arguments contain embedded whitespace. You want
8.9 The eval Function,
as in:
Makefile
foo:
mkdir foo
define FIZZ
foo/bar: foo
touch foo/bar
endef
$(eval $(FIZZ))
Then you'll get:
$ make foo/bar
mkdir foo
touch foo/bar

Is this a make bug?

Most likely it is not but I've been struggling with this one for an hour now:
$ cat Makefile
${FILE1}:
touch $#
a: ${FILE1}
${FILE2}: a
touch $#
$ make FILE1=foo FILE2=bar bar
touch foo
touch bar
$ ls
bar foo Makefile
$ make FILE1=foo FILE2=bar bar
touch bar
Why is the bar rule still activated?
If I change Makefile to:
${FILE1}:
touch $#
${FILE2}: ${FILE1}
touch $#
Everything works, i.e. bar is not touched again.
The target bar has a prerequisite, a. You have a rule for a, but it does not actually build a file named "a". So every time you ask Make to rebuild bar (if necessary), Make sees that the prerequisite a does not exist, and therefore it must attempt to rebuild both targets.

Makefile target dependency to generated files

I have a question regarding the behavior of Make when running targets that are dependent on generated files.
Given the source tree and Makefile below, when I run this it takes two runs to complete the "build" even though everything was generated on the first run.
$ ls -R
.:
bar foo Makefile
Makefile
all: foobar
work:
mkdir -p work
work/foo: work foo
cp foo work/foo
work/bar: work bar
cp bar work/bar
foobar: work/foo work/bar
make
$ make
mkdir -p work
cp foo work/foo
cp bar work/bar
$ ls -R
.:
work/ bar CMakeLists.txt foo Makefile
./work:
bar foo
$ make
cp foo work/foo
$ make
make: Nothing to be done for 'all'.
Why does this happen?
You need to make the directory an order-only prerequisite, otherwise the targets will be remade each time the directory changes; during the second invocation work is newer than work/foo because work/bar was created after work/foo, so work's timestamp is newer than work/foo.
work/foo: foo | work
cp foo work/foo
work/bar: bar | work
cp bar work/bar
Or more concisely
work/foo work/bar: work/%: % | work
cp $< $#

Rule for all targets in make - even if the file exists

I want to create a Makefile that outputs foo no matter what target name is given to make.
So all of these should work:
$ make
foo
$ make a
foo
$ make foobar
foo
The following Makefile does almost what I want:
all %:
#echo foo
.PHONY: all
However it fails if there exists a file with the same name as the target:
$ touch abc
$ make abc
make: `abc' is up to date.
As .PHONY doesn't accept pattern rules, I don't know how I can get make to ignore every file.
How about:
all $(MAKECMDGOALS): ; #echo foo
.PHONY: all $(MAKECMDGOALS)

Resources