如何访问Makefile中的make选项

如何访问Makefile中的make选项,makefile,Makefile,我想检测Makefile命令行中是否设置了“-s”。是否有一个变量可以捕获我可以测试的选项 例如,我想做如下事情: 生成文件: if ($(MAKE_OPTIONS), -s) #do something endif 调用: make $(MAKEFILE_OPTIONS) -C some_dir 您要查找的变量是MAKEFLAGS ifeq ($(filter s, $(MAKEFLAGS)),s) # do something endif 否,过滤器不是唯一的过滤器。使用fin

我想检测Makefile命令行中是否设置了“-s”。是否有一个变量可以捕获我可以测试的选项

例如,我想做如下事情:

生成文件:

if ($(MAKE_OPTIONS), -s)
    #do something
endif
调用:

make $(MAKEFILE_OPTIONS) -C some_dir

您要查找的变量是
MAKEFLAGS

ifeq ($(filter s, $(MAKEFLAGS)),s)
# do something
endif

否,
过滤器
不是唯一的过滤器。使用
findstring

ifneq ($(findstring s, $(MAKEFLAGS)),)


不幸的是,要找到一种真正可移植(跨GNU make的不同版本)的方法来实现这一点是很困难的。如果您在名称中设置了任何带有“s”的标志(例如,
--警告未定义的变量
),则Mark的解决方案会给出误报

在GNU make 4.0及更高版本中,MAKEFLAGS的布局定义良好,您可以使用:

$(findstring s,$(firstword -$(MAKEFLAGS))
$(findstring s,$(firstword -$(MAKEFLAGS)))$(filter -s,$(MAKEFLAGS))
可靠可靠地判断是否给出了
-s
。然而,这在4.0之前的GNU make版本中无法可靠地工作。您可以使用以下选项:

$(findstring s,$(firstword -$(MAKEFLAGS))
$(findstring s,$(firstword -$(MAKEFLAGS)))$(filter -s,$(MAKEFLAGS))

如果未给出
-s
,则扩展为空字符串;如果未给出,则扩展为非空字符串。我相信这在GNU make的所有版本中都会起作用。

事实证明,
MAKEFLAGS
的情况甚至更多,如下所示 功能不完全包括:

find_s = $(findstring s,$(firstword -$(MAKEFLAGS)))$(filter -s,$(MAKEFLAGS))
考虑下面显示
MAKEFLAGS
值的
Makefile
,两者都是 配方的内部和外部,以及
find_s
功能的结果:

find_s = $(findstring s,$(firstword -$(MAKEFLAGS)))$(filter -s,$(MAKEFLAGS))

$(info Outside a recipe, MAKEFLAGS="$(MAKEFLAGS)")
$(info $(if $(find_s),-s was detected,-s not found))

all:
    @echo 'Inside a recipe, MAKEFLAGS="$(MAKEFLAGS)"'
    @echo '$(if $(find_s),-s was detected,-s not found)'
这将正确检测标志
-s
的缺失或存在,或 没有其他单字符开关,如
-n
,例如:

$ make-3.81
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS=""
-s not found

$ make-4.1
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS=""
-s not found

$ make-3.81 -s
Outside a recipe, MAKEFLAGS="s"
-s was detected
Inside a recipe, MAKEFLAGS="s"
-s was detected

$ make-4.1 -s
Outside a recipe, MAKEFLAGS="s"
-s was detected
Inside a recipe, MAKEFLAGS="s"
-s was detected

$ make-3.81 -s -n
Outside a recipe, MAKEFLAGS="sn"
-s was detected
echo 'Inside a recipe, MAKEFLAGS="sn"'
echo '-s was detected'

$ make-4.1 -s -n
Outside a recipe, MAKEFLAGS="ns"
-s was detected
echo 'Inside a recipe, MAKEFLAGS="ns"'
echo '-s was detected'
一种常见情况是使用“long”开关调用
make
(从
--
)以及多个单字符开关。这些单字 开关将在Make 3.81中的
MAKEFLAGS
中组合在一个单词中:

$ make-3.81 -n -s --warn-undefined-variables
Outside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"
-s not found
echo 'Inside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"'
echo '-s not found'

$ make-4.1 -n -s --warn-undefined-variables
Outside a recipe, MAKEFLAGS="ns --warn-undefined-variables"
-s was detected
echo 'Inside a recipe, MAKEFLAGS="ns --warn-undefined-variables"'
echo '-s was detected'
开关的分组意味着
$(filter-s,$(MAKEFLAGS))
表达式无法使用Make 3.81检测到
-s

可以通过如下更改
find_s
来解决此问题:

find_s = $(findstring s,$(filter-out --%,$(MAKEFLAGS)))
--
开头的开关被过滤掉,然后剩下的内容被删除 扫描所需开关(
s
),产生正确的检测结果:

$ make-3.81 -n -s --warn-undefined-variables
Outside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"
-s was detected
echo 'Inside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"'
echo '-s was detected'
当变量赋值为 在命令行上传递(例如,
make var=value
);在本例中,变量
MAKEFLAGS
将另外包含这些变量赋值。具有 仔细选择的值,两种版本的检测逻辑
find\s
仍然可以 被愚弄,例如:

$ make-3.81 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS="var=fake\ -s"
-s was detected

$ make-4.1 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS=" -- var=fake\ -s"
-s was detected
解决第二个问题的最简单方法是保存
MAKEFLAGS
在另一个变量中,并在配方中使用该变量,因为幸运的是 配方,
MAKEFLAGS
不包含这些变量赋值;否则 下面更复杂的逻辑将解析
MAKEFLAGS
,然后停止处理 过滤掉以开头的开关时遇到单词
=
--
--

此新的
find_s
可在以下所有情况下正确检测
-s

$ make-3.81 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS="var=fake\ -s"
-s not found

$ make-4.1 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS=" -- var=fake\ -s"
-s not found

$ make-3.81 var='fake -s' -ns --warn-undefined-variables
Outside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"
-s was detected
echo 'Inside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn -- var=fake\ -s"'
echo '-s was detected'

$ make-4.1 var='fake -s' -ns --warn-undefined-variables
Outside a recipe, MAKEFLAGS="ns --warn-undefined-variables"
-s was detected
echo 'Inside a recipe, MAKEFLAGS="ns --warn-undefined-variables -- var=fake\ -s"'
echo '-s was detected'
我希望上述技术能在广泛的品牌中发挥作用 版本,但有这么多角落的情况,很难说;也许是疯狂的科学家
(GNU Make maintainer)可以在这方面发挥作用。

哦,天哪,我忘了你可以有这么多选择。谢谢,先生,我可以再来一杯吗!我没有注意到4.0已经发布。我在哪个星球上?谢谢你,保罗!这里还潜伏着其他一些角落案件;有关详细信息,请参阅。
$ make-3.81 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS="var=fake\ -s"
-s not found

$ make-4.1 var='fake -s'
Outside a recipe, MAKEFLAGS=""
-s not found
Inside a recipe, MAKEFLAGS=" -- var=fake\ -s"
-s not found

$ make-3.81 var='fake -s' -ns --warn-undefined-variables
Outside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn"
-s was detected
echo 'Inside a recipe, MAKEFLAGS=" --warn-undefined-variables -sn -- var=fake\ -s"'
echo '-s was detected'

$ make-4.1 var='fake -s' -ns --warn-undefined-variables
Outside a recipe, MAKEFLAGS="ns --warn-undefined-variables"
-s was detected
echo 'Inside a recipe, MAKEFLAGS="ns --warn-undefined-variables -- var=fake\ -s"'
echo '-s was detected'