makefile:在变量中查找单词的位置

iva*_*van 4 makefile

在我的makefile中,我需要根据命令行变量值进行变量赋值.例如,我这样做:

make var_1=xxx
Run Code Online (Sandbox Code Playgroud)

哪里var_1可以有100个可能值之一.基于值var_1,我需要var_2在我的makefile中分配一个值.我可以:

ifeq ($(var_1), a)
   var_2 = A
endif
ifeq ($(var_1), b)
   var_2 = B
endif
Run Code Online (Sandbox Code Playgroud)

等了所有100个可能的组合var_1,var_2.在这里a,A,b,B代表一些字符串.我该怎么做才能避免100的if陈述?我在考虑定义两个变量:

var_1_values = a b c d     
var_2_values = A B C D
Run Code Online (Sandbox Code Playgroud)

我可以用$(findstring $(var_1),$(var_1_values)),看看是否$(var_1)是中$(var_1_values),但我怎么找到的位置$(var_1)在所有$(var_1_values)?然后该位置用于选择内部的相应单词$(var_2_values).

Bet*_*eta 5

这是一个小小的kludgey,但如果你知道的符号不会出现任何值(例如"_"),你可以这样做:

var_1_values = a b c d
var_2_values = A B C D

# This will be a_A b_B c_C d_D
LIST1 = $(join $(addsuffix _,$(var_1_values)),$(var_2_values))

var_1 := a

# The filter gives a_A, the subst turns it into A
var_2 = $(subst $(var_1)_,,$(filter $(var_1)_%, $(LIST1)))
Run Code Online (Sandbox Code Playgroud)


小智 5

这可以非常巧妙地使用 GNU make 函数中的递归来完成,如下所示:

_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
       $(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))
Run Code Online (Sandbox Code Playgroud)

要使用它,您可以使用带有两个参数$(call)pos函数:要查找的项目和要在其中查找的列表。例如,

$(call pos,a,a b c d e f g)
$(call pos,e,a b c d e f g)
$(call pos,g,a b c d e f g)
$(call pos,h,a b c d e f g)
$(call pos,e,))
Run Code Online (Sandbox Code Playgroud)

它的工作原理是通过$2参数递归,直到它再也找不到 中的值$1。每次递归时,它都会$2使用$(wordlist 2,$(words $2),$2). 每次递归它都会x向返回的字符串添加一个,以便x每个位置都有一个$2直到$1找到的位置。

然后它只是$(words)用来计算从_posxs的数量)返回的长度。

如果您使用 GMSL 项目,则可以更巧妙地将其写为:

_pos = $(if $(findstring $1,$2),$(call $0,$1,$(call rest,$2),x $3),$3)
pos = $(words $(call _$0,$1,$2))
Run Code Online (Sandbox Code Playgroud)

请注意,我$0在这里使用了它将包含当前函数的名称(这是标准的 GNU make 功能)和 GMSL 函数rest以将头部从列表中删除。


小智 5

有一种使用递归的流畅方法,如下所示。首先定义一个被调用的函数pos,该函数在列表中查找元素的位置,然后用于$(word)提取另一个列表中的相应元素。

这是pos

_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
       $(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))
Run Code Online (Sandbox Code Playgroud)

阅读此答案以了解其工作原理:Makefile: find function which returns position

现在很容易定义一个函数,它在一个列表中找到一个元素,然后在另一个列表中找到相应的元素。

lookup = $(word $(call pos,$1,$2),$3)
Run Code Online (Sandbox Code Playgroud)

然后尝试是否像这样:

ALPHA := a b c d e f g h i j k l m n o p q r s t u v w x y z
NATO := alpha beta charlie delta echo foxtrot gamma hotel india\
        juliet kilo lima mike november oscar papa quebec romeo\
        sierra tango uniform victor whisky yankee zulu
to-nato = $(call lookup,$1,$(ALPHA),$(NATO))
Run Code Online (Sandbox Code Playgroud)

制作一个to-nato从字母表字母转换为北约字母表的函数。