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)
Related
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
I have the following project structure:
project/
- Makefile
- foo/
- foo.mk
- bar/
- bar.mk
Contents of Makefile:
.PHONY: all foo bar
all: foo bar
include foo/foo.mk
include bar/bar.mk
Contents of foo/foo.mk:
SOME_VAR=foo
foo:
#echo $(SOME_VAR)
Contents of bar/bar.mk:
SOME_VAR=bar
bar:
#echo $(SOME_VAR)
Running the command make in yields the output
bar
bar
The observed output is easy to explain: variables in recipes are expanded only when the rule is executed, so when SOME_VAR is overwritten in bar.mk the rule for foo prints bar. Is there any way of preventing this behaviour?
One way is to use target-specific variable values.
Change your sub-makefiles to
bar: SOME_VAR=bar
bar:
#echo $(SOME_VAR)
foo: SOME_VAR=foo
foo:
#echo $(SOME_VAR)
Recursive make will also work
all:
$(MAKE) -C foo -f foo.mk
$(MAKE) -C bar -f bar.mk
Let's consider this Makefile:
.SUFFIXES:
.DEFAULT_GOAL := all
out=foo
clean:
rm -f vars.mk
rm -f $(out)
vars.mk: vars.mk.default
#echo "Regenerating $#..."
cp $< $# # Let's assume the translation is much complex than a cp
-include vars.mk
ifeq ($(filter foo,$(FOO)),)
$(error FOO undefined)
endif
all: $(out)
$(out): vars.mk
echo "Cow says: I am not a $(FOO)." > $#
And the file vars.mk.default
FOO = foo bar
I would like to regenerate my targets if vars.mk.default is updated. Furthermore, as double check, one must check that foo exists in $(FOO).
How to force make to regenerate vars.mk if vars.mk.default is updated?
In other words, I would like this output:
$ make clean
$ sed 's/dog/cat/' vars.mk.default
$ make foo
Regenerating vars.mk...
echo "Cow says: I am not a cat" > all
$ make foo
make: Nothing to be done for 'all'.
$ sed 's/cat/dog/' vars.mk.default
$ make
Regenerating vars.mk...
echo "Cow says: I am not a dog" > all
$ rm vars.mak
$ make
Regenerating vars.mk...
echo "Cow says: I am not a dog" > all
To avoid failing if vars.mk doesn't exist, just check for it first:
ifeq ($(wildcard vars.mk),vars.mk)
ifeq ($(filter foo,$(FOO)),)
$(error FOO undefined)
endif
endif
My goal is to regenerate my targets if vars.mk.default is updated.
In this case make your targets depend on that file, but filter it out in the recipes, e.g.
foo.o : foo.cc vars.mk.default
$(COMPILE) $(filter-out vars.mk.default,$^)
In the case vars.mk does not exist, make fails on the ifeq and do not generates vars.mk.
Make is going to build vars.mk and restart, see How Makefiles Are Remade for more details.
So, to avoid that error, check first if FOO is defined with ifdef FOO.
A couple of things. First, you should put a - in front of the include to prevent a warning from popping up if the file does not exist:
-include vars.mk
This will not cause a fatal error if vars.mk is not generated, but because the vars.mk rule would fail in this case, you would get your error from there.
You can then check if $(FOO) contains foo from within a recipe:
checkForFoo: vars.mk
#[[ $(FOO) =~ .*foo.* ]] || false
all:checkForFoo
The recipe is only run after the vars.mk was generated and included, so it should only fail in the conditions you want.
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.
I am trying to compile set of targets. However it only seems to do the first one. Below is a cut down of the my makefile that shows the error.
OBJECTS = abc def ghi
SOURCES = abc.c def.c ghi.c
$(OBJECTS): $(SOURCES)
#echo target is $#, source is $<
In shell,
$ touch abc.c def.c ghi.c
$ make
When I run make I get the following output:
target is abc, source is abc.c
So it only seems to be running the first target.
If I replace $< with $^, the output is:
target is abc, source is abc.c def.c ghi.c
My question, is it possible to perform expansions on variables like with the (%: %) pattern?
Try this:
OBJECTS = abc def ghi
all: $(OBJECTS)
$(OBJECTS):%:%.c
#echo target is $#, source is $<
The trouble was
The default target (which is what Make chooses if you just type `make`) is the first target in the makefile, which was `abc`.
You made all sources prerequisites of every object. That is, all three sources were prerequisites of `abc`. They were also prerequisites of `def` and of `ghi`.