primer - ¿Qué significa $$ @ y el símbolo de tubería en Makefile?
makefile wikipedia (1)
(Tiene una opción lamentable de nombres de variables; cambiemos DESTDIR
a SOURCE_DIR
y dejemos DEST_DIR
solo).
Supongamos que estaba escribiendo una regla ordinaria:
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
cp $(SOURCE_DIR)/foo $(DEST_DIR)/foo
Eso funciona, pero la redundancia es problemática. Tarde o temprano cambiará $(DEST_DIR)/foo
en la preq, pero olvide cambiarlo en la regla. Y la regla es difícil de leer. Así que ponemos en una variable automática :
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo
cp $(SOURCE_DIR)/foo $@
Cuando se ejecute esta regla, $@
se expandirá al nombre del objetivo, $(DEST_DIR)/foo
. (Podemos hacerlo incluso mejor que eso, pero vamos a detenernos allí).
Ahora queremos asegurarnos de que $(DEST_DIR)
exista antes de que se ejecute esta regla, pero no queremos que sea un requisito previo exactamente, porque la ausencia de ese directorio no debería ser suficiente para que se ejecute esta regla. Así que lo hacemos un requisito previo de solo pedido :
$(DEST_DIR)/foo : $(SOURCE_DIR)/foo | $(DEST_DIR)
cp $(SOURCE_DIR)/foo $@
Ahora queremos muchas reglas como esta, para diferentes objetivos, y en lugar de hacerlo de forma inteligente , usaremos una "receta enlatada" , una especie de plantilla para crear reglas sobre la marcha.
# 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
El problema es que cuando evaluamos esta definición, $@
se expandirá, y dado que no es una regla todavía, se expandirá a nada. Entonces lo cambiamos a $$@
:
# This will work
define KERNEL_RULE
$(SOURCE_DIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(SOURCE_DIR)/$(1) | $(DEST_DIR)
cp $(SOURCE_DIR)/$(1) $$@
endef
Cuando Make llama a esta definición, $$@
expande a $@
, luego, si / cuando ejecuta la regla, $@
se expandirá al nombre del objetivo.
En la siguiente definición de Makefile:
- ¿Qué significa el
$$@
en la segunda última línea? - ¿Qué pasa con el
|
¿Símbolo en la línea media?
define KERNEL_RULE
$(DESTDIR)/$(1) : kernel_modules
$(DEST_DIR)/$(1) : $(DESTDIR)/$(1) | $(DEST_DIR)
cp $(DESTDIR)/$(1) $$@
endef