$$ @和Makefile中的管道符号代表什么?

时间:2012-09-06 11:45:06

标签: makefile

在以下Makefile定义中:

  1. 最后一行的$$@代表什么?
  2. 中间的|符号怎么样?
  3. define KERNEL_RULE
    $(DESTDIR)/$(1) : kernel_modules
    $(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
        cp $(DESTDIR)/$(1) $$@
    endef
    

1 个答案:

答案 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调用此定义时,$$@会扩展为$@,然后如果/当它运行规则时,$@将扩展为目标名称。