I'm trying to output a message if debug is enabled
ifeq ($(debug), 1)
$(warning Enabled debug mode, do not use it in production environment)
ccflags-y += -DDEBUG
endif
It won't work because "make" complains about the "warning" line:
Makefile:11: *** recipe commences before first target. Stop.
Any suggestions?
Don't add tabs inside the if body.
Related
I have C++ project that I build using a Makefile with two targets as so
debug: FLAGS += -g3 -DDEBUG -DSOCKET_LOG_COMMUNICATION
#printf ""
test: some_other_target
$(COMPILER) ...
I wanted to call make as so
make debug test
to define a macro and also build the test target. Is this possible?
Target-specific variables apply only to the named target and its dependencies (unless the variable is declared private), so the only way you would be able to have test inherit debug's variables would be debug: test which probably isn't what you're looking for.
One way to do this is use conditional statements:
ifdef debug
FLAGS += -g3 -DDEBUG -DSOCKET_LOG_COMMUNICATION
$(info whatever)
endif
test: some_other_target
$(COMPILER) ...
and invoke make test debug=1.
I am writing a makefile for distribution among students. To ease up their hacking experience, I would like make to warn about uninitialised variables.
I know there is the option --warn-undefined-variables to do just this, and of course, I can add an alias รก la alias make="make --warn-undefined-variables" to my .bashrc. But I would like to set this option within the makefile so students will automatically profit from those warnings too, when they start to extend the makefile.
The logical way to do so would be the MAKEFLAGS variable. However, while it works for short options, I cannot get it to work with --warn-undefined-variables as described in Can make warn me, when I use unset variables?
Makefile:
MAKEFLAGS=--warn-undefined-variables
$(info MAKEFLAGS: $(MAKEFLAGS))
$(info ${BAR})
Call:
$ make
MAKEFLAGS: --warn-undefined-variables
make: *** No targets. Stop.
$ make --warn-undefined-variables
MAKEFLAGS: --warn-undefined-variables
Makefile:3: warning: undefined variable 'BAR'
make: *** No targets. Stop.
When I change the MAKEFLAGS to -d the console is flooded with debug information, so I know MAKEFLAGS is set correctly. Any suggestions?
I have GNU make 4.0 here and I cannot for the life of me get make to honor MAKEFLAGS= --warn-undefined-variables with a straightforward Makefile. However, if I make the Makefile invoke itself, then MAKEFLAGS= --warn-undefined-variables works in the child invocation!
MAKEFLAGS= --warn-undefined-variables
$(info MAKEFLAGS: $(MAKEFLAGS))
$(info $(BAR))
# This prevents a warning if we invoke make without a target...
MAKECMDGOALS?=
all:
ifndef RECURSED
$(MAKE) RECURSED=1 $(MAKECMDGOALS)
else
echo $(FOO)
endif
If I just run make, I get:
MAKEFLAGS: --warn-undefined-variables
make RECURSED=1
make[1]: Entering directory '/tmp/t1'
MAKEFLAGS: --warn-undefined-variables
Makefile:3: warning: undefined variable 'BAR'
Makefile:12: warning: undefined variable 'FOO'
echo
make[1]: Leaving directory '/tmp/t1'
Either I'm borking on something... or there's a bug in make. I'm inclined to think the latter.
I'm trying to do an ifeq inside of a define within a Makefile, but I seem to be running into some errors, and I'm wondering if I'm missing something. I have the following Makefile:
$(info ---- start ----)
ifeq ("X","Y")
$(info DOES not appear_1)
endif
define TESTDEF
ifeq ("X","Y")
$(info SHOULD not appear)
# $(error DEFINITELY SHOULD not error...)
endif
endef
$(eval $(call TESTDEF, 1,2,3))
I'm getting the following error:
---- start ----
SHOULD not appear
Makefile:14: *** DEFINITELY SHOULD not error.... Stop.
Is there some trick that I'm missing? Is it possible to do ifeq's inside define? (note: this happens on both my native GNU 3.81 make, and on my mips uclibc cross-compiler)
When you call this function, Make evaluates the definition, using whatever parameters you provide (irrelevant in this case). So if the definition includes something like $(info ...) or $(error ...), even in a comment, Make will evaluate it and you'll see the result (see documentation; I've tested it in GNUMake 3.81).
To get the behavior you want, add a couple of dollar signs:
define TESTDEF
ifeq ("X","Y")
$$(info SHALL not appear)
# $$(info DEFINITELY SHALL not error...)
endif
endef
$(eval $(call TESTDEF))
I want to print some message while doing build process with a makefile. The following one can print the message, but it will not execute the script after it. How can I fix this issues?
ifeq (yes, ${TEST})
CXXFLAGS := ${CXXFLAGS} -DDESKTOP_TEST
test:
#echo '************ TEST VERSION ************'
else
release:
#echo "************ RELEASE VERSIOIN **********"
endif
It's not clear what you want, or whether you want this trick to work with different targets, or whether you've defined these targets elsewhere, or what version of Make you're using, but what the heck, I'll go out on a limb:
ifeq (yes, ${TEST})
CXXFLAGS := ${CXXFLAGS} -DDESKTOP_TEST
test:
$(info ************ TEST VERSION ************)
else
release:
$(info ************ RELEASE VERSIOIN **********)
endif
$(info your_text) : Information. This doesn't stop the execution.
$(warning your_text) : Warning. This shows the text as a warning.
$(error your_text) : Fatal Error. This will stop the execution.
src: https://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
This is either trivial or runs counter to the philosophy of how make should be used, but I'd like to have a command line that reads as "make debug" rather than "make DEBUG=1". I tried creating a phony target called debug that did nothing except set the DEBUG variable, but then there was a difference between "make debug build" and "make build debug"--namely that in one case, the variable got set after the build happened.
Is there a way to give certain targets precedence?
Thanks for your help.
See 'Target-specific variable values' in this page.
You can also do it by looking at the MAKECMDGOALS variable
ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
DEBUG = 1
endif
build:
#echo build and DEBUG is [$(DEBUG)]
debug:
This is what happens when you call it:
$ make build
build and DEBUG is []
$ make build debug
build and DEBUG is [1]
make: Nothing to be done for `debug'.
$ make debug build
make: Nothing to be done for `debug'.
build and DEBUG is [1]
you can write the following:
.PHONY: debug
debug:
$(MAKE) -$(MAKEFLAGS) build DEBUG=1
build:
echo makeflags='$(MAKEFLAGS)' debug=${DEBUG}
This will at least work with GNU Make, BSD Make and Interix Make. I didn't try all the other implementations.
One thing you can do with GnuMake is use macros that expand to rules with the foreach builtin. Something like:
TARGETS := build all foo bar baz
define DEBUG_TARGET_RULE
$(1).debug:
$$(MAKE) DEBUG=1 $(1)
debug.$(1):
$$(MAKE) DEBUG=1 $(1)
endef
$(foreach target,$(TARGETS),$(eval $(call DEBUG_TARGET_RULE,$(target))))
This will allow you to type make debug.foo or make foo.debug and it will automatically turn into make DEBUG=1 foo, and it works for any target you put in $(TARGETS)
If your debug will only be used with the build target, you might as well make debug call build so you can just type make debug or make build, where make build would be non-debug.
But as for your actual question, I'm not familiar enough with makefiles to answer it.
One approach is to set up the dependencies and build rules in both the build and debug targets, but add the your debugging options to the debug target. A simple example:
Makefile
program: program.c
gcc -o program program.c
debug: program.c
gcc -D DEBUG -o program program.c
Program.c
#include <stdio.h>
int main(void) {
#ifdef DEBUG
printf("DEBUG on!\n");
#endif
printf("in the program\n");
return 0;
}