gpt4 book ai didi

makefile - 如果变量未设置,如何中止 makefile?

转载 作者:行者123 更新时间:2023-12-03 04:26:14 30 4
gpt4 key购买 nike

如何根据 makefile 的变量未设置/赋值来中止 make/makefile 执行?

我想出了这个,但只有在调用者没有显式运行目标时才有效(即仅运行 make)。

ifeq ($(MY_FLAG),)
abort: ## This MUST be the first target :( ugly
@echo Variable MY_FLAG not set && false
endif

all:
@echo MY_FLAG=$(MY_FLAG)

我认为这样的东西是个好主意,但在 make 的手册中没有找到任何内容:

ifndef MY_FLAG
.ABORT
endif

最佳答案

TL;DR:使用error function :

ifndef MY_FLAG
$(error MY_FLAG is not set)
endif

请注意,行不得缩进。更准确地说,这些行之前不能有任何制表符。

<小时/>

通用解决方案

如果您要测试许多变量,则值得为此定义一个辅助函数:

# Check that given variables are set and all have non-empty values,
# die with an error otherwise.
#
# Params:
# 1. Variable name(s) to test.
# 2. (optional) Error message to print.
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))))

使用方法如下:

$(call check_defined, MY_FLAG)

$(call check_defined, OUT_DIR, build directory)
$(call check_defined, BIN_DIR, where to put binary artifacts)
$(call check_defined, \
LIB_INCLUDE_DIR \
LIB_SOURCE_DIR, \
library path)


这将输出如下错误:

Makefile:17: *** Undefined OUT_DIR (build directory).  Stop.

注释:

真正的检查在这里完成:

$(if $(value $1),,$(error ...))

这反射(reflect)了 ifndef 条件的行为,因此定义为空值的变量也被视为“未定义”。但这仅适用于简单变量和显式为空的递归变量:

# ifndef and check_defined consider these UNDEFINED:
explicitly_empty =
simple_empty := $(explicitly_empty)

# ifndef and check_defined consider it OK (defined):
recursive_empty = $(explicitly_empty)

正如 @VictorSergienko 在评论中所建议的,可能需要稍微不同的行为:

$(if $(value $1) tests if the value is non-empty. It's sometimes OK if the variable is defined with an empty value. I'd use $(if $(filter undefined,$(origin $1)) ...

还有:

Moreover, if it's a directory and it must exist when the check is run, I'd use $(if $(wildcard $1)). But would be another function.

针对特定目标的检查

还可以扩展该解决方案,以便仅在调用某个目标时才需要变量。

$(call check_define, ...) 从配方内部

只需将支票移至配方中即可:

foo :
@:$(call check_defined, BAR, baz value)

前导的@符号关闭命令回显,:是实际的命令,一个shell no-op stub .

显示目标名称

check_define 函数可以改进为还输出目标名称(通过 $@ 变量提供):

check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))$(if $(value @), \
required by target `$@')))

因此,现在失败的检查会产生格式良好的输出:

Makefile:7: *** Undefined BAR (baz value) required by target `foo'.  Stop.

check-defined-MY_FLAG 特殊目标

我个人会使用上面简单直接的解决方案。但是,例如this answer建议使用特殊目标来执行实际检查。人们可以尝试概括这一点并将目标定义为隐式模式规则:

# Check that a variable specified through the stem is defined and has
# a non-empty value, die with an error otherwise.
#
# %: The name of the variable to test.
#
check-defined-% : __check_defined_FORCE
@:$(call check_defined, $*, target-specific)

# Since pattern rules can't be listed as prerequisites of .PHONY,
# we use the old-school and hackish FORCE workaround.
# You could go without this, but otherwise a check can be missed
# in case a file named like `check-defined-...` exists in the root
# directory, e.g. left by an accidental `make -t` invocation.
.PHONY : __check_defined_FORCE
__check_defined_FORCE :

用法:

foo :|check-defined-BAR

请注意,check-defined-BAR 列为 order-only (|...) 先决条件。

优点:

  • (可以说)更简洁的语法

缺点:

我相信,使用一些 eval 可以克服这些限制。魔法和secondary expansion黑客,虽然我不确定这是否值得。

关于makefile - 如果变量未设置,如何中止 makefile?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10858261/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com