j3d
j3d

Reputation: 9724

How to Check Whether a Variable Used in a Target Defined in an External File Is Set

Here's my msbuild.mk...

# default build configuration
CONFIGURATION = Release

.PHONY: check-env build-app

check-env: ## Check build environment
    [ -v APP_NAME ] && $(error APP_NAME not set)
    [ -v APP_SRCDIR ] && $(error APP_SRCDIR not set)
    [ -v APP_OUTRDIR ] && $(error APP_OUTDIR not set)

build-app: check-env ## Build .NET application
    @msbuild ${APP_SRCDIR}/${APP_NAME}.sln -t:Build \
        -p:BaseIntermediateOutputPath=${APP_OUTDIR}/obj/ \
        -p:OutDir=${APP_OUTDIR}/bin/ \
        -p:Configuration=${CONFIGURATION}

... and here I've included it into my actual Makefile:

include ./msbuild.mk

SRCDIR = src

APP_NAME = MyApp
APP_SRCDIR = ${SRCDIR}/code/${APP_NAME}
APP_OUTDIR = ${OUTDIR}/${APP_NAME}

.DEFAULT_GOAL = build-app

When I try this...

make build-app

... the check-env target in msbuild.mk aborts the script saying the variables are not set (even they are set in the actual Makefile). Furthermore, if I remove the check-env target, the build-app target succeeds as variables APP_NAME, APP_SRCDIR, and APP_OUTDIR seem to be set correctly.

I'm a bit lost... Am I missing something?

Upvotes: 0

Views: 119

Answers (1)

MadScientist
MadScientist

Reputation: 100836

A few things.

First, the -v option to test is not a POSIX standard option; it's a bash extension. Make will always invoke /bin/sh as the shell which may or may not actually be bash, depending on your system. If all you care about is whether the variable has a non-empty value or not you can use [ -n "$VAR" ] instead.

Second, you can't intersperse make functions like $(error ...) with shell operations like test. If you think about it there's no way that can work: make doesn't have a shell interpreter embedded in it, it expands the command, runs a real shell process, and waits for the exit code to know if it worked. How can a condition that is handled by the shell control whether or not a make function like $(error ...) is run or not?

If you want to test shell variables you have to use shell commands to handle the error, something like this:

check-env: ## Check build environment
        [ -n "$$APP_NAME" ] || { echo APP_NAME not set; exit 1; }

If you just want to check for make variables being set, you can do it more straightforwardly using make syntax. Something like:

check-env = $(foreach V,APP_NAME,APP_SOURCEDIR,APP_OUTDIR, \
              $(if $($V),,$(error Variable $V is not set)))

build-app:
        $(check-env)
        ...

Upvotes: 1

Related Questions