Disable cflag in makefile - makefile

If a macro is being defined on the compiler, as:
cflag += -D name
How could I disable this definition?

If you want to remove a flag from cflag, you can either:
Comment out the line that adds the flag.
Reset cflag to a known value that excludes the flag.
Use $(subst) to strip the flag from cflag, as follows:
cflag := $(subst -D name,,$(cflag)
Note that you could also do the substitution at the point where cflag is referenced.

Related

What does "$(#:%.o=%.d)" mean in a makefile?

I see below command options for GCC in a makefile:
... -MMD -MP -MF "$(#:%.o=%.d)" -MT "$(#:%.o=%.d)" -o "$#" "$<"
How to interpret it?
I searched through the makefile document, but no luck so far.
(This is not just about Automatic Variables)
$(:=) performs a string replacement.
$# is the name of the file being generated (the target).
So $(#:%.o=%.d) is the name of the file, with the .o extension changed to .d.
This command line generates one .d dependency file for each .o file.
(Thanks to #Quentin's clue. I just found it!)
It is called Substitution Reference
Some quote:
A substitution reference substitutes the value of a variable with
alterations that you specify. It has the form ‘$(var:a=b)’ (or
‘${var:a=b}’) and its meaning is to take the value of the variable
var, replace every a at the end of a word with b in that value, and
substitute the resulting string.
When we say “at the end of a word”, we mean that a must appear either
followed by whitespace or at the end of the value in order to be
replaced; other occurrences of a in the value are unaltered. For
example:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
sets ‘bar’ to ‘a.c b.c c.c’. See Setting Variables.
A substitution reference is actually an abbreviation for use of the
patsubst expansion function (see Functions for String Substitution and
Analysis). We provide substitution references as well as patsubst for
compatibility with other implementations of make.
So, the full interpretation of the following command:
... -MMD -MP -MF "$(#:%.o=%.d)" -MT "$(#:%.o=%.d)" -o "$#" "$<"
is:
Use gcc to compile the 1st prerequisite file ($<) and generate the
output file named after the current rule target's name (%#). And by
the way, generate a makefile named as *.d containing a rule to describe the dependency of current rule target. And change the name of rule target in the
generated *.d makefile from *.o to *.d.

How to pass down option -f SomeMakefile to a sub-make? [here with GNUMake]

When invoking itself recursively via some $(MAKE) foo in recipes, GNUMake passes down some of the options it was called with, but not all of them. In particular it does not pass down a -f SomeMakefile option. See section 5.7.3 of manual.
How can I find whether make was invoked with some -f option and how can I pass it down to a sub-make ?
To make the question concrete, here is what my SomeMakefile contains:
%.pdf : %.tex
pdflatex $(PDFLATEXFLAGS) $*
#if [ -f $*.log ] ; then $(MAKE) --silent $*.slw; fi
The problem is that how to make foo.slw is defined in SomeMakefile and the recursive make won't use it.
You can get the name of the makefile from MAKEFILE_LIST variable. E.g.:
${MAKE} -f $(lastword $(MAKEFILE_LIST))
If your makefile includes other makefiles you may like to store the name of the makefile early into an immediately assigned variable, e.g.:
# Somewhere at the top of your makefile, before any includes
this_makefile := $(lastword ${MAKEFILE_LIST})
# and use it later
some_rule :
${MAKE} -f ${this_makefile}
Alternatively, if you know that your makefile is always the first one read by make, then it is going to be in the front of MAKEFILE_LIST, e.g. $(firstword ${MAKEFILE_LIST}).

GNU make is adding white space after -I (shared directory) option

I'm trying to use armclang compiler through a GNU makefile, but there is a clash between both tools when using -I option.
For armclang compiler, the -I means "Adds the specified directory to the list of places that are searched to find included files.Syntax -Idir" without a space.
For GNU makefile ‘-I dir’ has the same meaning (but with a space).
in My makefile I have the following:
$(aarch32_bootobj): %.o: %.s
#echo " [ASM ] $<"
#armclang --target=armv8a-arm-none-eabi -Icommon/shared -c $< -o $#
When Running the Makefile, I'm getting the following Warning and Error :
armclang: warning: argument unused during compilation: '-I common/shared'
aarch32/shared/bootcode.s:32:10: error: Could not find include file 'boot_defs.hs'
Where boot_defs.hs exists under common/shared
When running the same armclang command outside the makefile, it works. therefore I'm assuming that makefile has formatted the -Icommon/share option and added automatic space just after the -I.
Is there any way to run the armclang command correctly? in other worlds, is it possible to let the makefile parse the -Icommon/shared without any automatic formatting?
I have been trying a lot of tricks to workaround that without any success.
Thanks a lot In advance.
GNU make doesn't split the -Icommon/shared option, and even if it did armclang would be able to parse that. If you remove the # from the armclang call in the Makefile, you'll see exactly what make does and that the -Icommon/shared parameter remains intact.
Your problem is with armclang; see this bug on the tracker. It doesn't pass -I flags to its integrated assembler. A workaround, then, should be to pass -no-integrated-as to armclang:
#armclang -no-integrated-as --target=armv8a-arm-none-eabi -Icommon/shared -c $< -o $#
If that doesn't work, replace the .include directive with #include and either rename your asm files to .S (upper-case S), which indicates that they need C preprocessing, or pass armclang the -x assembler-with-cpp flag. The behavior of this is documented here.

Do I need to pass CFLAGS explicitly to gcc?

I read a lot of tutorials about CFLAGS and also looked in the official docs. Everywhere they say CFLAGS is implicit but still pass it explicitly in their example makefile to the compiler:
CFLAGS=-O2
gcc $(CFLAGS) -c foo.c -o foo.o
So, what does the term "implicit" mean in this context? If I declare CFLAGS=-O2 in my makefile and later just say gcc -c foo.c -o foo.o, will -O2 be active or not (so, is it really implicit)? If so, why do all tutorials (including official docs) still pass it explicitly in their examples?
Everywhere they say CFLAGS is implicit but still pass it explicitly in their example makefile to the compiler.
gcc does not use CFLAGS environment variable. See Environment Variables Affecting GCC.
CFLAGS is a conventional name for a Makefile variable with C-compiler flags and it is used by implicit make rules. See Variables Used by Implicit Rules for more details.
If you use your own make rules instead of the built-in ones, you do not need to use CFLAGS at all. Although it is a useful convention to do so because people are familiar with the conventional make variable names.
I believe CFLAGS is implicitly passed to the compiler command line by the makefile via the default compilation rule... Yet the CFLAGS can be overridden with custom flags so that each compilation command will take it and use.
You can test it easily:
$ cat cflags.mak
CFLAGS = -wrong
foo.o: foo.c
$ make -f cflags.mak
cc -wrong -c -o foo.o foo.c
cc: unrecognized option '-wrong'
So you can see it used the value of CFLAGS even though it was not explicitly specified in a rule; thus it is implicit.
But if you do specify your own rule for compiling .c files, you have to include it if you want it used:
$ cat cflags.mak
CFLAGS = -wrong
foo.o: foo.c
gcc -c $<
$ make -f cflags.mak
gcc -c foo.c
Here I provided my own rule for .c files which did not include CFLAGS, so CFLAGS was not used.
So the bottom line is if you rely on the built-in make rule for compiling .c files, CFLAGS will be included implicitly. But if you override that rule, you have to include it explicitly if you still want it to be used.
It means that there are implicit make rules, that use the CFLAGS, you can use.
So you can write a one line makefile with:
CFLAGS=-O2
if you later do:
make filename
(omitting extension) it will use an implicit rule that references the CFLAGS to convert you source file .c in an executable, so you don't need to write an explicit build statement for simple builds.
E.g. if you prepared a source name file.c it will build it with an implicit rule like:
$GCC $CFLAGS file.c -o file $LDFLAGS
see: GNU make documentation

How to specify --no-print-directory within the Makefile itself

I'd like to run my makefile without the -w flag turned on by the recursive make calls.
The flag to do that is --no-print-directory on the make command line.
Is it possible to specify that flag within the makefile itself?
I plan to make this flag dependent on a VERBOSE mode, perhaps something like
$(if $(VERBOSE),,MAKEFLAGS += no-print-directory))
Thanks,
Dan
Yes, just appending --no-print-directory to MAKEFLAGS should be enough, but you have to do that with conditional directives, not with conditional functions:
ifndef VERBOSE
MAKEFLAGS += --no-print-directory
endif
You can include the .SILENT: special target in the calling makefile. For example, here's your toplevel makefile:
all:
$(MAKE) -f sub.mk foo
.SILENT:
and the submake makefile, sub.mk:
foo:
#echo done
Note that .SILENT is considered obsolete, so it may not be around forever, and also note that including that in your makefile also has the effect of suppressing command echo, just as if you had put # before every command in the makefile.

Resources