makefile: найти позицию слова в переменной - PullRequest
4 голосов
/ 13 марта 2012

В моем make-файле мне нужно назначить переменную на основе значения переменной командной строки. например, я делаю:

make var_1=xxx

, где var_1 может иметь одно из, скажем, 100 возможных значений. Исходя из значения var_1, мне нужно присвоить значение var_2 в моем make-файле. Я мог бы сделать:

ifeq ($(var_1), a)
   var_2 = A
endif
ifeq ($(var_1), b)
   var_2 = B
endif

и так далее для всех 100 возможных комбинаций var_1, var_2. Здесь a, A, b, B представляют некоторые строки. Как мне сделать это, чтобы избежать сотен из if утверждений? Я думал определить две переменные:

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

Я могу использовать $(findstring $(var_1),$(var_1_values)), чтобы увидеть, находится ли $(var_1) среди $(var_1_values), но как мне найти положение $(var_1) среди всех $(var_1_values)? Затем эта позиция используется для выбора соответствующего слова внутри $(var_2_values).

Ответы [ 5 ]

5 голосов
/ 13 марта 2012

Это немного хитро, но если есть символ, который, как вы знаете, не будет ни в одном из значений (например, "_"), вы можете сделать это:

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)))
4 голосов
/ 13 марта 2012

Один из способов имитировать ассоциативные контейнеры в make - это использовать вычисляемые переменные . E.g.:

var_2.a := A
var_2.b := B
# ...

# lookup
var_2 = ${var_2.${var_1}}
# or, lookup and assign a default value if lookup fails
var_2_or_default = $(or ${var_2.${var_1}},<default-value>)
3 голосов
/ 27 мая 2016

Существует плавный способ сделать это с помощью рекурсии следующим образом.Сначала определите функцию с именем 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))

Прочтите этот ответ, чтобы понять, как он работает: Makefile: функция find, которая возвращает позицию

Теперь легко определить функцию, которая находит элемент в списке и находит соответствующийэлемент в другом списке.

lookup = $(word $(call pos,$1,$2),$3)

А затем попробуйте, если получится так:

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))

Чтобы создать функцию to-nato, которая преобразует буквы алфавита в алфавит НАТО.

3 голосов
/ 27 мая 2016

Это можно сделать довольно гладко, используя рекурсию внутри GNU make, следующим образом:

_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
       $(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))

Чтобы использовать его, вы должны $(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,))

Он работает путем повторения аргумента $2 до тех пор, пока не сможет найти значение в $1. Каждый раз, когда он повторяется, он отрубает голову $2, используя $(wordlist 2,$(words $2),$2). Каждый раз, когда повторяется, он добавляет x к возвращаемой строке, так что есть один x для каждой позиции через $2 до того места, где был найден $1.

Затем он просто использует $(words) для подсчета длины возврата от _pos (количество x с).

Если вы используете проект GMSL, это может быть написано более гладко, напишите это как:

_pos = $(if $(findstring $1,$2),$(call $0,$1,$(call rest,$2),x $3),$3)
pos = $(words $(call _$0,$1,$2))

Обратите внимание, что здесь я использовал $0, который будет содержать имя текущей функции (это стандартная функция GNU make) и функцию GMSL rest, чтобы убрать голову из списка.

1 голос
/ 06 августа 2017
FAB = macrofab
# NOTE: base starts at 1 instead of 0
none := 1
seeed := 1
oshpark := 2
macrofab := 2
pcbng := 3
#NOTE: String must end with a space for word function to work
SUFFIX_DRILLS := "txt xln drl "

.PHONY: gerber

gerber:
    @echo $(FAB) drill suffix is $(word $($(FAB)), $(SUFFIX_DRILLS))

Вывод make: суффикс макрофаб сверла xln

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...