如何检查是否设置了在外部文件中定义的目标中使用的变量

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

这是我的 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}

... 在这里,我将其包含在我的实际 Makefile:

include ./msbuild.mk

SRCDIR = src

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

.DEFAULT_GOAL = build-app

当我尝试这个时...

make build-app

... msbuild.mk 中的 check-env 目标中止脚本,表示变量未设置(即使它们在实际 Makefile 中设置)。此外,如果我删除 check-env 目标,build-app 目标会成功,因为变量 APP_NAMEAPP_SRCDIRAPP_OUTDIR 似乎设置正确。

我有点迷茫...我是不是漏掉了什么?

一些事情。

首先,要测试的-v选项不是POSIX标准选项;这是一个 bash 扩展。 Make 将始终调用 /bin/sh 作为 shell,它实际上可能是也可能不是 bash,具体取决于您的系统。如果您只关心变量是否具有非空值,则可以改用 [ -n "$VAR" ]

其次,您不能将 $(error ...) 之类的 make 函数与 test 之类的 shell 操作穿插在一起。如果你考虑一下,没有办法可以工作:make 没有嵌入 shell 解释器,它扩展了命令,运行 是一个真正的 shell 进程,并等待退出代码以了解它是否有效。 shell 处理的条件如何控制像 $(error ...) 这样的 make 函数是否是 运行 还是没有?

如果你想测试 shell 变量你必须使用 shell 命令来处理错误,像这样:

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

如果您只想检查 make 变量被设置,您可以使用 make 语法更直接地完成它。类似于:

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

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