Makefile führt ein anderes Ziel aus

122

Ich habe ein Makefile wie folgt strukturiert:

all : 
    compile executable

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

Ich stellte fest, dass ich in meinem Terminal ständig "make clean" gefolgt von "clear" ausführte, bevor ich "make all" ausführte. Ich möchte ein sauberes Terminal haben, bevor ich versuche, böse C ++ - Kompilierungsfehler zu sichten. Also habe ich versucht, ein drittes Ziel hinzuzufügen:

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

Dies funktioniert, jedoch wird eine zweite Instanz von make ausgeführt (glaube ich). Gibt es einen richtigen Weg, um die gleiche Funktionalität zu erhalten, ohne eine zweite Instanz von make auszuführen?

sas4740
quelle

Antworten:

171

Eigentlich haben Sie recht: Es wird eine weitere Instanz von make ausgeführt. Eine mögliche Lösung wäre:

.PHONY : clearscr fresh clean all

all :
    compile executable

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

fresh : clean clearscr all

clearscr:
    clear

Wenn make freshSie anrufen, erhalten Sie zuerst das cleanZiel, dann das, clearscreenwas ausgeführt wird clearund schließlich das, allwas den Job erledigt.

BEARBEITEN 4. August

Was passiert bei parallelen Builds mit der -jOption make ? Es gibt eine Möglichkeit, die Bestellung zu korrigieren. Aus dem Herstellungshandbuch, Abschnitt 4.2:

Gelegentlich kommt es jedoch vor, dass Sie den aufzurufenden Regeln eine bestimmte Reihenfolge auferlegen möchten, ohne dass das Ziel aktualisiert werden muss, wenn eine dieser Regeln ausgeführt wird. In diesem Fall möchten Sie nur Auftragsvoraussetzungen definieren. Nur-Auftrags-Voraussetzungen können angegeben werden, indem ein Pipe-Symbol (|) in die Liste der Voraussetzungen eingefügt wird: Alle Voraussetzungen links vom Pipe-Symbol sind normal. Alle Voraussetzungen auf der rechten Seite sind nur auf Bestellung: Ziele: Normalvoraussetzungen | Nur-Bestellung-Voraussetzungen

Der Abschnitt mit den normalen Voraussetzungen kann natürlich leer sein. Sie können auch weiterhin mehrere Voraussetzungszeilen für dasselbe Ziel deklarieren: Sie werden entsprechend angehängt. Beachten Sie, dass, wenn Sie dieselbe Datei sowohl als normale als auch als reine Bestellvoraussetzung deklarieren, die normale Voraussetzung Vorrang hat (da sie eine strikte Obermenge des Verhaltens einer reinen Bestellvoraussetzung darstellt).

Daher wird das Makefile

.PHONY : clearscr fresh clean all

all :
    compile executable

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

fresh : | clean clearscr all

clearscr:
    clear

EDIT 5. Dezember

Es ist keine große Sache, mehr als eine Makefile-Instanz auszuführen, da jeder Befehl innerhalb der Aufgabe sowieso eine Unter-Shell ist. Aber Sie können wiederverwendbare Methoden haben die Verwendung von Anruffunktion .

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
quelle
6
@ sas4740: Grundsätzlich wird alles, was folgt, .PHONY : als ein Schlüsselwort behandelt, das immer ausgeführt wird, während nicht gefälschte Ziele Dateien sein sollen.
Dacav
sind "Nur-Bestell-Voraussetzungen" bedingt? für Ziel t2 möchte ich zuerst t0 tun, als nur, wenn t0 erfolgreich t1 ausführen, und nur, wenn beide erfolgreich eine Aufgabe in t3
ausführen
1
@ Fantastory, nein, ich denke sie sind unabhängig. t2wird davon abhängen t0, t1und t3. Wenn Sie diese benötigen , sollten Sie stellen je t3nach Bedarf durch t2, je t1nach Bedarf nach t3und t0nach Bedarf durch t1. Dies bedeutet 3 verschiedene Regeln. Sie sollten dies jedoch überprüfen. Ich bin nicht 100% sicher.
Dacav
3
"Nur-Bestellung-Voraussetzungen" sind unabhängig
fantastisch
2
Ich sehe nicht, wo die Garantie ist, dass "sauber" vor "allen" funktioniert? Die Tatsache, dass Sie sie richtig aus | setzen lässt sie nicht in der richtigen Reihenfolge ausführen. Nur-Auftragsabhängigkeit bedeutet, dass das Ziel nach einem solchen Vorgang nicht unbedingt aktualisiert werden muss. Es hat nichts mit der Reihenfolge der abhängigen Elemente zu tun ... oder?
CygnusX1
6

Wenn Sie die make allLinie von Ihrem "frischen" Ziel entfernt haben:

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

Sie können einfach den Befehl make fresh allausführen, der als ausgeführt wird make fresh; make all.

Einige mögen dies als eine zweite Instanz von make betrachten, aber es ist sicherlich keine Unterinstanz von make (ein make innerhalb eines make), was Ihr Versuch zu ergeben schien.

Codenaugh
quelle