2016-05-06 1 views
0

Angenommen, wir haben zwei Verzeichnisse foo und bar. Wo foo Dateien enthält Beispiel.S, run.c, exec.S und bar enthält Beispiel.S wenn ich foo und bar als Abhängigkeiten übergeben. Ich möchte nur example.S im Verzeichnis bar kompilieren von example.S im Verzeichnis fooIgnorieren von Datei mit ähnlichen Namen aus dem Kompilieren in Makefile

DEP ignorieren: = foo bar

DIR: = $ (foreach $ dirs, $ (DEP) , $ (shell $ (HOME) -find -type d-name $ (dirs))),

würde mir den absoluten Pfad der foo und bar-Verzeichnisse zur Verfügung stellen.

FILES: = $ (foreach-Datei, $ (DIR), $ (Platzhalter $ (file)/*)), würde mir die Liste der Dateien foo und bar als

foo/example. S foo/run.c foo/exec.S bar/example.S

Ich möchte auf mehrere Vorkommen von Datei mit dem gleichen Namen prüfen. und kompiliere nur die neuesten, d. h., anstelle von foo/example.S Ich möchte gerne bar/example.S ...

Ich habe keine Ahnung, wie es geht, wie ich bin sehr neu bei der Erstellung von Makefile.

Antwort

0

Dies ist eigentlich eher eine Shell-Frage als ein Makefile. Sie möchten einen Shell-Befehl erstellen, der für jede Datei zwei Spaltenlisten generiert - die erste Spalte ist der vollständige Dateiname und die zweite Spalte ist nur der Dateiname. Dann sortieren Sie sie und entfernen Sie die mit doppelten Dateinamen und geben Sie dann nur die erste Spalte aus.

Grundsätzlich verwenden Sie:

DIRS = ./A ./B 
files=`find $(DIRS) -type f -exec sh -c 'echo {} $$(basename {})' \; | sort -u --stable -k2,2 | awk '{print $$1}'` 

Sie würden die ./B ./A mit einer sortierten Liste von Verzeichnissen zu ersetzen haben Sie durchsuchen wollten Beachten Sie die $$ ‚s - Make löst diese $ vor dem Laufen. Shell-Befehl. Die $(DIRS) hat nur eine einzige $, so dass es erweitert wird, bevor der Befehl ausgeführt wird.

Erläuterung:

find ./B ./A -type f -exec sh -c 'echo {} $(basename {})' \;: Dies sucht die Verzeichnisse B und dann A (in dieser Reihenfolge)

type -f Dateien gibt nur - es Verzeichnisse nicht zurückkehren wird.

-exec sh -c 'echo {} $(basename {})' \;: Für jede gefundene Datei wird der Befehl echo ausgeführt, wobei {} in die gefundene Datei aufgelöst wird. Es wird daher den vollständigen Dateipfad gefolgt von nur dem Dateinamen gedruckt.

: Sortieren Sie die Liste der Dateien basierend auf Spalte 2 (der Dateiname). Die -u bedeutet eindeutig, wenn also passende Dateien vorhanden sind, wird nur die erste Datei gedruckt. Die --stable bedeutet, dass bei zwei übereinstimmenden Zeilen immer die erste ausgegeben wird.

awk '{print $1}': Drucken Sie die erste Spalte der Ausgabe (der vollständige Pfadname).

Sie dann eine Liste der eindeutigen Dateinamen haben, einschließlich ihren Verzeichnisse in $(files)

+0

Danke für die Lösung, wenn ich „$ (Dateien echo)“ ich Liste der Dateien erhalten tun .. Aber –

+0

Vielen Dank für die Lösung, wenn ich "echo $ (Dateien)" Ich bekomme eine Liste von Dateien .. Aber, OBJ_SRC: = $ (info $ (Dateien)) gibt die folgenden 'find /../../foo/example.S /../../foo/run.c/../../foo/exec.S/S./../../bar/example.S -type f -exec sh -c 'echo { } $ (Basisname {}) '\; | sort -u --stable -k2,2 | awk '{print $ 1}' 'Aber ich brauche nur die Dateinamen mit diesem Befehl. –

0

a Es ist (relativ) einfache Art und Weise zu bekommen, was Sie wollen, mit reversing a list beginnen (mit dank @simona). Nachdem Sie DIR Weg berechnet haben,

reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) 

DIR := $(call reverse,$(DIR)) 

Dann VPATH verwenden:

VPATH = $(DIR) 

Jetzt können Sie sagen suchen Stellen für eine Datei (wie example.S), und es wird die letzte Instanz finden (in diesem Fall .../bar/example.S):

example: example.S 
    @echo building [email protected] from $^ 
Verwandte Themen