How tp undefining variables in Makefile - makefile

In the Makefile manual, version 4.3 section 6.9
it shows the followings:
foo := foo
bar = bar
undefine foo
undefine bar
I put the content in the Makefile and type make (the code does not have indentation at the beginning of each line)
I see Makefile:4: *** missing separator. Stop.
Since I am using 3.81 version make, I also checked the Makefile manual of that version and I believe this is supported.
I wonder if there is anyone know the answer for this simple Makefile mistake.
Thanks.
KT

undefine was added in GNU make 3.82, released over 11 years ago.
See the NEWS file description of this feature.

Related

Possible bug in GNU make 4.3?

I have the following line in the Makefile of a software I'm working with:
VERSION = $(subst $(space),.,$(wordlist 1,2,$(subst ., ,$(patsubst v%,%,$(shell cat VERSION)))))
Where VERSION is a file containing the exact version of the software (f.e 3.12.3)
I'm not such an expert in Makefiles but this line should return the major version (without the v indicating TAG), in this case, 3.12. And it does, or, at least, it does it when you run it with GNU make <= 4.2
I've recently updated to make 4.3 (because I use a rolling release, Arch Linux) and then executing the same line in my makefile, I got 3 12. instead of 3.12
I've been reading Make changelog in order to check if there is any change in something related to the line in charge of retrieving the major version but I can't find where the problem is.
I've confirmed that the problem appears only with GNU make 4.3 (it works with make 4.2) and I'm wondering if there is a bug or I am missing something.
Maybe someone could help me.
Best regards
As G.M. mentioned, it all depends on how you've defined space, which you haven't shown us.
It worked for me using the "normal" way of defining space, with GNU make 4.3:
E =
space = $E $E
VERSION = $(subst $(space),.,$(wordlist 1,2,$(subst ., ,$(patsubst v%,%,$(shell cat VERSION)))))
$(info VERSION='$(VERSION)')
Then:
$ cat VERSION
v3.12.3
$ make --version
GNU Make 4.3
...
$ make
VERSION='3.12'
As MadScientist and G.M mentioned, the problem was in the definition of space. I dind't noticed it was defined as
space =
space +=
and, according to Makefile 4.3 change log:
* WARNING: Backward-incompatibility!
Previously appending using '+=' to an empty variable would result in a value
starting with a space. Now the initial space is only added if the variable
already contains some value. Similarly, appending an empty string does not
add a trailing space.
The expected behavior for += to an empty variable has changed... so here is the problem!
Thank you very much!

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. :(

Command-line option '--what-if' in makefile does not work [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
From theGNU Make docs:
-W FILE
--what-if=FILE
--assume-new=FILE
--new-file=FILE
"What if". Each '-W' flag is followed by a file name. The given
files' modification times are recorded by 'make' as being the
present time, although the actual modification times remain the
same. You can use the '-W' flag in conjunction with the '-n' flag
to see what would happen if you were to modify specific files.
And there, elsewhere:
'-W FILE'
'--what-if=FILE'
'--new-file=FILE'
'--assume-new=FILE'
Pretend that the target FILE has just been modified. When used
with the '-n' flag, this shows you what would happen if you were to
modify that file. Without '-n', it is almost the same as running a
'touch' command on the given file before running 'make', except
that the modification time is changed only in the imagination of
'make'. *Note Instead of Executing Recipes: Instead of Execution.
So, given a makefile:
# 'all' is "up-to-date", when it is "checked" against its prerequisites 'foo'.
$(shell touch foo)
$(shell sleep 1)
$(shell touch all)
all : foo
echo '$#'
foo : phony
: blah blah
.PHONY : phony
Running, I get:
# 'all' would-be "up-to-date", when it is "checked" against its prerequisites 'foo'.
$ touch 'foo'
$ sleep 1
$ touch 'all'
# To quote the documentation, cited above, we:
# "Change the modification-time in the imagination of Make", for the file: 'foo'
$ make --new-file='foo'
: blah blah
No commands were executed for the file 'all', despite the explicit command-line option --new-file=foo, that was supposed to change the modification-time in the "imagination" of Make, as explained in the quote above.
OK. your understanding to this flag is wrong. gnu make keeps track of the files generated. your test program is bazaar, because nothing is generated from the dependencies.
in your original program:
foo : phony
: blah blah
.PHONY : phony
phony is a pseudo target, which make shall mandatorily run it and the targets that depends on it. that's the reason your code for foo target gets run -- it has nothing to do with the state of the file foo in your file system.
since all depends on foo, however, to generate foo, the modification time before running the command and after are the same, so at make's point of view, there is no need to generate all at all, which is very much expected behavior for common make usage.
following is my code to demonstrate what this flag is for:
all : foo
touch all
foo : phony
touch foo
then in your console:
$ touch phony && make
touch foo
touch all
then again:
$ make
make: 'all' is up to date.
the reason should be obvious. then if i add that flag:
$ make --new-file=phony
touch foo
touch all
now you shall see.
the difference here, is in make's imaginary, the dependency phony has been modified, therefore the whole dependency tree needs to be refreshed too.
if we combine the documentation:
When used
with the '-n' flag, this shows you what would happen if you were to
modify that file.
this makes a lot of sense, because it allows me to probe the dependency tree and see how many things need to be rebuilt if i modify this file.

Conditional part of makefile always evaluating to true

I have a legacy makefile based build system that I am trying to make changes to. I am not familiar with make and so was making changes on a trial and error basis.
Not being able to deduce what the problem is I inserted this bit of code in the makefile:
ARG1 = GCC
ARG2 = ARM
ifeq($(ARG1),$(ARG2))
$(warning *** WARNING ***)
endif
When I run make, I always get the print:
\PathToBuildDirectory\makefile.options:54:*** WARNING ***
NOTE: I am using clearmake with the -C gnu option.
How or why does the condition evaulate to true?
If it behaves this way for a makefile consisting of only the above content then it's a bug in clearmake. I know that clearmake's emulation of GNU make is incomplete, but this seems pretty simple.
However, since you're already echoing an error wouldn't it be straightforward to also show the values of ARG1 and ARG2? Maybe they ARE equal. Maybe one or both are set on the command line. Maybe elsewhere one or both was assigned with the override option. Maybe clearmake is invoked with the -e option and one or both of those variables are set in the environment.
If you show their values, then you'll know.
ETA: Maybe the problem is this: in GNU make you must put a space after the ifeq, like this:
ifeq ($(ARG1),$(ARG2))
If you try your original version with GNU make, you'll get an error:
Makefile:3: *** missing separator. Stop.
but I guess clearmake just ignores the line without any error messages.

What does CC?= in a Makefile mean?

I have a Makefile for a C program that has the declaration
CC?=gcc
Changing it to
CC?=g++
does NOT make it compile with g++. Changing it to
CC=g++
DOES make it use g++.
So I wonder what the ?= operator does? My guess is that it looks at a environment variable to decide which compiler to use and if it's not set then use gcc? Anyone who can clear this up?
From http://www.gnu.org/software/make/manual/make.html:
There is another assignment operator
for variables, `?='. This is called a
conditional variable assignment
operator, because it only has an
effect if the variable is not yet
defined. This statement:
FOO ?= bar
is exactly equivalent to this (see The
origin Function):
ifeq ($(origin FOO), undefined)
FOO = bar
endif
Probably CC is already defined as gcc, so CC ?= g++ won't override the existing gcc.
The ?= operator sets the variable only if it isn't already set: info make → * Using Variables → * Setting.
As others mentioned, it is likely already predefined.
On GNU, you can see what is defined with make -p from a directory that does not contain a Makefile.
This is documented at: https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
CC
Program for compiling C programs; default ‘cc’.
Usually, CC=cc by default. Then on Ubuntu 14.04 for e.g., cc is usually a symlink to gcc.
To disable all variables at once see: Disable make builtin rules and variables from inside the make file Seems currently impossible.
The "?" operator means set if not already set.
So, if CC is already blank CC?= will set it. If CC already contains something, it won't.
Source: http://unix.derkeiler.com/Mailing-Lists/FreeBSD/questions/2007-03/msg02057.html

Resources