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?

sas4740
źródło

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!")
Dacav
źródło
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.

codenaugh
źródło