makefile wykonuje inny cel


123

Mam plik makefile o takiej strukturze:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

Zdałem sobie sprawę, że konsekwentnie wykonywałem w terminalu polecenie „make clean”, a następnie „wyczyść”, zanim uruchomiłem polecenie „make all”. Lubię mieć czysty terminal, zanim spróbuję przejrzeć okropne błędy kompilacji C ++. Więc spróbowałem dodać trzeci cel:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

To działa, jednak uruchamia drugą instancję make (wierzę). Czy istnieje właściwy sposób na uzyskanie tej samej funkcjonalności bez uruchamiania drugiej instancji make?

Odpowiedzi:


172

Właściwie masz rację: uruchamia kolejną instancję marki. Możliwym rozwiązaniem byłoby:

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : clean clearscr all

clearscr:
    clear

Dzwoniąc make fresh, otrzymujesz najpierw cleancel, następnie ten, clearscreenktóry działa, cleara na końcu, allktóry wykonuje zadanie.

EDYTUJ 4 sierpnia

Co dzieje się w przypadku równoległych kompilacji z -jopcją marki ? Jest sposób na ustalenie zamówienia. Z instrukcji marki, sekcja 4.2:

Czasami jednak zdarza się sytuacja, w której chcesz narzucić określoną kolejność reguł, które mają być wywoływane, bez wymuszania aktualizacji celu, jeśli jedna z tych reguł zostanie wykonana. W takim przypadku chcesz zdefiniować wymagania wstępne dotyczące tylko zamówienia. Wymagania wstępne dotyczące tylko zamówienia można określić, umieszczając symbol potoku (|) na liście wymagań wstępnych: wszelkie wymagania wstępne po lewej stronie symbolu rury są normalne; wszelkie wymagania wstępne po prawej stronie dotyczą tylko zamówienia: cele: normalne wymagania wstępne | wymagania wstępne dotyczące tylko zamówienia

Normalna sekcja wymagań wstępnych może oczywiście być pusta. Możesz także nadal zadeklarować wiele wierszy wymagań wstępnych dla tego samego celu: są one odpowiednio dołączane. Zwróć uwagę, że jeśli zadeklarujesz ten sam plik jako wymaganie wstępne normalne i wymaganie wstępne tylko dla zamówienia, pierwszeństwo ma normalne wymaganie wstępne (ponieważ są one ścisłym nadzbiorem zachowania warunku wstępnego dotyczącego tylko zamówienia).

Stąd plik makefile staje się

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : | clean clearscr all

clearscr:
    clear

EDYTUJ 5 grudnia

Uruchomienie więcej niż jednej instancji makefile nie jest problemem, ponieważ każde polecenie wewnątrz zadania i tak będzie podpowłoką . Ale możesz mieć metody wielokrotnego użytku, używając funkcji call .

log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)

install:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  command1  # this line will be a subshell
  command2  # this line will be another subshell
  @command3  # Use `@` to hide the command line
  $(call log_error, "It works, yey!")

uninstall:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  ....
  $(call log_error, "Nuked!")

6
@ sas4740: w zasadzie wszystko, co następuje, .PHONY : jest traktowane jako słowo kluczowe, które jest zawsze wykonywane, podczas gdy niefałszowane cele mają być plikami.
— Dacav

czy „Wymagania wstępne dotyczące tylko zamówienia” są warunkowe? dla celu t2 chcę najpierw zrobić t0, niż tylko wtedy, gdy t0 zakończy się sukcesem, uruchomi t1, i tylko jeśli obaj pomyślnie wykonają jakieś zadanie w t3
— fantastyczny

1
@fantastory, nie, myślę, że są niezależne. t2będzie zależeć t0, t1i t3. Jeśli potrzebujesz tego, umieść t3zgodnie z wymaganiami t2, t1zgodnie z wymaganiami t3i t0zgodnie z wymaganiami t1. Oznacza to 3 różne zasady. Powinieneś to jednak zweryfikować. Nie jestem pewien w 100%.
— Dacav,

3
„Wymagania wstępne dotyczące tylko zamówienia” są niezależne
— fantastyczne

2
Nie rozumiem, gdzie jest gwarancja, że ​​„czysty” działa przed „wszystkim”? Fakt, że poprawiłeś je z | nie powoduje ich wykonania w kolejności. Zależność tylko od zamówienia oznacza, że ​​cel nie jest koniecznie aktualizowany po takiej operacji. Nie ma to nic wspólnego z porządkowaniem elementów zależnych… czy?
— CygnusX1

6

Jeśli usunąłeś make allwiersz ze swojego „nowego” celu:

fresh :
    rm -f *.o $(EXEC)
    clear

Możesz po prostu uruchomić polecenie make fresh all, które zostanie wykonane jako make fresh; make all.

Niektórzy mogą uznać to za drugą instancję marki, ale z pewnością nie jest to podrzędna instancja marki (marka wewnątrz marki), do czego wydawała się skutkować twoja próba.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.