¿Cómo fuerza un archivo MAKE para reconstruir un objective

Tengo un archivo MAKE que construye 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.

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

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

 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: nombres eliminados para proteger a los inocentes

Edición: Versión fija final:

 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 

Podrías declarar que uno o más de tus objectives son falsos .

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

Un objective falso no debe ser un requisito previo de un archivo de destino real; si lo es, su receta se ejecutará cada vez que make vaya a actualizar ese archivo. Siempre que un objective falso nunca sea un requisito previo para un objective real, la receta del objective falso se ejecutará solo cuando el objective falso sea un objective específico.

El cambio de -B a hacer, cuya forma larga es – --always-make , le dice a make ignorar las marcas de tiempo y hacer los objectives especificados. Esto puede frustrar el propósito de usar make, pero puede ser lo que necesita.

Un truco que solía documentarse en un manual de Sun para make es utilizar un objective (no existente) ‘.FORCE’. Puede hacer esto creando un archivo, force.mk, que contenga:

 .FORCE: $(FORCE_DEPS): .FORCE 

Luego, suponiendo que su archivo make existente se llama makefile , podría ejecutar:

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

Como .FORCE no existe, todo lo que dependa de él estará desactualizado y reconstruido.

Todo esto funcionará con cualquier versión de make ; en Linux, tiene GNU Make y, por lo tanto, puede usar el objective .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 de 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 …

Alguien más sugirió .PHONY, que definitivamente es 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 objective de output: input formulario output: input ¡debe usar .PHONY para TODOS ellos!

Dicho todo esto, probablemente debas definir algunas variables en la parte superior de tu archivo MAKE para los distintos nombres de archivo, y definir reglas de creación real que tengan tanto secciones de entrada como de salida para que puedas usar los beneficios de make, es decir, que solo comstacks cosas que son necesarias para copmile!

Editar: ejemplo agregado. No probado, pero así es como lo haces .PHONY

 .PHONY: clean clean: $(clean) 

Si recuerdo correctamente, ‘make’ usa marcas de tiempo (tiempo de modificación del archivo) para determinar si un objective 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 objectives (tal vez uno de esos sub-makefiles), lo que podría obligar a Make a ejecutar ese comando.

Esta técnica simple permitirá que el archivo MAKE funcione normalmente cuando no se desea forzarlo. Crea un nuevo objective llamado force al final de tu archivo MAKE . El objective de la fuerza tocará un archivo del que depende su objective predeterminado. En el siguiente ejemplo, he agregado touch myprogram.cpp . También agregué una llamada recursiva para hacer . Esto hará que el objective predeterminado se haga cada vez que se escribe fuerza .

 yourProgram: yourProgram.cpp g++ -o yourProgram yourProgram.cpp force: touch yourProgram.cpp make 

make clean borra todos los archivos de objetos ya comstackdos.

Intenté esto y funcionó para mí

agregue estas líneas a Makefile

 clean: rm *.o output new: clean $(MAKE) #use variable $(MAKE) instead of make to get recursive make calls 

guardar y ahora llamar

 make new 

y volverá a comstackr todo

¿Que pasó?

‘nuevas’ llamadas limpias ‘limpias’ do ‘rm’ que elimina todos los archivos de objetos que tienen la extensión de ‘.o’ ‘nuevas’ llamadas ‘make’. ‘make’ ve que no hay archivos ‘.o’, por lo que sigue y crea todo el ‘.o’ de nuevo. entonces el enlazador vincula todo el archivo .o int una ejecución ejecutable

Buena suerte

¡Según Recursive Miller Make Considered Harmful , 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, es engorroso evitarlo. Y a pesar de que son conscientes de este problema, es su forma documentada de hacer las cosas.

OTOH, makepp fue 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. Así que hay una solución alternativa en la que $(MAKE) no hace más que canalizar las subpeticiones de vuelta al proceso principal de makepp. Solo si haces cosas redundantes o, lo que es peor, contradictorias entre tus submake, 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.

Si no necesita conservar ninguno de los resultados que ya compiló satisfactoriamente

 nmake /A 

reconstruye todo

De hecho, depende de lo que sea el objective. Si es un objective falso (es decir, el objective NO está relacionado con un archivo) debe declararlo como .PHONY.

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

Ya se mencionó, pero pensé que podría agregar al uso del touch

Si touch todos los archivos fuente que se comstackrán, el comando touch cambia las marcas de tiempo de un archivo a la hora del sistema en que se ejecutó el comando touch .

El timstamp del archivo fuente es lo que make usos “sepan” que un archivo ha cambiado, y necesita ser comstackdo nuevamente

Por ejemplo: si el proyecto era un proyecto de C ++, entonces touch *.cpp , luego ejecute make nuevamente, y make debería recomstackr todo el proyecto.

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 objective. Cuando el archivo debe regenerarse cada vez, se requiere tanto la FUERZA de dependencia falsa en el archivo como .PHONY para la dependencia falsa.

incorrecto:

 date > $@ 

derecho:

 FORCE date > $@ FORCE: .PHONY: FORCE