Respuestas:
De forma predeterminada, los destinos de Makefile son "destinos de archivo": se utilizan para crear archivos a partir de otros archivos. Make asume que su objetivo es un archivo, y esto hace que escribir 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". Lo más probable es que este no sea el caso, pero es posible que tenga un archivo nombrado clean
en su directorio principal. En tal caso, Make se confundirá porque, de forma predeterminada, el clean
destino se asociaría 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 decirle 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 siempre que lo solicite make <phony_target>
, se ejecutará, independientemente del estado del sistema de archivos. Algunos comunes make
objetivos que a menudo son falsas son: all
, install
, clean
, distclean
, TAGS
, info
, check
.
Supongamos que tiene un install
objetivo, que es muy común en los archivos MAKE. Si no lo usa .PHONY
, y un archivo llamadoinstall
existe en el mismo directorio que el Makefile, entonces make install
no hará nada . Esto se debe a que Make interpreta que la regla significa "ejecutar tal y tal receta para crear el archivo llamadoinstall
". Como el archivo ya está allí y sus dependencias no cambiaron, no se hará nada.
Sin embargo, si haces el install
crea el PHONY de destino, le dirá a la herramienta de creación que el destino es ficticio, y que make no debe esperar que cree el archivo real. Por lo tanto, no verificará si el install
archivo existe, lo que significa: a) su comportamiento no se alterará si el archivo existe yb) extrastat()
no se llamará .
En general, todos los objetivos en su Makefile que no producen un archivo de salida con el mismo nombre que el nombre del objetivo deben ser PHONY. Esto normalmente incluye all
, install
, clean
, distclean
, y así sucesivamente.
.sh
o .bash
para los "programas" que se ejecutan como si tuvieran una función principal y que se reserve agregar una extensión para las bibliotecas que incluya ( source mylib.sh
). De hecho, llegué a esta pregunta SO porque tenía un script en el mismo directorio que llamaba mi Makefileinstall
.PHONY
todo el tiempo ...
.PHONY
versión.
NOTA : La herramienta make lee el archivo make y comprueba las marcas de tiempo de modificación de los archivos a ambos lados del símbolo ':' en una regla.
En un directorio 'prueba' están presentes los siguientes archivos:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
En makefile, una regla se define de la siguiente manera:
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 marca de tiempo de modificación (o creación) de 'hello' será más nueva que la de 'hello.c'. Entonces, cuando invoquemos 'make hello' desde la línea de comandos, se imprimirá como:
make: `hello' is up to date.
Ahora acceda al archivo 'hello.c' y coloque algunos espacios en blanco, lo que no afecta la sintaxis o la lógica del código, luego guarde y salga. Ahora la marca de tiempo de modificación de hello.c es más nueva que la de 'hola'. Ahora si invocas '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 de la siguiente manera:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
y luego invoque 'make hello', ignorará cualquier archivo presente en la 'prueba' de pwd y ejecutará el comando cada vez.
Ahora suponga que ese objetivo 'hola' no tiene dependencias declaradas:
hello:
cc hello.c -o hello
y el archivo 'hello' ya está presente en la 'prueba' de pwd, luego 'make hello' siempre se mostrará como:
make: `hello' is up to date.
make
que todo tenga sentido, ¡todo se trata de los archivos! Gracias por esta respuesta
.PHONY: install
La mejor explicación es el manual de creación de GNU en sí mismo: 4.6 Sección de objetivos falsos .
.PHONY
es uno de los nombres de destino incorporados especiales de la marca . Hay otros objetivos en los que puede estar interesado, por lo que vale la pena hojear estas referencias.
Cuando es hora de considerar un objetivo .PHONY, make ejecutará su receta incondicionalmente, independientemente de si existe un archivo con ese nombre o cuál es su hora de última modificación.
También puede estar interesado en los objetivos estándar de make , como all
y clean
.
También hay un importante truco 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
Simplemente esperaría que si actualizara TARGET2, entonces TARGET1 debería considerarse obsoleto frente a TARGET1, por lo que TARGET1 debería reconstruirse. Y realmente funciona de esta manera .
La parte difícil es cuando TARGET2 no está rancio 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 normalmente lo hacen los objetivos falsos) , lo que significa que el objetivo falso se consideró actualizado . Y debido a eso, TARGET1 se considera rancio 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:
Puede ver que fileall depende del archivo1 indirectamente a través de un objetivo falso, pero siempre se reconstruye debido a esta dependencia. Si cambia la dependencia fileall
de filefwd
a file
, ahora fileall
no se reconstruye cada vez, sino solo cuando cualquiera de los objetivos dependientes está obsoleto como un archivo.
El objetivo especial .PHONY:
permite declarar objetivos falsos, por lo que make
no los verificará como nombres de archivo reales: funcionará todo el tiempo incluso si dichos archivos aún existen.
Puedes poner varios .PHONY:
en tu Makefile
:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
Hay otra forma de declarar objetivos falsos: simplemente ponga '::'
all :: prog1 prog2
...
clean ::
...
distclean ::
...
El '::' tiene un significado especial: los objetivos son falsos y pueden aparecer varias veces:
clean ::
rm file1
...
clean ::
rm file2
Los bloques de comando se llamarán uno tras otro.
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 falsos, make superclean
dispararía clean
, andsomethingelse
y catcher superclean
; pero con PHONY, make superclean
no disparará catcher superclean
.
No tenemos que preocuparnos por decir que el clean
objetivo es FALSIA, porque no es completamente falso. Aunque nunca produce el archivo limpio, tiene comandos para disparar, así que crea que será un objetivo final.
Sin embargo, el superclean
objetivo es realmente falso, por lo que make intentará apilarlo con cualquier otra cosa que proporcione detalles para el superclean
objetivo; esto incluye otros superclean
objetivos y el%
objetivo.
Tenga en cuenta que no decimos nada sobre andsomethingelse
o blah
, por lo que claramente van al receptor.
El resultado se parece a esto:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah