Определение переменных в макросе make-файла (определение) - PullRequest
8 голосов
/ 22 апреля 2011

Я использую define для создания макроса. Тем не менее, в рамках определенной конструкции я не могу создать переменную. Присвоение переменной не приводит к ошибке, но когда я пытаюсь использовать ее чуть позже, ее значение становится пустым.

Например

#######################################################
## JIDL_RULE
## Macro to build and install PHP and JS files 
## from idl.json files
#######################################################
## param $(1) Full path to idl.json file
## param $(2) Path to directory to copy PHP file into (relative to where make is run from)
## param $(3) Path to directory to copy JS file into (relative to where make is run from)
##########################################################
define JIDL_RULE
# Create the output directory if it doesn't exist
$(2):
    mkdir -p $(2)

$(3):
    mkdir -p $(3)

# Rule to generate a PHP file. Notice that we have to prepend `pwd`
$(call GENERATED_FILE,$(1),$(2),php): $(1)
    $(PHPHOME)/bin/php -f $(JIDL2PHP) -- `pwd`/$$< $(DATADEF_HOME) > $$@

# Rule to generate a JS file
$(call GENERATED_FILE,$(1),$(3),js): $(1)
    $(PHPHOME)/bin/php -f $(JIDL2JS) -- `pwd`/$$< $(DATADEF_HOME) > $$@

# Add those generated files to the all target
all:: $(call GENERATED_FILE,$(1),$(2),php) $(call GENERATED_FILE,$(1),$(3),js) $(2) $(3)

# Remove generated files on clean:
clean::
    -$(RM) -f $(call GENERATED_FILE,$(1),$(2),php) $(call GENERATED_FILE,$(1),$(3),js)

# Rules to install generated files
$(call PHP_RULE, $(call GENERATED_FILE,$(1),$(2),php))
$(call JS_RULE, $(call GENERATED_FILE,$(1),$(3),js))
endef

Вы можете видеть из кода выше, что я дублирую строки

$(call GENERATED_FILE,$(1),$(2),php) и $(call GENERATED_FILE,$(1),$(3),js) из нескольких мест. Поэтому я попытался создать две переменные в качестве первых двух операторов в макросе, например:

PHP_OUT_FILE := $(call GENERATED_FILE,$(1),$(2),php)
JS_OUT_FILE := $(call GENERATED_FILE,$(1),$(3),js)

Но если я попытаюсь использовать их позже (все еще в пределах определения), например $(PHP_OUT_FILE) или $(JS_OUT_FILE), переменные будут пустыми. Я хотел бы иметь возможность удалить это дублирование из моего макроса. Я делаю это неправильно? Разве это не возможно? Есть ли другой способ сделать это?

ИСПЫТАНИЕ ОБА ОТВЕТОВ

Я попробовал подход Эриктуса и Исе Глицинии, и они оба "сработали". Ни один из них не создает приватные переменные, только глобальные переменные, с которыми у меня все в порядке, мне просто нужно быть осторожным с конфликтующими переменными, и я не могу совершать рекурсивные вызовы (которые я не планировал).

Проблема с подходом eriktous заключается в том, что добавление $$ делает его таким образом, что переменная оценивается снаружи, то есть $$ выводится как один $ и вычисляется только при вызове target. Поэтому повторный вызов макроса переопределит его.

Подход Исе Глицинии делает то, что мне нужно. Вызов eval гарантирует, что переменная будет объявлена ​​немедленно, и, следовательно, она доступна и расширяется макросом во время удаления макроса. Это означает, что я не могу установить для него два разных значения в макросе, но я тоже согласен с этим.

Вот make-файл, который я использовал для проверки

define TEST
$(eval INNERVAR := Blah $(1))
inner::
    echo Using EVAL: INNERVAR = $(INNERVAR)
    echo 

endef

define TEST2
INNERVAR2 := Blah $(1)
inner::
    echo Using  double dollar sign: INNERVAR2 = $$(INNERVAR2)
    echo 
endef

$(eval $(call TEST,TEST_1_A))
$(eval $(call TEST,TEST_1_B))
$(eval $(call TEST2,TEST_2_A))
$(eval $(call TEST2,TEST_2_B))

inner::
    echo is that var really private? $(INNERVAR) 
    echo is that var really private? $(INNERVAR2) 

А вот и вывод: я пропустил повторение команды make, которая должна быть выполнена, чтобы ее было легче увидеть.

Using EVAL: INNERVAR = Blah TEST_1_A

Using EVAL: INNERVAR = Blah TEST_1_B

# Calling the macro twice overwrites the global variable and since
# it's not expanded immediately, calling the macro with different params
# will output the last value that we set the variable to
Using double dollar sign: INNERVAR2 = Blah TEST_2_B
Using double dollar sign: INNERVAR2 = Blah TEST_2_B

# As expected, the variables are not private to the macro.
is that var really private? Blah TEST_1_B
is that var really private? Blah TEST_2_B

Ответы [ 2 ]

13 голосов
/ 22 апреля 2011

Решает ли проблема применение eval к назначению, подобному следующему?

$(eval PHP_OUT_FILE := $(call GENERATED_FILE,$(1),$(2),php))
$(eval JS_OUT_FILE := $(call GENERATED_FILE,$(1),$(3),js))

Надеюсь, это поможет

5 голосов
/ 22 апреля 2011

Я немного экспериментировал с этим, и теперь я понимаю, что порядок оценки make следует.
Исе Глициния предложила одно решение вашей проблемы, которое, я думаю, должно сработать. Другой способ - просто добавить секунду $ при обращении к переменным, например: $$(PHP_OUT_FILE).

...