Makefile assignment to special variable .DEFAULT_GOAL is not expanded - makefile

.DEFAULT_GOAL=${IMG}
BUILD_DIR=build
IMG=${BUILD_DIR}/hd60M.img
BIN=${addprefix ${BUILD_DIR}/,${addsuffix .bin,${objects}}}
${IMG}:${BIN}
touch $#
make -n gives the result:
make: *** No rule to make target `${IMG}'. Stop.
If I change the first line to .DEFAULT_GOAL=build/hd60M.img, it works without error messages.
It seems that assignment to .DEFAULT_GOAL is not expanded. Why?

You should use := instead of =, () instead of {}, and expand variables AFTER setting them:
# Expand rhs on assignment
IMG := $(BUILD_DIR)/hd60M.img
…
# Set default goal after variable is set
.DEFAULT_GOAL := $(IMG)

I find the problem is due to my make version.
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
After I updated GNU make to the newest version, the problem is solved.

Related

Why make is locking up?

I've defined below function inside makefile.
# check debug xdc
define check_debug_xdc
if [ -f ${DEBUG_XDC} ]; then \
...
fi
endef
make runs fine, if directly call it.
# Optimize
${OUTPUTS1}: ${INPUTS1}
#echo ""
#echo "Optimization"
#date '+%Y_%m%d_%H%M'
#$(call check_debug_xdc)
But if I commented out DEBUG_XDC and put $(call check_debug_xdc) inside if-fi to check whether DEBUG_XDC is defined or not, make stops responding, nothing is printing out, even the date.
# DEBUG_XDC = ./fpga_ila/fpga_ila.srcs/constrs_1/new/${TOP}.xdc
...
# Optimize
${OUTPUTS1}: ${INPUTS1}
#echo ""
#echo "Optimization"
#date '+%Y_%m%d_%H%M'
#if [ ! -z "${DEBUG_XDC}" ]; then $(call check_debug_xdc); fi
Tried make -dn, it prints below message then stop responding.
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i686-pc-linux-gnu
Reading makefiles...
Reading makefile `makefile'...
Updating makefiles....
Considering target file `makefile'.
...
Finished prerequisites of target file `fpga/fpga_opt.dcp'.
Must remake target `fpga/fpga_opt.dcp'.
How to fix it?

GNU make builtin functions not working

Tried to get GNU make 3.81 Built-in Function to work
but kept getting an error message.
I built a simple makefile:
FOO=bar
$(info $(FOO) $(origin FOO))
$(firstword $(origin FOO))
and ran it.
The first function works but second will not.
Error message is:
...
$ make -d
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i686-pc-linux-gnu
Reading makefiles...
Reading makefile `makefile'...
bar file
makefile:6: *** missing separator. Stop.
...
First two functions work correctly so why is this happening? Am I not seeing something obvious or is this $(firstword) function not supported in this version of make?
Thanks for any help.
For the most part, a make file looks like one or more of these blocks:
target: [depends-on]...
command to build
another command
Where the command lines start with a tab. Your error is complaining about finding 2 consecutive lines that look like target lines.
I've never seen the book you speak of, but either it is wrong or you are reading it wrong. Try this:
FOO=bar
all:
$(info $(FOO) $(origin FOO))
echo '<' $(firstword $(origin FOO)) '>'
You need the echo on the last line because firstword is an ordinary substitution function, while info works more like a command.
I put the angle brackets on the firstword line just to show what was going on where.
Again, note that indented lines on Makefiles use tabs not spaces.
The firstword function is a text manipulation function. It takes text as its input, and returns text as its output. It does not write any messages or error output.
As such, when you call it, you are using it to build a makefile. Makefiles have a special syntax, just like any other programming language. When you put text into a makefile, it has to be structured in a particular way - you have to make a statement, or define a variable, or something.
For example, this is what a 'build rule' looks like:
output: input
rule to produce output from input
You put a word into the makefile (the result of $(firstword)), so make assumes you are doing something - defining a variable or specifying a build rule. But you didn't follow up with any other words. Basically, your make program has a syntax error. :(

make SECONDEXPANSION broken by implicit rule recursion?

