在makefile宏中定义变量(定义)

在makefile宏中定义变量(定义),makefile,local-variables,Makefile,Local Variables,我正在使用define创建宏。但是,在define构造中,我无法创建变量。分配变量不会导致错误,但当我稍后尝试使用它时,它的值为空 比如说 ####################################################### ## JIDL_RULE ## Macro to build and install PHP and JS files ## from idl.json files ########################################

我正在使用
define
创建宏。但是,在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
但是如果我稍后尝试使用它们(仍然在定义中),比如
$(PHP\u OUT\u文件)
$(JS\u OUT\u文件)
,那么变量是空的。我希望能够从我的宏中删除该重复项。我做错了吗?不可能吗?还有别的办法吗

测试两个答案

我尝试了eriktous和Ise Wisteria的方法,它们都“奏效”。这两种方法都不创建私有变量,只创建全局变量,我对此没有意见,我只需要小心冲突变量,我不能进行任何递归调用(我没有计划这样做)

eriktous方法的问题在于,添加$$会使变量在外部求值,也就是说,$$作为单个$输出,只有在调用目标时才会求值。因此,调用宏两次将覆盖它

Ise Wisteria的方法确实满足了我的需要。调用eval可确保立即声明变量,因此在对宏求值时,该变量可用并由宏展开。这确实意味着我不能在宏中将其设置为两个不同的值,但我也同意

这是我用来测试它的makefile

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

eval
应用于以下作业是否解决了问题

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

希望这有帮助

我已经做了一些试验,我想我现在明白了评估的顺序。
make
如下所示。

Ise紫藤为您的问题提供了一个解决方案,我认为应该有效。另一种方法是在引用变量时简单地添加第二个
$
,如下所示:
$$(PHP\u OUT\u文件)

为什么不能使用更简单的模式规则来实现相同的目标?好吧,这并没有回答这个问题,但我认为你想找到一个解决方案来构建这些东西…:)解释原因要花很长时间,这对回答这个问题没有帮助。我不是在寻求帮助来解决实际问题。只是在define中定义局部变量的一种方法:)@STATUS\u ACCESS\u DENIED:让我试着回答你的问题,也许不是全部;idl.json文件位于多个文件夹中,不会复制到它们所在的同一文件夹中。每次调用宏都必须指定输出目录。请不要问我为什么是这样:)为什么要使用内部:,而不是内部:在这里?这几乎有效。。。如果我只调用宏一次,请参见我编辑以获取解释。我仍然非常感谢您的输入。它确实有效,太棒了,谢谢,请参阅我的编辑以与eriktous的方法进行比较。谢谢,很高兴它有所帮助:-)eriktous的解决方案很有趣。这将有助于在略有不同的情况下。
$(eval PHP_OUT_FILE := $(call GENERATED_FILE,$(1),$(2),php))
$(eval JS_OUT_FILE := $(call GENERATED_FILE,$(1),$(3),js))