it-swarm.dev

¿Cómo forzar un makefile para reconstruir un objetivo?

Tengo un makefile que genera y luego llama a otro makefile. Dado que este makefile 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 makefile 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: Nombres eliminados para 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
143
Lodle

Puede declarar que uno o más de sus objetivos es falso .

Un objetivo falso es uno que no es realmente el nombre de un archivo; más bien, es solo un nombre para que se ejecute una receta cuando realiza 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 falso no debe ser un requisito previo de un archivo de destino real; Si es así, su receta se ejecutará cada vez que make vaya a actualizar ese archivo. Siempre que un objetivo falso nunca sea un requisito previo de un objetivo real, la receta del objetivo falso se ejecutará solo cuando el objetivo falso sea un objetivo específico

25
Dave

El interruptor -B para crear, cuya forma larga es --always-make, le dice a make que ignore las marcas de tiempo y haga los objetivos especificados. Esto puede anular el propósito de usar make, pero puede ser lo que necesite.

600
sykora

Un truco que solía estar documentado en un manual de Sun para make es usar un objetivo (no existente) '.FORCE'. Puedes hacer esto creando un archivo, force.mk, que contenga:

.FORCE:
$(FORCE_DEPS): .FORCE

Luego, asumiendo 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, cualquier cosa que dependa de él estará desactualizada y reconstruida.

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

También vale la pena considerar por qué make considera que el lanzamiento está actualizado. 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 ...

15
Jonathan Leffler

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

Dicho todo esto, probablemente deberías definir algunas variables en la parte superior de tu makefile para los diversos nombres de archivo, y definir reglas de make real que tengan secciones de entrada y salida para que puedas usar los beneficios de make, es decir, que solo compilarás ¡Cosas que hay que hacer!

Edición: ejemplo añadido. Sin probar, pero así es como lo haces .PHONY

.PHONY: clean    
clean:
    $(clean)
13
easel

Esta técnica simple permitirá que el makefile funcione normalmente cuando no se desea forzar. Crea un nuevo objetivo llamado force al final de tu makefile . El force target tocará un archivo del que depende su target predeterminado. En el siguiente ejemplo, he agregado toque myprogram.cpp . También agregué una llamada recursiva a make . Esto hará que el objetivo predeterminado se realice cada vez que escriba make force .

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

force:
       touch yourProgram.cpp
       make
4
groko

Si recuerdo correctamente, 'make' usa 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 'tocar'. Puede intentar invocar 'toque' en su makefile para actualizar la marca de tiempo de uno de los objetivos (quizás uno de esos sub-makefiles), lo que podría forzar a Make a ejecutar ese comando.

4
poundifdef

Probé esto y funcionó para mí.

agrega estas lineas 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 compilar todo de nuevo.

¿Que pasó?

1) 'nuevas' llamadas limpias. 'clean' do 'rm' que elimina todos los archivos de objeto que tienen la extensión '.o'.

2) 'nuevas' llamadas 'make'. 'make' ve que no hay archivos '.o', por lo que crea todos los '.o' de nuevo. entonces el vinculador vincula todo el archivo .o int una salida ejecutable

Buena suerte

3
hamaney

Si no necesita conservar ninguna de las salidas que ya compiló con éxito

nmake /A 

reconstruye todo

1
CZahrobsky

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

Por supuesto, con GNU es complicado evitarlo. Y aunque son conscientes de este problema, es su forma documentada de hacer las cosas.

OTOH, makepp se creó como una solución para este problema. Puede escribir sus makefiles en un nivel por directorio, sin embargo, todos se agrupan en una vista completa de su proyecto.

Pero los archivos make legados se escriben recursivamente. Así que hay una solución alternativa en la que $(MAKE) no hace nada más que canalizar las subrequisiciones al proceso de makepp principal. 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 makefiles, pero si están escritos de forma sencilla, las reconstrucciones necesarias de makepp deberían suceder automáticamente, sin la necesidad de ningún truco sugerido por otros.

1
Daniel

make clean borra todos los archivos de objetos ya compilados.

0
Hanan Shteingart
0
abernier

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

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

La marca de tiempo del archivo de origen es lo que make utiliza para "saber" que un archivo ha cambiado y debe volver a compilarse

Por ejemplo: si el proyecto era un proyecto c ++, entonces ejecute touch *.cpp, luego ejecute make otra vez, y haga que vuelva a compilar todo el proyecto.

0
mrflash818

En realidad, depende de cuál es el objetivo. Si es 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 alguna razón (un ejemplo es cuando usa la macro de preprocesamiento __TIME__), debe usar el esquema de FUERZA descrito en las respuestas aquí.

0
Kostas