Cause makefile to error if an environment variable is not set? - makefile

I'd like my makefile to crash if an environment variable is not set. This is what I have so far:
ifneq ($(shell echo $${VIRTUAL_ENV:+True}),True)
$(error Looks like no virtualenv is active)
endif
and it works!
I'm wondering if there's a more elegant way to do this, perhaps with make directly instead of calling $(shell ...).
Thanks for your help!

You can make use of the origin function...
ifeq ($(origin VIRTUAL_ENV),undefined)
$(error Looks like no virtualenv is active)
endif

This could be simplest option, but isn't as fine tuned as using origin.
ifndef VIRTUAL_ENV
$(error Looks like no virtualenv is active)
endif
One caveat here is that you can't distinguish if VIRTUAL_ENV defined in the Makefile or in the environment.
As #KurtisRader pointed out in a comment, this is possible because environment vars are implicitly "imported" into make's namespace https://www.gnu.org/software/make/manual/html_node/Environment.html.

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

Makefile rule causing unnecessary rebuild

I've got a rule that checks if a certain environment variable has been set:
check-env:
ifndef NODE_ENV
$(error NODE_ENV is undefined)
endif
I then have stuff that depend on it (which should fail if NODE_ENV isn't set):
sql/schema.js: sql/schema.sql check-env
...
My issue is that check-env always causes a rebuild, what should I actually be doing to achieve what I want in a reasonably modular way?
Why are you doing this in the recipe of a target? Why not just put it out in the main part of your makefile?
ifndef NODE_ENV
$(error NODE_ENV is undefined)
endif
If you really want to have this done through rules, your best bet (assuming you're using a "new-enough" version of GNU make) is to use order-only prerequisites like this:
check-env:
$(if $(NODE_ENV),,$(error NODE_ENV is undefined))
sql/schema.js: sql/schema.sql | check-env
...
(note the pipe symbol |). See the manual for details.

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

Check for flags in Makefile

How to check for flags in Makefile ? Suppose I run make -a, I need to be able to do certain things, How do I detect if the flag is set inside a Makefile ?
If you're using GNUMake, you can check MAKEFLAGS, like this:
someTarget:
ifneq (,$(findstring a,$(MAKEFLAGS)))
do something
else
do something else
endif

Is it possible to "unset" an environment variable in a Makefile?

I'm using GNU make, and including a 3rd party library in a project that has a build system that goes berserk if CFLAGS is defined in the environment when it is called. I like to have CFLAGS defined in my environment for other reasons. The library's build is being invoked from another makefile, so that I say e.g.:
3rdparty:
$(MAKE) -f Makefile.3rdparty
But I would like to be sure that CFLAGS is unset when I invoke make on the 3rd party Makefile. The nearest thing I can find is to say:
CFLAGS:=
But this still leaves CFLAGS set in the environment, it's just an empty string. Apart
from doing something hideous like saying:
3rdparty:
bash -c "unset CFLAGS; $(MAKE) -f Makefile.3rdparty"
Is there an easy way to "unset" the CFLAGS variable from within my primary makefile, so that it isn't present at all in the environment when the third party library is invoked?
Doesn't the following work for you?
unexport CFLAGS
3rdparty:
$(MAKE) -f Makefile.3rdparty
As of version 3.82 make has an "undefine" directive:
undefine CFLAGS
This can be problematic if you need the variable to be defined for other commands in the recipe and only don't want it defined in the submake. Another solution is to use env - to invoke the submake and explicitly set any environment variables you need set in the submake, eg:
env - PATH="$$PATH" LD_LIBRARY_PATH="$$LD_LIBRARY_PATH" $(MAKE) -f Makefile.3rdparty
To unset an Environment variable in linux.
Use:
export -n MY_ENV_VARIABLE

Resources