2009-05-03 13 views
114

Tengo un archivo MAKE que crea y luego llama a otro archivo MAKE. Como este archivo make llama a más makefiles que hacen el trabajo, realmente no cambia. Por lo tanto, sigue pensando que el proyecto está construido y actualizado.Cómo fuerza un archivo MAKE a reconstruir un objetivo

dnetdev11 ~ # make 
make: `release' is up to date. 

¿Cómo fuerzo el archivo MAKE para reconstruir el objetivo?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean 


build = svn up ~/xxx              \ 
     $(clean)                \ 
     ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace  \ 
     $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)     \ 


release: 
     $(build) 

debug: 
     $(build DEBUG=1) 

clean: 
     $(clean) 

install: 
     cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin 
     cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib 

Nota: Los nombres a fin de proteger a los inocentes

Edición: Versión final fija:

clean = $(MAKE) -f xxx_compile.workspace.mak clean; 


build = svn up;           \ 
     $(clean)          \ 
     ./cbp2mak/cbp2mak -C . xxx_compile.workspace; \ 
     $(MAKE) -f xxx_compile.workspace.mak $(1); \ 


.PHONY: release debug clean install 

release: 
     $(call build,) 

debug: 
     $(call build,DEBUG=1) 

clean: 
     $(clean) 

install: 
     cp ./source/xxx_utillity/release/xxx_util /usr/bin 
     cp ./dlls/Release/xxxcore.so /usr/lib 

Respuesta

30

Se puede declarar una o más de sus objetivos para ser phony.

Un objetivo falso es aquel que no es realmente el nombre de un archivo; más bien, es solo el nombre de una receta que se ejecutará cuando realice una solicitud explícita . Hay dos razones para usar un objetivo falso: evitar un conflicto con un archivo del mismo nombre y mejorar el rendimiento.

...

Un objetivo falsa no debe ser un requisito previo de un archivo de destino real; si es , su receta se ejecutará cada vez que haga va a actualizar ese archivo . Mientras un objetivo falso no es un requisito previo de un objetivo real , la receta objetivo falsa sólo se ejecutará cuando el falso objetivo es un objetivo determinado,

+41

Esta respuesta, si bien es "aceptada" y altamente "votada" es realmente fuera de lugar. Primero, dice "declarar que los objetivos son falsos", pero luego dice "el objetivo falso no es realmente el nombre de un archivo".Bueno, si su objetivo es un archivo, eso es una contradicción en la respuesta. En segundo lugar, dice que "el objetivo falso no debería ser un requisito previo de un real" - bueno, ¿y si es? La pregunta original, no especificó si lo es o no. La respuesta correcta es _no_ declarar que _sus_ objetivos son falsos, sino declarar un objetivo falso adicional y, a continuación, depender de los objetivos que desee reconstruir. –

4

Si no recuerdo mal, 'hacer' utiliza marcas de tiempo (hora de modificación del archivo) para determinar si un objetivo está actualizado o no. Una forma común de forzar una reconstrucción es actualizar esa marca de tiempo, usando el comando 'toque'. Podría intentar invocar 'toque' en su archivo MAKE para actualizar la marca de tiempo de uno de los objetivos (tal vez uno de esos sub-makefiles), lo que podría obligar a Make a ejecutar ese comando.

12

Alguien más sugirió .PHONY que es definitivamente correcto. .PHONY se debe usar para cualquier regla para la que una comparación de fecha entre la entrada y la salida no sea válida. Como no tiene ningún objetivo del formulario output: input, debe usar .PHONY para TODOS ellos.

Dicho todo esto, probablemente deba definir algunas variables en la parte superior de su archivo MAKE para los distintos nombres de archivo, y definir reglas reales que tengan secciones de entrada y salida para que pueda usar los beneficios de make, es decir, que ' ¡Solo compilaré las cosas que son necesarias para copmile!

Editar: ejemplo agregado. No probado, pero esta es la forma de hacer .PHONY

.PHONY: clean  
clean: 
    $(clean) 
+0

Bueno, si pudiera mostrarme un ejemplo, estaría bien. Estoy tratando de hacer que la represa funcione: P – Lodle

+1

La ubicación del objetivo '.PHONY' no importa. Puede estar en cualquier parte del 'Makefile'. –

+0

Se cambió "antes de" a "para". Buen punto = p – easel

433

El interruptor para hacer -B, cuya forma larga es --always-make, dice make hacer caso omiso de las marcas de tiempo y hacer que los objetivos especificados. Esto puede frustrar el propósito de usar make, pero puede ser lo que necesita.

+67

Esta debería ser la respuesta aceptada ... –

+3

@MarkKCowan Estoy completamente de acuerdo! Esta opción es exactamente lo que estaba buscando, no un truco alternativo como Dave sugiere. –

+4

La advertencia con este enfoque es que solo crea demasiadas cosas. Específicamente con autotools, lo vi volver a ejecutar configure ... ¡¡¡Ojalá se pueda construir una solución basada en LD_PRELOAD !! – vrdhn

14

Un truco que solía documentarse en un manual de Sun para make es utilizar un objetivo (no existente) '.FORCE'. Puedes hacer esto creando un archivo, fuerza.mk, que contiene:

.FORCE: 
$(FORCE_DEPS): .FORCE 

Entonces, suponiendo que el archivo MAKE existente se llama makefile, podría ejecutar:

make FORCE_DEPS=release -f force.mk -f makefile release 

Desde .FORCE no existe, todo lo que depende de él estará fuera de fecha y reconstruido.

Todo esto funcionará con cualquier versión de make; en Linux, tiene GNU Make y, por lo tanto, puede usar el objetivo .PHONY como se explicó.

También vale la pena considerar por qué make considera que la versión está actualizada. Esto podría deberse a que tiene un comando touch release entre los comandos ejecutados; podría ser porque hay un archivo o directorio llamado 'release' que existe y no tiene dependencias, por lo que está actualizado. Luego está la razón real ...

0

Depende en realidad de lo que es el objetivo. Si se trata de un objetivo falso (es decir, el objetivo NO está relacionado con un archivo), debe declararlo como .PHONY.

Sin embargo, si el objetivo no es un objetivo falso pero solo quiere reconstruirlo por algún motivo (un ejemplo es cuando usa la macro de preprocesamiento __TIME__), debe usar el esquema FORCE descrito aquí en las respuestas.

1

Según Miller Recursive Make Considered Harmful se debe evitar llamar $(MAKE)! En el caso que muestre, es inofensivo, porque esto no es realmente un archivo MAKE, solo un script de contenedor, que bien podría haber sido escrito en Shell. Pero dices que continúas así a niveles de recursión más profundos, por lo que probablemente hayas encontrado los problemas que se muestran en ese ensayo revelador.

Por supuesto, con GNU hace que sea difícil de evitar. Y a pesar de que son conscientes de este problema, es su forma documentada de hacer las cosas.

OTOH, makepp se ha creado como una solución para este problema. Puede escribir sus archivos MAKE por nivel de directorio, pero todos se unen para obtener una vista completa de su proyecto.

Pero los archivos make heredados se escriben recursivamente. De modo que hay una solución alternativa en la que $(MAKE) no hace más que canalizar las subpeticiones al proceso principal de makepp. Solo si haces cosas redundantes o, lo que es peor, contradictorias entre tus submakes, debes solicitar --traditional-recursive-make (lo que por supuesto rompe esta ventaja de makepp). No conozco tus otros archivos makefiles, pero si están escritos de manera clara, con makepp las reconstrucciones necesarias deberían suceder automáticamente, sin la necesidad de ningún truco sugerido aquí por otros.

+0

No contestó la pregunta: tangente al punto principal y debería ser un comentario, no una respuesta. – flungo

+0

Quizás no fui lo suficientemente claro. Con [makepp] (http://makepp.sourceforge.net/) no se necesita este archivo MAKE completo. Al conocer las dependencias exactas (todas, no solo las enumeradas después de ':') siempre se reconstruirán cuando sea necesario. – Daniel

-1

En mi sistema Linux (Centos 6.2), hay una diferencia significativa entre declarar el destino .PHONY y crear una dependencia falsa en FORCE, cuando la regla realmente crea un archivo que coincide con el objetivo. Cuando el archivo debe regenerarse cada vez, se requiere la FUERZA de dependencia falsa en el archivo y .PHONY para la dependencia falsa.

equivocada:

date > [email protected] 

derecha:

FORCE 
    date > [email protected] 
FORCE: 
    .PHONY: FORCE 
3

Esta sencilla técnica permitirá que el makefile para funcionar normalmente cuando no se desea forzar. Cree un nuevo objetivo llamado force al final de su makefile. El objetivo force tocará un archivo del que depende su destino predeterminado. En el siguiente ejemplo, he agregado touch myprogram.cpp. También agregué una llamada recursiva al make. Esto hará que el objetivo predeterminado se haga cada vez que escriba for force.

yourProgram: yourProgram.cpp 
     g++ -o yourProgram yourProgram.cpp 

force: 
     touch yourProgram.cpp 
     make 
0

Ya se ha mencionado, pero pensé que podría añadir a la utilización de touch

Si usted touch todos los archivos de código fuente para ser compilado, el comando touch cambia las marcas de tiempo de un archivo a la hora del sistema del touch comando fue ejecutado.

El archivo de origen timstamp es lo make utiliza a "saber" que un archivo ha cambiado, y tiene que ser re-compilado

Por ejemplo: Si el proyecto fue un proyecto de C++, entonces touch *.cpp, a continuación, ejecutar make de nuevo, y make debería recompilar todo el proyecto.

2

yo probamos este y funcionó para mí

añadir estas líneas al fichero Makefile

clean: 
    rm *.o output 

new: clean 
    $(MAKE)  #use variable $(MAKE) instead of make to get recursive make calls 

parada de ahora llamar

make new 

y va a volver a compilar todo de nuevo

Lo sucedió?

'nuevas' llamadas limpias 'clean' do 'rm' que elimina todos los archivos de objetos que tienen la extensión '.o' 'nuevas' llamadas 'make'. 'make' ve que no hay archivos '.o', por lo que sigue y crea todo el '.o' de nuevo. a continuación, los enlaces de engarce todos del archivo .o int una salida ejecutable

Buena suerte

+1

En la receta para 'nuevo' mejor uso '$ (MAKE)' que 'make' –

+0

actualizado. Gracias – hamaney

1

Si no necesita conservar cualquiera de las salidas ya compilado correctamente

nmake /A 

reconstruye todo

1

make clean borra todos los archivos de objetos ya compilados.

Cuestiones relacionadas