2009-10-23 13 views
23

Come posso eseguire uno script, che deve essere eseguito prima di tutti gli altri comandi makefile? E sarà bello (ma non obbligatorio) per lo script non viene eseguito se non c'è nulla da costruire.Passo pre-compilazione nel makefile

Ho cercato SO e Google, ma non riesco a trovare nulla.

ho questa soluzione alternativa:

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

ma è molto brutto. Esiste un altro modo per eseguire "pre-build step" nel file makefile?

+0

"Non eseguire se non per costruire" non è molto importante ora, ma sarà un bene. La domanda è cambiata. – zxcat

+0

Cosa stai cercando in definitiva di fare? Che cosa fa myscript.bat? Stai davvero solo cercando di calcolare alcuni flag di compilatore aggiuntivi, o è un esempio forzato? –

+0

Il mio script ottiene la revisione SVN e controlla, è modificato dall'ultimo commit. Mette queste informazioni su un altro script (genera un file rev.bat), che fornisce semplicemente queste informazioni senza nient'altro. Più tardi nel makefile uso REVISION = $ (shell rev.bat) per ottenere queste informazioni. E poi: AXF_FILE = project_r $ (REVISIONE) _ $ (architettura) .axf – zxcat

risposta

22

propongo due soluzioni. I primi imita ciò che 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 

Il secondo è ispirate ai lunghi capelli da ciò che 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 

Si noti che nel primo, pre e post generazioni sono sempre chiamati a prescindere dal fatto la build principale è determinata per essere aggiornata o meno.

Nella seconda, la fase di post-build non viene eseguita se lo stato della costruzione principale è aggiornata. Mentre il passo di pre-build è sempre eseguito in entrambi.

+5

pre-build non deve essere eseguito prima di main-build nel secondo esempio in quanto non esiste alcuna dipendenza tra di essi. Fai attenzione a questo se fai un parallelo. –

+0

Scott Wales è corretto. Ho visto aggiunte ulteriori dipendenze da pre-build a main-build, e da main-build a post-build, per combattere questo. – mlepage

+0

Penso che tu abbia ragione ... Sentiti libero di suggerire/apportare modifiche per migliorare il secondo esempio. – Amro

9

A seconda della versione make, qualcosa di simile a quanto segue dovrebbe almeno evitare l'esecuzione di decine di volte se CFLAGS e AFLAGS vengono valutati decine di volte:

CHEAT_ARG := $(shell myscript) 

Nota del colon.

Viene eseguito esattamente una volta. Mai più di una volta, ma anche mai meno di una volta. Scegli i tuoi compromessi.

+0

Non che eseguire in ogni caso, anche se non ha bisogno di? La domanda richiede che non venga eseguita se non c'è niente da costruire. –

+0

Oh giusto. Beh, almeno funziona esattamente una volta e quindi non muove mai più di una volta, anche se ci sono dozzine di regole per far crescere CFLAGS e AFLAGS. – ndim

+1

ndim, grazie! Questa risposta è il modo migliore per me. – zxcat

3

Quello che stai proponendo sembra un po '"non-simile". Perché non eseguire semplicemente il comando in qualunque target makefile di cui hai bisogno prima?

esempio, se è necessario per eseguire prima di collegare foo:

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

Grazie per la risposta. Sì, ho provato anche questo. Ma ho diverse regole $ (CC) e $ (AS) (l'armasm usa parametri diversi per architetture diverse - il binario è universale e sceglie il codice dipendente dall'architettura in fase di esecuzione). E non è una buona idea aggiungere "my-command" in molti posti. Ma meglio del mio attuale metodo – zxcat

+0

Non riesco a eseguirlo prima del collegamento, perché ho bisogno dei risultati precedenti. E voglio eseguirlo una volta, non su ogni elaborazione di file. Prima di qualsiasi altro precessione di file. – zxcat

5

Si potrebbe aggiungere un obiettivo speciale al vostro Makefile ed avere tutte le regole di compilazione dipendere da quello:

run-script: 
    myscript 

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

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

seconda su ciò che effettivamente fa lo script, metterlo in esecuzione una volta in una fase precedente al Makefile (configurare la fase in termini di autoconf) potrebbe avere ancora più senso (e avere meno lavoro).

+0

È quasi la stessa cosa suggerita da asveikau. Lo script verrà eseguito prima di ogni file (più volte). – zxcat

+0

E autoconf avrà lo stesso risultato della tua prima risposta, vero? – zxcat

+1

Uhm, hai ragione (hai bisogno di più caffè). Solo se riesci ad esprimere alcuni deps appropriati sul tuo script, puoi salvare le invocazioni. – ndim

1

Grazie per le risposte. ndim mi ha aiutato molto, asveikau. Il file finale è un eseguibile binario, in modo da poter usare ora qualcosa di simile:

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

Verrà eseguito myscript volta. Il valore di {AXF_FILE} dipende da myscript e devo eseguirlo prima del. E in questo caso myscript gira sempre, non solo quando è necessaria la ricostruzione. Dopo, la risposta più semplice è venuto in mente:

all: run-script $(AXF_FILE) 

Ecco tutto;) (Naturalmente, qualsiasi obiettivo può essere usato al posto di "tutti")


Modifica: questo metodo esegue lo script dopo $ (AXF_FILE) viene calcolato anche. Quindi è possibile ottenere il valore sbagliato di AXF_FILE. Ora solo la prima risposta di ndim funziona come ho bisogno.

+0

Non penso che questo garantisca che lo script di esecuzione si verifichi prima che vengano creati i file obj. – mlepage