2009-10-23 12 views
23

Jak mogę uruchomić skrypt, który musi zostać wykonany przed wszystkimi innymi poleceniami makefile? I będzie to miłe (ale nie obowiązkowe), że skrypt nie zostanie wykonany, jeśli nie ma nic do zbudowania.Krok pre-build makefile

Szukałem SO i Google, ale nie mogę znaleźć niczego.

mam tego rozwiązania:

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

Ale to bardzo brzydkie. Czy istnieje inny sposób uruchomienia "pre-build step" w makefile?

+0

"Nie wykonać, jeśli nic nie budować" nie jest teraz bardzo ważne, ale będzie dobrze. Pytanie się zmieniło. – zxcat

+0

Co ostatecznie zamierzasz zrobić? Do czego służy myscript.bat? Czy naprawdę próbujesz obliczyć dodatkowe flagi kompilatora, czy jest to wymyślny przykład? –

+0

Mój skrypt otrzymuje wersję SVN i sprawdza, czy jest modyfikowany od ostatniego zatwierdzenia. Umieszcza te informacje w innym skrypcie (generuje plik rev.bat), który prosto wyprowadza tę informację bez niczego więcej. Później w makefile używam REVISION = $ (shell rev.bat), aby uzyskać te informacje. A następnie: AXF_FILE = project_r $ (REVISION) _ $ (ARCHITEKTURA) .axf – zxcat

Odpowiedz

22

Proponuję dwa rozwiązania. Pierwsze naśladuje co NetBeans IDE generuje:

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 

Drugi jest inpired przez co Eclipse IDE generuje:

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 

pamiętać, że w pierwszym, przed i po kompilacje są zawsze o nazwie niezależnie od tego, czy główny build jest uważany za aktualny lub nie.

W drugim kroku po kompilacji nie wykonuje się, jeśli stan kompilacji głównej jest aktualny. Podczas gdy etap wstępnej kompilacji jest zawsze wykonywany w obu.

+5

wstępna kompilacja nie musi być uruchamiana przed główną wersją w drugim przykładzie, ponieważ nie ma między nimi zależności. Uważaj na to, jeśli robisz równoległą markę. –

+0

Scott Wales jest poprawny. Widziałem dodatkowe zależności dodane od wstępnej wersji do głównej wersji i od głównej wersji do późniejszej kompilacji, aby walczyć z tym. – mlepage

+0

Myślę, że masz rację ... Możesz zaproponować/wprowadzić zmiany, aby poprawić drugi przykład. – Amro

9

zależności od wersji make, coś jak poniżej powinna przynajmniej unikać używania dziesiątki razy jeśli CFLAGS i AFLAGS oceniane są dziesiątki razy:

CHEAT_ARG := $(shell myscript) 

Uwaga okrężnicy.

To działa dokładnie jeden raz. Nigdy więcej niż raz, ale nigdy nie rzadziej niż raz. Wybierz własne kompromisy.

+0

Czy i tak to nie zadziała, nawet jeśli nie musi? Pytanie prosi o to, aby nie zostało wykonane, jeśli nie ma nic do zbudowania. –

+0

O rację. Cóż, przynajmniej działa dokładnie raz, a zatem nigdy nie przenosi się więcej niż raz, nawet jeśli istnieją dziesiątki reguł tworzenia rozszerzających CFLAGS i AFLAGS. – ndim

+1

ndim, dziękuję! Ta odpowiedź jest dla mnie najlepsza. – zxcat

3

To, co proponujesz, wydaje się nieco "nierealne". Dlaczego po prostu nie uruchomisz komendy w jakimkolwiek celu pliku Makefile, do którego potrzebujesz go wcześniej?

przykład, jeśli jest to potrzebne do uruchomienia przed łącząc foo:

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

Dzięki za odpowiedź. Tak, też tego próbowałem. Ale mam kilka reguł $ (CC) i $ (AS) (armasm używa różnych parametrów dla różnych architektur - plik binarny jest uniwersalny i wybiera kod zależny od architektury w czasie wykonywania). I nie jest dobrym pomysłem dodawanie "my-command" w wielu miejscach. Ale lepiej niż moja obecna metoda – zxcat

+0

Nie mogę uruchomić go przed linkiem, ponieważ potrzebuję jego wyników wcześniej. I chcę uruchomić go raz, a nie przy każdym przetwarzaniu pliku. Przed każdym innym plikiem precessing. – zxcat

5

można dodać specjalny cel swojej Makefile i mieć wszystkie swoje zasady budowania zależą że:

run-script: 
    myscript 

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

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

zależności na tym, co faktycznie robi twój skrypt, umieszczenie go raz na etapie przed Makefile (konfiguracja w kategoriach autoconf) może uczynić jeszcze więcej sensu (i mniej pracy).

+0

To prawie to samo, jak sugerował asveikau. Skrypt zostanie wykonany przed każdym plikiem (kilka razy). – zxcat

+0

Autoconf będzie taki sam jak w pierwszej odpowiedzi, prawda? – zxcat

+1

Uhm, masz rację (potrzebujesz więcej kawy). Tylko jeśli możesz wyrazić pewne poprawne make deps w swoim skrypcie, możesz zaoszczędzić na wywołaniach. – ndim

1

Dziękuję za odpowiedzi. ndim pomógł mi bardzo, asveikau. Ostateczna wykonywalny plik binarny jest jeden, więc mogę teraz używać coś takiego:

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

będzie działać myscript raz. Wartość {AXF_FILE} zależy od myscript i muszę go uruchomić przed. I w tym przypadku myscript działa zawsze, nie tylko wtedy, gdy konieczna jest przebudowa. Po, Najprostsza odpowiedź przyszedł do mojego umysłu:

all: run-script $(AXF_FILE) 

To wszystko;) (Oczywiście, każdy cel może być stosowany zamiast "wszystkie")


Edycja: ta metoda wykonania skryptu po $ (AXF_FILE) jest również obliczana. Tak więc można uzyskać błędną wartość AXF_FILE. Teraz tylko pierwsza odpowiedź ndim działa tak, jak potrzebuję.

+0

Nie sądzę, że to gwarantuje, że run-script występuje przed utworzeniem plików obj. – mlepage