在以下Makefile定义中:
$$@
代表什么?|
符号怎么样?define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
cp $(DESTDIR)/$(1) $$@
endef
答案 0 :(得分:69)
(你有一个可悲的变量名称选择;让我们将DESTDIR
更改为SOURCE_DIR
并单独留下DEST_DIR
。)
假设您正在编写一条普通规则:
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
cp $(SOURCE_DIR)/foo $(DEST_DIR)/foo
这有效,但冗余很麻烦。迟早你会在preq中更改$(DEST_DIR)/foo
但忘记在规则中更改它。这条规则很难理解。所以我们输入automatic variable:
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
cp $(SOURCE_DIR)/foo $@
此规则运行后,$@
将扩展为目标名称$(DEST_DIR)/foo
。 (我们可以做得更好,但让我们停在那里。)
现在我们要确保在此规则运行之前存在$(DEST_DIR)
,但我们并非希望它完全是先决条件,因为缺少该目录不应该足以导致此规则运行。所以我们将其设为order-only prerequisite:
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo | $(DEST_DIR)
cp $(SOURCE_DIR)/foo $@
现在我们想要这样的许多规则,针对不同的目标,而不是the smart way,我们将使用"canned recipe",一种模板来动态创建规则。
# This won't work
define KERNEL_RULE
$(SOURCE_DIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(SOURCE_DIR)/$(1) | $(DEST_DIR)
cp $(SOURCE_DIR)/$(1) $@
endef
问题在于,当我们评估此定义时,$@
将被扩展,并且由于它还不是规则,它将扩展为空。所以我们将其更改为$$@
:
# This will work
define KERNEL_RULE
$(SOURCE_DIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(SOURCE_DIR)/$(1) | $(DEST_DIR)
cp $(SOURCE_DIR)/$(1) $$@
endef
当Make调用此定义时,$$@
会扩展为$@
,然后如果/当它运行规则时,$@
将扩展为目标名称。