Forum: PC-Programmierung Namen der Ziele in Make beliebig?


von Dussel (Gast)


Lesenswert?

Moin,

um bei der VHDL-Entwicklung mit GHDL nicht jede Zeile immer wieder 
aufrufen zu müssen, habe ich mich mal ein bisschen mit Make beschäftigt 
und mir eine Makedatei geschrieben.
1
Test.vcd: Testbench
2
  ghdl -r Testbench --vcd="Test.vcd" --stop-time=200ns
3
  
4
Testbench: ../Types.vhdl ALU.vhdl Testbench.vhdl
5
  ghdl -a ../Types.vhdl
6
  ghdl -a ALU.vhdl
7
  ghdl -a Testbench.vhdl
8
  ghdl -e Testbench
Ich weiß, dass das nicht ideal ist, weil ich alle Dateien in einer Regel 
übersetze, aber das ist jetzt nicht die Frage.
Die Frage ist, ob die Namen der Regeln/Ziele, in diesem Fall 'Testbench' 
eine Bedeutung haben, oder ob ich jeden beliebigen nehmen kann. Ich habe 
es ausprobiert und es funktioniert auch mit anderen Namen, aber ist das 
nur hier so oder grundsätzlich?

Beispiele sind immer in der Art
1
prog: foo.o bar.o
2
    $(LD) -o prog foo.o bar.o
3
4
foo.o: foo.c
5
    $(CC) -c foo.c
6
7
bar.o: bar.c
8
    $(CC) -c bar.c
(Von Wikipedia: Make)
Daher dachte ich, dass die Regel so heißen muss, wie die erzeugte Datei.
Haben die Namen der Ziele also etwas mit den Namen der erzeugten Dateien 
zu tun oder sind das nur Bezeichner und man kann sie beliebig nennen?

Da Make wahrscheinlich hauptsächlich von Programmierern benutzt wird, 
stelle ich die Frage hier.

von Noch einer (Gast)


Lesenswert?

Es gibt 2 Arten von Zielen.

In einem normalen Makefile findest du Ziel, die du von aussen aufrufst, 
wie "make all" oder "make dist" oder "make clean". Die kannst du nennen, 
wie du willst.

Und dann gibt es die internen Ziele. Bevor Make das Ziel "prog" 
erstellen kann, muss es zunächst die Ziele "foo.o" und "bar.o" 
erstellen. Nahezu alle dieser internen Ziele musst du genau so nennen, 
wie die Datei. (Make schaut, ob eine Datei dieses Namens bereits 
existiert, und ob sie neuer ist, als die Ziele, von denen diese Datei 
abhängt).

von Clemens L. (c_l)


Lesenswert?

Dussel schrieb:
> Haben die Namen der Ziele also etwas mit den Namen der erzeugten Dateien
> zu tun oder sind das nur Bezeichner und man kann sie beliebig nennen?

Das Ziel einer Regel ist immer ein Dateiname.

Wenn du also folgende Regeln schreibst:
1
all: Testbench prog
2
3
hello:
4
        echo "Hello, world!"
5
6
...
... dann versucht "make hello" , die Datei "hello" zu erstellen, indem 
das echo ausgeführt wird; und "make all" versucht, die Datei "all" zu 
erstellen, indem zuerst die beiden Abhängigkeiten erstellen werden, und 
dann die Kommando-Liste der Regel selbst ausgeführt wird (die Liste ist 
leer).

In beiden Fällen gibt es die Ziel-Datei dann nicht. Wenn du "make hello" 
noch einmal aufrufst, wird die Meldung noch einmal ausgegeben. Wenn du 
"make all" noch einmal aufrufst, werden die drei Abhängigkeiten neu 
erstellt, falls notwendig.

Aber wenn es im aktuellen Verzeichnis Dateien mit den Namen "all" oder 
"hello" gibt (die neuer sind als ihre Abhängigkeiten), dann würde Make 
die Kommandos nicht mehr ausführen. Um dieses Problem zu vermeiden, hat 
GNU Make die Direktive .PHONY, mit der man ein Ziel festlegen kann, das 
keine Datei ist:
https://www.gnu.org/software/make/manual/make.html#Phony-Targets

: Bearbeitet durch User
von Dussel (Gast)


Lesenswert?

Ach, jetzt habe ich es verstanden, glaube ich.
Wenn die Ziele in der Datei beliebig nenne, funktioniert es trotzdem, 
aber es erkennt dann nicht mehr, was aktuell ist.
Ich habe die Datei ein bisschen umgeschrieben:
1
Test.vcd: Testbench
2
  ghdl -r Testbench --vcd="Test.vcd" --stop-time=200ns
3
4
Testbench: Types.o ALU.o Testbench.o
5
  ghdl -e Testbench
6
7
Types.o: ../Types.vhdl
8
  ghdl -a ../Types.vhdl
9
  
10
ALU.o: ALU.vhdl Types.o
11
  ghdl -a ALU.vhdl
12
  
13
Testbench.o: Testbench.vhdl ALU.o
14
  ghdl -a Testbench.vhdl
