comando - makefile ubuntu
¿Cuál es el propósito de.PHONY en un makefile? (8)
¿Qué significa .PHONY
en un Makefile? He pasado por this , pero es demasiado complicado.
¿Puede alguien explicármelo en términos simples?
A menudo los uso para decirle al objetivo predeterminado que no dispare.
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
Sin PHONY, make superclean
dispararía clean
, y andsomethingelse
, y catcher superclean
; pero con PHONY, make superclean
no disparará al catcher superclean
.
No tenemos que preocuparnos por decirle que el objetivo clean
es PHONY, porque no es completamente falso. Aunque nunca produce el archivo limpio, tiene comandos para disparar, así que make pensará que es un objetivo final.
Sin embargo, el objetivo superclean
es realmente falso, por lo que make intentará apilarlo con cualquier otra cosa que proporcione deps para el objetivo superclean
, esto incluye otros objetivos superclean
y el objetivo %
.
Tenga en cuenta que no decimos nada en absoluto acerca de andsomethingelse
o de andsomethingelse
como blah
, por lo que claramente van al receptor.
La salida se ve algo como esto:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah
De forma predeterminada, los destinos de Makefile son "objetivos de archivo", se utilizan para crear archivos a partir de otros archivos. Make asume que su objetivo es un archivo, y esto hace que la creación de Makefiles sea relativamente fácil:
foo: bar
create_one_from_the_other foo bar
Sin embargo, a veces desea que su Makefile ejecute comandos que no representan archivos físicos en el sistema de archivos. Buenos ejemplos de esto son los objetivos comunes "limpio" y "todos". Es probable que este no sea el caso, pero es posible que tenga un archivo llamado clean
en su directorio principal. En tal caso, Make se confundirá porque, de forma predeterminada, el objetivo clean
estaría asociado con este archivo y Make solo lo ejecutará cuando el archivo no parezca estar actualizado con respecto a sus dependencias.
Estos objetivos especiales se llaman falsos y puede indicar explícitamente a Make que no están asociados con archivos, por ejemplo:
.PHONY: clean
clean:
rm -rf *.o
Ahora make clean
se ejecutará como se espera, incluso si tiene un archivo llamado clean
.
En términos de Make, un objetivo falso es simplemente un objetivo que siempre está desactualizado, por lo que cada vez que solicite make <phony_target>
, se ejecutará, independientemente del estado del sistema de archivos. Algunos objetivos comunes de make
que suelen ser falsos son: all
, install
, clean
, distclean
, TAGS
, info
, check
.
Es un objetivo de compilación que no es un nombre de archivo.
La mejor explicación es el propio manual GNU make: 4.6 Sección de objetivos falsos .
.PHONY
es uno de los Nombres de objetivos incorporados especiales de make. Hay otros objetivos que le pueden interesar, por lo que vale la pena hojear estas referencias.
Cuando sea el momento de considerar un objetivo .PHONY, make ejecutará su receta incondicionalmente, sin importar si existe un archivo con ese nombre o cuál es su hora de última modificación.
También te pueden interesar los objetivos estándar de make, como all
and clean
.
Supongamos que tiene un destino de install
, que es muy común en makefiles. Si no usa .PHONY
, y existe un archivo llamado install
en el mismo directorio que Makefile, make install
no hará nada . Esto se debe a que Make interpreta la regla para que signifique "ejecutar tal y cual receta para crear el archivo llamado install
". Como el archivo ya está allí y sus dependencias no cambiaron, no se hará nada.
Sin embargo, si hace que el objetivo de la install
PHONY, le dirá a la herramienta make que el objetivo es ficticio y que no debe esperar que cree el archivo real. Por lo tanto, no comprobará si existe el archivo de install
, lo que significa que: a) su comportamiento no se modificará si el archivo existe yb) extra stat()
no se llamará.
En general, todos los destinos en su Makefile que no produzcan un archivo de salida con el mismo nombre que el nombre del objetivo deben ser PHONY. Esto normalmente incluye all
, install
, clean
, distclean
, etc.
También hay un tratamiento delicado importante de ".PHONY": cuando un objetivo físico depende de un objetivo falso que depende de otro objetivo físico:
TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2
Usted simplemente esperaría que si actualizase TARGET2, entonces TARGET1 debería considerarse obsoleto contra TARGET1, por lo que TARGET1 debería reconstruirse. Y realmente funciona de esta manera .
La parte difícil es cuando TARGET2 no está obsoleto contra TARGET1, en cuyo caso debe esperar que TARGET1 no se reconstruya.
Esto sorprendentemente no funciona porque: el objetivo falso se ejecutó de todos modos (como lo hacen normalmente los objetivos falsos) , lo que significa que el objetivo falso se consideró actualizado . Y debido a eso, TARGET1 se considera obsoleto contra el objetivo falso .
Considerar:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
Puedes jugar con esto:
- Primero haz ''preparar'' para preparar los "archivos fuente"
- juega con eso tocando archivos particulares para verlos actualizados
Puede ver que fileall depende de file1 indirectamente a través de un objetivo falso, pero siempre se reconstruye debido a esta dependencia. Si cambia la dependencia en fileall
de filefwd
a file
, ahora fileall
no se reconstruye cada vez, pero solo cuando cualquiera de los objetivos dependientes está obsoleto como archivo.
NOTA : La herramienta de fabricación lee el archivo MAKE y verifica las marcas de tiempo de modificación de los archivos en ambos lados del símbolo '':'' en una regla.
Ejemplo
En un directorio ''prueba'' están presentes los siguientes archivos:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
En makefile una regla se define como sigue:
hello:hello.c
cc hello.c -o hello
Ahora suponga que el archivo ''hola'' es un archivo de texto que contiene algunos datos, que se creó después del archivo ''hola.c''. Por lo tanto, la modificación (o creación) de la marca de tiempo de ''hola'' será más nueva que la de ''hola.c''. Entonces, cuando invocaremos ''make hello'' desde la línea de comando, se imprimirá como:
make: `hello'' is up to date.
Ahora acceda al archivo ''hello.c'' y coloque algunos espacios en blanco en él, lo que no afecta la sintaxis o la lógica del código, y luego guarde y salga. Ahora la modificación de la marca de tiempo de hello.c es más reciente que la de ''hello''. Ahora, si invoca ''make hello'', ejecutará los comandos como:
cc hello.c -o hello
Y el archivo ''hola'' (archivo de texto) se sobrescribirá con un nuevo archivo binario ''hola'' (resultado del comando de compilación anterior).
Si usamos .PHONY en makefile como sigue:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
y luego invoca ''make hello'', ignorará si algún archivo presente en el pwd llamado ''hello'' y ejecutará el comando cada vez.
Ahora suponga que si no hay dependencias de destino en makefile:
hello:
cc hello.c -o hello
y el archivo ''hola'' ya está presente en la ''prueba'' de pwd, entonces ''hola'' siempre se mostrará como:
make: `hello'' is up to date.
.PHONY: install
- significa que la palabra "instalar" no representa un nombre de archivo en este Makefile;
- significa que Makefile no tiene nada que ver con un archivo llamado "instalar" en el mismo directorio.