0

I want to detect if "-s" is set in the Makefile command line. Is there a variable that captures make options that I can test?

For example, I want to do something like:

Makefile:

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

Invocation:

make $(MAKEFILE_OPTIONS) -C some_dir
4

4 回答 4

2

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

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

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

稳健可靠地判断是否-s给出。然而,这在 GNU make 4.0 之前的版本中不能可靠地工作。你可以使用这个:

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

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

于 2013-10-22T19:34:28.010 回答
0

您要查找的变量是MAKEFLAGS.

ifeq ($(filter s, $(MAKEFLAGS)),s)
# do something
endif
于 2013-10-22T15:20:25.820 回答
0

不,filter不是那个。使用findstring

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

...

endif

或者

$(if $(findstring s, $(MAKEFLAGS)),...)
于 2013-10-22T17:28:12.937 回答
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)'

这可以正确检测 flag 的缺失或存在,无论是否有-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使用“长”开关(以 开头)调用 when 。--这些单字符开关将MAKEFLAGS在 Make 3.81 中组合成一个单词:

$ 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)) 表达式无法-s使用 Make 3.81 进行检测。

这可以通过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 维护者)可以在这方面进行权衡。

于 2018-09-01T20:27:14.753 回答