如何在Makefile中访问make选项

问题描述 投票:0回答:4

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

例如,我想做类似的事情:

Makefile文件:

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

调用:

make $(MAKEFILE_OPTIONS) -C some_dir
makefile
4个回答
2
投票

不幸的是,找到一个真正可移植的(跨GNU make的不同版本)方法是很棘手的。如果您在名称中设置了带有“s”的标志(例如,--warn-undefined-variables),Mark的解决方案会给出误报。

在GNU make 4.0及以上版本中,MAKEFLAGS的布局是明确定义的,您可以使用:

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

能够有力而可靠地判断是否给出了-s。但是,这在4.0之前的GNU make版本中无法可靠地工作。你可以用这个:

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

如果没有给出-s,则扩展为空字符串,如果是,则扩展为非空字符串。我相信这将适用于所有版本的GNU make。


0
投票

你要找的变量是MAKEFLAGS

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

0
投票

不,filter不是那个。使用findstring

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

...

endif

要么

$(if $(findstring s, $(MAKEFLAGS)),...)

0
投票

事实证明,MAKEFLAGS有更多的角落案例,以下功能并不完全涵盖:

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

考虑下面的Makefile,它显示MAKEFLAGS的值,在配方的内部和外部,以及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'

一个角落的情况是,除了多个单字符开关之外,还使用“长”开关(从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并在遇到单词=--后停止处理,同时过滤掉以--开头的开关:

empty :=
space := $(empty) $(empty)
# Define variable " " to avoid warnings with --warn-undefined-variables.
$(space) :=

parseFlags = $\
  $(if $(findstring =,$(firstword $1)),$\
       $(empty),$\
       $(if $(firstword $1),$\
            $(if $(filter-out --%,$(firstword $1)),$\
                 $(subst -,$(empty),$(firstword $1)))$\
            $(if $(filter-out --,$(firstword $1)),$\
                 $(call $0,$(wordlist 2,$(words $1),$1)))))

find_s = $(findstring s,$(call parseFlags,$(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'

我希望上述技术适用于广泛的Make版本,但是有很多极端情况很难说清楚;也许MadScientist(GNU Make maintainer)可以在这方面权衡。

© www.soinside.com 2019 - 2024. All rights reserved.