I'd like to use .SECONDEXPANSION: as described on http://make.mad-scientist.net/secondary-expansion. I have the following makefile:
.SECONDEXPANSION:
x.deps := y.foo
%.foo: $$($$*.deps)
echo $#
Unfortunately, when I try make x.foo, I get
make: *** No rule to make target `.foo'. Stop.
Running it with -Rd, I get
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
Reading makefiles...
[...]
Updating goal targets....
Considering target file `x.foo'.
File `x.foo' does not exist.
Looking for an implicit rule for `x.foo'.
Trying pattern rule with stem `x'.
Trying rule prerequisite `y.foo'.
Trying pattern rule with stem `x'.
Trying rule prerequisite `y.foo'.
Looking for a rule with intermediate file `y.foo'.
Avoiding implicit rule recursion.
No implicit rule found for `x.foo'.
Finished prerequisites of target file `x.foo'.
Must remake target `x.foo'.
make: *** No rule to make target `x.foo'. Stop.
I guess it's not working because, according to the docs, "No single implicit rule can appear more than once in a chain." But that's exactly what I need -- for x.foo to resolve to y.foo, which resolves to a rule with no dependencies. My application demands the uniform (*.foo) naming scheme. Can anyone suggest a work-around? BTW, unfortunately, I must use make 3.81, not something more recent.

How to make "%" wildcard match targets containing the equal sign?

The makefile wildcard system doesn't seem to match targets if they contain the equal sign. Is there a way to work around this deficiency? Some flag or setting or rule to escape the equal sign? I know I can just not use the equal sign but I'd prefer to fix this idiosyncrasy of make if possible.
Here's an example of what I mean
$ cat Makefile
all:
echo Dummy target
b_%:
echo $#
$ make b_c=1
echo Dummy Target
$ make b_c1
echo b_c1
The first make command does not match b_% even though it should. I also wasn't able to find documentation for exactly what is supposed to be matched by the % wildcard. Any pointers? My make version is
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This program built for i386-apple-darwin10.0
The problem here is not with the % syntax, but with the fact that any command-line argument with an equals sign in it is interpreted as a variable assignment.
You should find that if you add the dependency all: b_c=1, then make all will generate the file just fine.
There are restrictions on what file names you can use with make -- they can't contain spaces or newlines, and e.g. backslashes are problematic, too (though not completely impossible to accommodate for simple use cases).
If you absolutely have to have a file named like this, my suggested workaround would be to use a different name internally, and then symlink it to the external name as the last step of the make recipe.

Can I tell if --jobs is used inside a Makefile?

I want to set some variables based on whether or not parallel builds are enabled, so I tried this:
jobs:
»·echo "executing jobs job"
ifneq (,$(findstring -j,$(MAKEFLAGS)))
»·$(warning "parallel!")
else
»·$(warning "not parallel!")
endif
And this is what happens:
$ make -j2
Makefile:2: "not parallel!"
echo "executing jobs job"
executing jobs job
I also tried testing $(JOBS), but no luck.
Is there a way for me to tell inside a Makefile that the --jobs parameter was used?
Additional info:
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
Surprisingly, ${MAKEFLAGS} will only gain the -j when it is expanded at recipe expansion time.
Makefile:
$(warning [${MAKEFLAGS}])
.PHONY: all
all:
$(warning [${MAKEFLAGS}])
echo Now do something useful
Run:
$ make -j5
1:1: []
1:5: [ -j --jobserver-fds=3,4]
echo Now do something useful
Now do something useful
About the MAKEFLAGS expansion in #bobbogo's answer: If we look at the code I think I can explain the behavior:
Looking at the code, main function of make calls the define_makeflags function several times.
/* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the
command switches. Include options with args if ALL is nonzero.
Don't include options with the 'no_makefile' flag set if MAKEFILE. */
static struct variable *
define_makeflags (int all, int makefile)
{
......
Call locations in main:
1)
/* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see.
Initialize it to be exported but allow the makefile to reset it. */
define_makeflags (0, 0)->export = v_export;
2)
/* Set up MAKEFLAGS and MFLAGS again, so they will be right. */
define_makeflags (1, 0);
3)
/* Set up 'MAKEFLAGS' specially while remaking makefiles. */
define_makeflags (1, 1);
There are other calls in sub-functions but this should be enough to explain.
The first call sets all parameter to false. The others set to true. With all set to false, the define_makeflags function only parses "simple flags" and j is not one of them. In order to understand the parsing one needs to look into this switch statement and the definition of command line params.
My SWAG is like the following:
I presume the parsing of ifneq statements happen after the first call to define_makeflags but before the subsequent calls. I can guess the reason of keeping the MAKEFLAGS simple at the start is to continue to support documented Makefile patterns like the following.
From doc1, doc2:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
If MAKEFLAGS contained long options or options that take parameters, then searching for single char flags in MAKEFLAGS would not be possible.
There is some guesstimate in my answer. Maybe someone who was involved in the design decision can also weigh in. Given this change Paul Smith may have an idea.

Resources