在以下 Makefile 定义中:
$$@
倒数第二行中的 代表什么?|
中间线的符号呢?
define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
cp $(DESTDIR)/$(1) $$@
endef
在以下 Makefile 定义中:
$$@
倒数第二行中的 代表什么?|
中间线的符号呢?define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
cp $(DESTDIR)/$(1) $$@
endef
(您有一个可悲的变量名选择;让我们更改DESTDIR
为SOURCE_DIR
并DEST_DIR
不管。)
假设您正在编写一个普通规则:
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
cp $(SOURCE_DIR)/foo $(DEST_DIR)/foo
这行得通,但是冗余很麻烦。迟早你会改变$(DEST_DIR)/foo
preq 但忘记在规则中改变它。而且规则很难阅读。所以我们放入一个自动变量:
$(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 调用此定义时,$$@
扩展为$@
,然后如果/当它运行规则时,$@
将扩展为目标的名称。