2009-10-23 10 views
23

¿Cómo puedo ejecutar un script, que debe ejecutarse antes que todos los demás comandos de archivo MAKE? Y será bueno (pero no obligatorio) que el script no se ejecute si no hay nada que compilar.Paso previo a la compilación en makefile

He buscado SO y Google, pero no encuentro nada.

que tienen esta solución:

# myscript.bat output is empty 
CHEAT_ARGUMENT = (shell myscript.bat) 
CFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT) 
AFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT) 

pero es muy feo. ¿Hay alguna otra manera de ejecutar "pre-build step" en makefile?

+0

"no ejecutar si no hay nada para construir" no es muy importante ahora, pero será bueno. La pregunta ha cambiado – zxcat

+0

¿Qué estás tratando de hacer en última instancia? ¿Qué hace myscript.bat? ¿Realmente estás tratando de calcular algunos indicadores adicionales del compilador, o es un ejemplo artificial? –

+0

Mi script obtiene revisiones y revisiones de SVN, ¿está modificado desde la última confirmación? Pone esta información en otra secuencia de comandos (generar el archivo rev.bat), que simplemente genera esta información sin otra cosa. Más adelante en makefile utilizo REVISION = $ (shell rev.bat) para obtener esta información. Y luego: AXF_FILE = project_r $ (REVISION) _ $ (ARCHITECTURE) .axf – zxcat

Respuesta

22

Propongo dos soluciones. Los primeros imita lo que NetBeans IDE genera:

CC=gcc 

.PHONY: all clean 

all: post-build 

pre-build: 
    @echo PRE 

post-build: main-build 
    @echo POST 

main-build: pre-build 
    @$(MAKE) --no-print-directory target 

target: $(OBJS) 
    $(CC) -o [email protected] $(OBJS) 

clean: 
    rm -f $(OBJS) target 

El segundo se inpired por lo que Eclipse IDE genera:

CC=gcc 

.PHONY: all clean 
.SECONDARY: main-build 

all: pre-build main-build 

pre-build: 
    @echo PRE 

post-build: 
    @echo POST 

main-build: target 

target: $(OBJS) 
    $(CC) -o [email protected] $(OBJS) 
    @$(MAKE) --no-print-directory post-build 

clean: 
    rm -f $(OBJS) target 

Tenga en cuenta que en el primero, antes y después de compilaciones son siempre llamados independientemente de si la construcción principal está determinada para estar actualizada o no.

En el segundo, el paso posterior a la construcción no se ejecuta si el estado de la compilación principal está actualizado. Mientras que el paso de preconstrucción siempre se ejecuta en ambos.

+5

pre-build no tiene que ejecutarse antes de main-build en el segundo ejemplo ya que no existe dependencia entre ellos. Ten cuidado con esto si haces una marca paralela. –

+0

Scott Wales es correcto. He visto dependencias adicionales añadidas desde precompilación a main-build, y desde main-build a post-build, para combatir esto. – mlepage

+0

Creo que tienes razón ... No dudes en sugerir/editar para mejorar el segundo ejemplo. – Amro

9

Dependiendo de la versión make, algo como lo siguiente, al menos, debe evitar decenas de veces en ejecución si CFLAGS y AFLAGS se evalúan decenas de veces:

CHEAT_ARG := $(shell myscript) 

Nota del colon.

Esto funciona exactamente una vez. Nunca más de una vez, pero nunca menos de una vez. Elija sus propias compensaciones.

+0

¿No se ejecutará de todos modos, incluso si no es necesario? La pregunta pide que no se ejecute si no hay nada que construir. –

+0

Oh, claro. Bueno, al menos funciona exactamente una vez y, por lo tanto, nunca se mueve más de una vez, incluso si hay docenas de reglas de make que expanden CFLAGS y AFLAGS. – ndim

+1

ndim, ¡Gracias! Esta respuesta es la mejor manera para mí. – zxcat

3

Lo que estás proponiendo parece un poco "improvisado". ¿Por qué no simplemente ejecutar el comando en el objetivo de cualquier archivo MAKE que necesite antes?

ejemplo, si la necesita para funcionar antes de enlazar foo:

foo: ${OBJS} 
    my-command-goes-here 
    ${CC} -o [email protected] ${OBJS} ${LIBS} 
+1

Gracias por responder. Sí, lo he intentado también. Pero tengo varias reglas $ (CC) y $ (AS) (armasm usa diferentes parámetros para diferentes arquitecturas; el binario es universal y elige el código dependiente de la arquitectura en tiempo de ejecución). Y no es una buena idea agregar "my-command" en muchos lugares. Pero mejor que mi método actual – zxcat

+0

No puedo ejecutarlo antes del enlace, porque necesito sus resultados antes. Y quiero ejecutarlo una vez, no en cada procesamiento de archivos. Antes de cualquier otro archivo de precesión. – zxcat

5

Se podría añadir un objetivo especial a su Makefile y tener todas sus reglas de generación confiar en que:

run-script: 
    myscript 

.o.c: run-script 
    $(CC) $(CFLAGS) -o [email protected] $< 

.o.S: run-script 
    $(AS) $(AFLAGS) -o [email protected] $< 

Dependiendo en lo que realmente hace el script, ponerlo a ejecutar una vez en una etapa antes del Makefile (configure la etapa en términos de autoconf) podría tener aún más sentido (y menos trabajo).

+0

Es casi lo mismo, como sugirió Asveikau. El script se ejecutará antes de cada archivo (varias veces). – zxcat

+0

Y autoconf resultará lo mismo que en su primera respuesta, ¿no es así? – zxcat

+1

Uhm, tienes razón (necesitas más café). Solo si puede expresar algunos make deps adecuados en su secuencia de comandos, puede ahorrar en invocaciones. – ndim

1

Gracias por las respuestas. ndim me ayudó mucho, asveikau. El archivo final es un ejecutable binario, por lo que puede utilizar ahora algo como esto:

run-script: 
    myscript 
$(AXF_FILE): run-script $(OBJ_DIRS) $(OBJ_FILES) 
    $(LINK) #...... 

Se ejecutará una vez miscript. El valor {AXF_FILE} depende de myscript y debo ejecutarlo antes de. Y en este caso, myscript se ejecuta siempre, no solo cuando se necesita reconstruir. Después, la respuesta más simple me vino a la mente:

all: run-script $(AXF_FILE) 

Eso es todo;) (Por supuesto, cualquier objetivo se puede utilizar en lugar de "todos")


Editar: Este script de ejecución de método después de $ (AXF_FILE) se calcula también. Por lo tanto, es posible obtener un valor incorrecto de AXF_FILE. Ahora solo la primera respuesta por ndim funciona como lo necesito.

+0

No creo que esto garantice que run-script ocurra antes de que se hagan los archivos obj. – mlepage

Cuestiones relacionadas