How can I print message in Makefile? - makefile

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

Related

Makefile ifndef variable in target

Please believe me: I searched and tested a lot... but I don't get whats wrong here:
VERSION := 123
all:
ifndef VERSION
$(error VERSION not set)
else
$(info Start deploy $(VERSION))
endif
outputs VERSION not set
what I really wanted was to call make like VERSION=1.2.3 make but not even setting the variable in the Makefile worked
What am I missing?
For me it outputs Start deploy 123.
Note that ifndef and $(error) and $(info) are part of makefile syntax, not the recipe syntax belonging to all target. So, your code is equivalent to:
VERSION := 123
ifndef VERSION
$(error VERSION not set)
else
$(info Start deploy $(VERSION))
endif

How to check if a file exists in Makefile

I am using makefile to build my program in multiple system. Some system have installed colorgcc script. In my Makefile i want to check, if script exists
and depending on it i setting up CC variable. But my Makefile don't work correctly - in system, that haven't colorgcc, make always set $(CC) as colorgcc. Here's part of Makefile:
ifneq ("$(wildchar /usr/bin/colorgcc)","")
CC=colorgcc
else
CC=gcc
endif
I also tried to use this variant:
ifeq ( $(shell test -e /usr/bin/colorgcc), )
CC=colorgcc
else
CC=gcc
endif
In both case $(CC) doesn't depend of existence file /usr/bin/colorgcc
How can i solve my problem?
In the first case, you mistyped the function $(wildcard ...) so you get nothing, always.
In the second case, the output of test is always the empty string. It will set its exit code depending on whether the condition is true or not, but you are not examining its exit code, just the output it prints, which will always be nothing at all.

How to use ifeq inside of a define in GNU Make?

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))

Using ifeq and ifndef in GNU Make

I've written a fairly simple test Makefile where I define two targets, all & clean. I've got two different conditional statements. One checks for the existence of the $(MAKECMDGOALS) special variable and the other detects whether any of the command line targets matched those listed in a variable (NODEPS). The problem I'm having is that none of the branches within my conditionals get executed. Ultimately I want to use a conditional to decide whether the target I'm supplying should include some autogenerated dependency files but at the moment I'm struggling to get either expression to even evaluate. I'm running GNU make version 3.81 and I've tried it under Ubuntu and Mac OS X to no avail.
NODEPS := clean
INCLUDE = $(filter $(NODEPS),$(MAKECMDGOALS))
.PHONY : all clean
ifndef $(MAKECMDGOALS)
#echo "$$(MAKECMDGOALS) is not defined"
else
#echo "$(MAKECMDGOALS) is defined"
endif
ifneq (0, $(words $(INCLUDE)))
#echo "INCLUDE = $(INCLUDE) != 0"
else
#echo "INCLUDE = $(INCLUDE) == 0"
endif
all :
#echo "all : $(MAKECMDGOALS)"
clean :
#echo "clean : $(MAKECMDGOALS)"
I eventually managed to work out what was wrong. #eriktous was right, pointing out that I should be using $(info) rather than #echo. More subtly though, part of the problem was that I'd indented the #echos with a tab. It seems that tabs are mandatory for rules but not allowed in conditionals. The other mistake was I'd expanded the $(MAKECMDGOALS) variable in the test condition when it should have been written as just ifndef MAKECMDGOALS.
https://www.gnu.org/software/make/manual/html_node/Make-Control-Functions.html
A makefile is not a shell script. You can not "randomly" place executable statements anywhere you like and expect them to be executed.
There are various ways of communicating with the outside world from within a makefile: $(info ...), $(warning ...), $(error ...) and $(shell #echo ...) (some or all of these may be GNU make extensions).
Ps: you misspelled PHONY.

using makefile targets to set build options

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;
}

Resources