und testweise (xyz.o statt ALU.o)
1
Test.vcd: Testbench
2
  ghdl -r Testbench --vcd="Test.vcd" --stop-time=200ns
3
4
Testbench: Types.o xyz.o Testbench.o
5
  ghdl -e Testbench
6
7
Types.o: ../Types.vhdl
8
  ghdl -a ../Types.vhdl
9
  
10
xyz.o: ALU.vhdl Types.o
11
  ghdl -a ALU.vhdl
12
  
13
Testbench.o: Testbench.vhdl xyz.o
14
  ghdl -a Testbench.vhdl
Beim ersten wird erkannt, wenn die Dateien noch aktuell sind, und nichts 
mehr ausgeführt, beim zweiten werden bei jedem Aufruf die Anweisungen 
nochmal ausgeführt.
Mich hatte irritiert, dass es in beiden Fällen geklappt hat. Deshalb sah 
es für mich so aus, als seien die Namen egal.
Danke.

von I <3 Makefiles (Gast)


Lesenswert?

Noch einer schrieb:
> Es gibt 2 Arten von Zielen.
>
> In einem normalen Makefile findest du Ziel, die du von aussen aufrufst,
> wie "make all" oder "make dist" oder "make clean". Die kannst du nennen,
> wie du willst.
>
> Und dann gibt es die internen Ziele. Bevor Make das Ziel "prog"
> erstellen kann, muss es zunächst die Ziele "foo.o" und "bar.o"
> erstellen. Nahezu alle dieser internen Ziele musst du genau so nennen,
> wie die Datei. (Make schaut, ob eine Datei dieses Namens bereits
> existiert, und ob sie neuer ist, als die Ziele, von denen diese Datei
> abhängt).

Hier stimmt einiges, aber nicht ganz.

Prinzipiell ist jedes Ziel in make eine Datei, welche es zu erstellen 
gilt.
OB diese Zieldatei (erneut) erstellt werden muss, hängt von den 
Zeitstempel der Zieldatei selbst und deren Abhängigkeiten ab: ist die 
Zieldatei zwar vorhanden jedoch älter als ihre Abhängigkeiten oder 
existiert sie nicht, so werden die dazugehörigen Befehle ausgeführt (das 
WIE).

Ziele wie "clean" welche keiner Datei entsprechen, nennt man phony und 
sollten mit diesem Schlüsselwort ausgezeichnet werden. (bei "clean" 
werden typischerweise *.o Dateien gelöscht, bei "download" o.ä. wird 
eine Binärdatei zum Zielgerät übertragen)

Ziele wie "all", "dist" o.ä. können für mehrere Dateien auf einmal 
stehen; das wird mit Variablen realisiert, deren Werte Listen von 
Dateien sind. (und/oder mit phony)

JEDES der Ziele kann aufgerufen werden.

Nebst den weiter oben aufgeführten namentlicher Nennung jeder einzelnen 
Datei (was in sinnloser Fleißarbeit ausartet) kennt make auch 
raffinierte Wildcards, also Musterorientierte Regeln und zugehörige 
Funktionen zu Manipulation von Zeichenketten (insbes. Pfad- und 
Dateinamenbestandteile).
Die Auflösung solcher Musterorientierten Regeln produzieren make 
-interne Regeln und Ziele, welche zwar nur für die Dauer des gerade 
laufenden make -Programmlaufes existieren, jedoch genauso gültige 
Ziele für einen Aufruf sind.

  -  -  -

Ein kunstgerecht geschriebenes Makefile enthält sehr wenig Redundanz: 
z.B. wird nur eine (ggfs. mehrteilige) Liste von Quelldateien geführt 
und gepflegt (nein, die kann make nicht erraten... ausserdem werden 
durchaus noch welche von Hilfsmittel wie z.B. flex, bison uva. erst 
noch erzeugt, natürlich via weitere make -Regeln... ) die Liste von 
*.o-Dateien entsprechend davon "rausgerechnet", es produziert jedoch 
entsprechen viele interne Regeln sodass make die totale UND 
detaillierte Übersicht ALLER Abhängigkeiten hat.

Hat make diese Übersicht, kann es mittels Kommandozeilenschalter 
"--jobs n " angemessen bis beliebig viele Teilbereiche parallel 
Kompilieren

In Projekte von "ordentlicher" Größe (ab hunderte von Quellcodedateien) 
zeichnen sich kunstgerecht geschriebene Makefiles dadurch aus dass sie 
zwar bei Start "ein wenig Nachdenken" bevor die Kompileraufrufe 
loslegen, dann aber beim Wechsel von "make clean; make all -j 1" 
(default) auf "make clean; make all -j 16" tatsächlich die 
Auslastungsanzeige ALLER CPU-Cores "an die Decke hochjagen" und die 
Buildzeit des Projektes durchaus um 90% verkürzen.
(unsachgemäss, plump geschriebene Makefiles können da entsprechend 
nicht zaubern...)

PS: "Datei" steht im ganzen Text für ein beliebiger Eintrag im 
Dateisystem, also stellvertretend für echte Dateien, (Sym)Links, 
Verzeichnisse, usw.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.