Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does $$@ and the pipe symbol in Makefile stand for?

Tags:

makefile

In the following Makefile definition:

  1. What does the $$@ in the second last line stand for?
  2. What about the | symbol in the middle line?
define KERNEL_RULE $(DESTDIR)/$(1) : kernel_modules $(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)     cp $(DESTDIR)/$(1) $$@ endef 
like image 559
woodstok Avatar asked Sep 06 '12 11:09

woodstok


People also ask

What does pipe symbol mean in makefile?

Order-only prerequisites can be specified by placing a pipe symbol ( | ) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only: targets : normal-prerequisites | order-only-prerequisites.

What means $@ in makefile?

The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.

What does colon mean in makefile?

In the first line, the list of target names is terminated by a colon. This, in turn, is followed by the dependency list, if there is one. If several targets are listed, this indicates that each such target is to be built independently using the rule supplied.

What is dash in makefile?

Hyphen prior to commands in makefiles is used to suppress errors and continue instead of failing like this: clean: -rm -f *.o. The same way goes for include syntax in makefiles to suppress the error messages that would otherwise appear if the file isn't available like this: -include $(SRC:%.c=%.d)


1 Answers

(You have a lamentable choice of variable names; let's change DESTDIR to SOURCE_DIR and leave DEST_DIR alone.)

Suppose you were writing an ordinary rule:

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

That works, but the redundancy is troublesome. Sooner or later you'll change $(DEST_DIR)/foo in the preq but forget to change it in the rule. And the rule is hard to read. So we put in an automatic variable:

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

When this rule runs, $@ will be expanded to the name of the target, $(DEST_DIR)/foo. (We can do even better than that, but let's stop there.)

Now we want to make sure that $(DEST_DIR) exists before this rule runs, but we don't want it to be a prerequisite exactly, because the absence of that directory shouldn't be enough to cause this rule to run. So we make it an order-only prerequisite:

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

Now we want many rules like this, for different targets, and instead of doing it the smart way, we'll use a "canned recipe", sort of a template for creating rules on the fly.

# 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 

The problem is that when we evaluate this definition, $@ will be expanded, and since it isn't a rule yet, it will expand to nothing. So we change it to $$@:

# This will work define KERNEL_RULE $(SOURCE_DIR)/$(1) : kernel_modules $(DEST_DIR)/$(1) : $(SOURCE_DIR)/$(1) | $(DEST_DIR)     cp $(SOURCE_DIR)/$(1) $$@ endef 

When Make calls this definition, $$@ expands to $@, then if/when it runs the rule, $@ will expand to the name of the target.

like image 173
Beta Avatar answered Sep 29 '22 03:09

Beta