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

woo*_*tok 30 makefile

在以下Makefile定义中:

  1. 什么是$$@在倒数第二行代表什么?
  2. |中间的符号怎么样?
define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
    cp $(DESTDIR)/$(1) $$@
endef
Run Code Online (Sandbox Code Playgroud)

Bet*_*eta 74

(你有变量名的可悲的选择;让我们改变DESTDIRSOURCE_DIR离开DEST_DIR.单独的)

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

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
    cp $(SOURCE_DIR)/foo $(DEST_DIR)/foo
Run Code Online (Sandbox Code Playgroud)

这有效,但冗余很麻烦.迟早你会改变$(DEST_DIR)/foopreq但是忘记在规则中改变它.这条规则很难理解.所以我们输入一个自动变量:

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
    cp $(SOURCE_DIR)/foo $@
Run Code Online (Sandbox Code Playgroud)

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

现在我们要确保$(DEST_DIR)在此规则运行之前存在,但我们不希望它完全是先决条件,因为缺少该目录不足以导致此规则运行.所以我们将它作为仅限订单的先决条件:

$(DEST_DIR)/foo : $(SOURCE_DIR)/foo | $(DEST_DIR)
    cp $(SOURCE_DIR)/foo $@
Run Code Online (Sandbox Code Playgroud)

现在我们想要这样的许多规则,针对不同的目标,而不是以聪明的方式做,我们将使用"罐头配方",一种用于动态创建规则的模板.

# 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
Run Code Online (Sandbox Code Playgroud)

问题在于,当我们评估这个定义时,$@将会扩展,并且由于它还不是规则,它将扩展为空.所以我们将其改为$$@:

# This will work
define KERNEL_RULE
$(SOURCE_DIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(SOURCE_DIR)/$(1) | $(DEST_DIR)
    cp $(SOURCE_DIR)/$(1) $$@
endef
Run Code Online (Sandbox Code Playgroud)

当Make调用此定义时,$$@展开到$@,然后如果/当它运行规则时,$@将扩展为目标的名称.