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

如果未设置变量,如何中止makefile?,makefile,Makefile,基于makefile的变量未设置/值,如何中止make/makefile执行 我提出了这个方法,但只有在调用方未显式运行目标时(即仅运行makeonly)才有效 我认为这样做是个好主意,但在make的手册中没有找到任何内容: ifndef MY_FLAG .ABORT endif TL;DR:使用: ifndef MY_标志 $(错误:未设置MY_标志) 恩迪夫 请注意,这些行不得缩进。更准确地说,这些行前面不必有制表符 通解 如果您要测试许多变量,那么为其定义一个辅助函数是值得的: #

基于makefile的变量未设置/值,如何中止make/makefile执行

我提出了这个方法,但只有在调用方未显式运行目标时(即仅运行
make
only)才有效

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

ifndef MY_FLAG
.ABORT
endif
TL;DR:使用:

ifndef MY_标志
$(错误:未设置MY_标志)
恩迪夫
请注意,这些行不得缩进。更准确地说,这些行前面不必有制表符


通解 如果您要测试许多变量,那么为其定义一个辅助函数是值得的:

#检查给定变量是否已设置且所有变量均具有非空值,
#否则就会因错误而死。
#
#参数:
#   1. 要测试的变量名。
#   2. (可选)要打印的错误消息。
检查\u已定义=\
美元(带美元)(每小时1美元\
$(调用已定义的检查,$1,$(strip$(值2‘‘‘‘‘)'))
__检查\u已定义=\
$(如果$(值$1)\
$(错误未定义$1$(如果为$2,($2)))
下面是如何使用它:

$(已定义调用检查,我的标记)
$(调用检查\定义,输出\目录,生成目录)
$(调用check_defined,BIN_DIR,二进制工件的放置位置)
$(调用检查已定义\
LIB_INCLUDE_DIR\
LIB_SOURCE_DIR\
图书馆路径)

这将输出如下错误:

Makefile:17:**Undefined OUT\u DIR(构建目录)。停止
笔记: 真正的检查在这里完成:

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

代码> > IFNDEF和CHECKY定义考虑这些未定义的: 显式\u空= 简单\u空:=$(显式\u空) γIFNDEF和CHECKY定义为OK(定义): 递归\u empty=$(显式\u empty) 正如@VictorSergienko在评论中所建议的,可能需要稍微不同的行为:

$(如果$(值$1)
测试值是否为非空。如果变量定义为空值,则有时可以。我会使用
$(如果$(过滤器未定义,$(原点$1))…

以及:

此外,如果它是一个目录,并且在运行检查时它必须存在,我会使用
$(如果$(通配符$1))
,但这是另一个函数

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

$(调用检查定义,…)
从配方内部 只需将支票移动到配方中:

foo:
@:$(调用检查已定义,条形图,baz值)

前导的
@
标志关闭命令回显,
是实际的命令,一个shell

显示目标名称 可以改进
check_defined
函数,以同时输出目标名称(通过
$@
变量提供):

check\u defined=\
美元(带美元)(每小时1美元\
$(调用已定义的检查,$1,$(strip$(值2‘‘‘‘‘)'))
__检查\u已定义=\
$(如果$(值$1)\
$(错误未定义$1$(如果$2,($2))$(如果$(值@)\
目标`$@')所需)
因此,现在失败的检查将生成格式良好的输出:

Makefile:7:**target'foo'所需的未定义条(baz值)。停止。
check-defined-MY_标志
特殊目标 就我个人而言,我会使用上面简单明了的解决方案。但是,例如,建议使用一个特殊的目标来执行实际检查。可以尝试将其概括,并将目标定义为隐式模式规则:

#检查通过阀杆指定的变量是否已定义并具有
#非空值,否则会导致错误。
#
#%:要测试的变量的名称。
#   
检查已定义-%:u检查已定义\u强制
@:$(已定义调用检查,$*,特定于目标)
#由于模式规则不能作为.PHONY的先决条件列出,
#我们使用老派和黑客势力的变通方法。
#你可以不带这个去,否则支票可能会错过
#如果根目录中存在名为“check defined-…”的文件
#目录,例如意外的'make-t'调用留下的。
.伪造:\检查\定义\强制
__检查定义的力:
用法:

foo:|检查定义的条
请注意,
检查定义栏
被列为(
|…
)先决条件

优点:

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

  • 无法指定自定义错误消息
  • 运行
    make-t
    (请参阅)会用大量
    check-defined-…
    文件污染根目录。这是模式规则的一个可悲缺点

我相信,这些限制可以通过使用一些魔法和黑客来克服,尽管我不确定它是否值得。

使用shell函数
测试

foo:
    test $(something)
用法:

$ make foo
test 
Makefile:2: recipe for target 'foo' failed
make: *** [foo] Error 1
$ make foo something=x
test x

对未设置的变量使用shell错误处理(注意双精度
$
):

如果需要自定义错误消息,请将其添加到

$ cat Makefile
hello:
        echo "hello $${name:?please tell me who you are via \$$name}"

$ make hello
echo "hello ${name:?please tell me who you are via \$name}"
/bin/sh: name: please tell me who you are via $name
make: *** [hello] Error 127

$ make hello name=jesus
echo "hello ${name:?please tell me who you are via \$name}"
hello jesus

您可以使用IF来测试:

check:
        @[ "${var}" ] || ( echo ">> var is not set"; exit 1 )
结果:

$ make check
>> var is not set
Makefile:2: recipe for target 'check' failed
make: *** [check] Error 1

为简便起见:

$ cat Makefile
check-%:
        @: $(if $(value $*),,$(error $* is undefined))

bar:| check-foo
        echo "foo is $$foo"
有产出:

$ make bar
Makefile:2: *** foo is undefined. Stop.
$ make bar foo="something"
echo "foo is $$foo"
foo is something

可能重复什么?从未使用过Mac,但我猜它默认安装了另一个Make实现(例如,BSD Make而不是GNU Make)。我建议您首先检查
Make--version
。Make 3.81中似乎不起作用。即使定义了变量(并且可以回显),它也总是会出错.Ah,你需要按照链接副本中的结构进行精确设置。@bibstha我添加了脑海中出现的选项,请阅读更新的答案。我要为noobies(像我一样)添加一个澄清
$ cat Makefile
check-%:
        @: $(if $(value $*),,$(error $* is undefined))

bar:| check-foo
        echo "foo is $$foo"
$ make bar
Makefile:2: *** foo is undefined. Stop.
$ make bar foo="something"
echo "foo is $$foo"
foo is something