40

在以下 Makefile 定义中:

  1. $$@倒数第二行中的 代表什么?
  2. |中间线的符号呢?
define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
    cp $(DESTDIR)/$(1) $$@
endef
4

1 回答 1

92

(您有一个可悲的变量名选择;让我们更改DESTDIRSOURCE_DIRDEST_DIR不管。)

假设您正在编写一个普通规则:

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
    cp $(SOURCE_DIR)/foo $(DEST_DIR)/foo

这行得通,但是冗余很麻烦。迟早你会改变$(DEST_DIR)/foopreq 但忘记在规则中改变它。而且规则很难阅读。所以我们放入一个自动变量

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
    cp $(SOURCE_DIR)/foo $@

当此规则运行时,$@将扩展为目标的名称,$(DEST_DIR)/foo. (我们可以做得更好,但让我们停在那里。)

现在我们要确保$(DEST_DIR)在此规则运行之前它存在,但我们不希望它完全成为先决条件,因为该目录的缺失不应足以导致此规则运行。因此,我们将其设为仅限订单的先决条件

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo | $(DEST_DIR)
    cp $(SOURCE_DIR)/foo $@

现在我们想要很多这样的规则,针对不同的目标,而不是聪明的方式,我们将使用“罐头食谱”,一种用于动态创建规则的模板。

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

于 2012-09-06T13:05:41.817 回答