Hallo,
ich versuche seit Tagen das AVR Makefile Beispiel für den NC30 Compiler
von Renesas zu ändern. Dabei fange ich klein an und will nur meine c
files in Objekte wandeln. Zuerst wird das Verzeichnis durchsucht:
1
CSRC := $(wildcard *.c)
Den Asudruck verstehe ich scheinbar flasch:
1
%.o: %.c
2
$(ECHO) compiling $<
Das bedeutet doch, dass für jedes .c file ein .o File erzeugt wird !?
Aber wo müssen die .c Files definiert sein, damit das greift?
Beim NC30 gibt es keine .o sondern .r30 files, deshalb habe ich:
1
all: %.r30
2
3
%.r30: %.a30
4
$(ECHO) assembling $<
5
6
%.a30 : %.c
7
$(ECHO) compiling $<
Bei mir kommt dann nur:
make: *** No rule to make target `%.r30', needed by `all'. Stop.
Was verstehe ich hier falsch?
Danke
Bronko
Ja Danke,
das lese ich schon die ganze Zeit.
Da steht das es eine implizite Rule ist, also eine spezielle Rule für C
Compiler. Funktioniert das nur für .c nach .o, aber nicht für a30?
Nein mit .o geht mein Beispiel auch nicht.
Im Beispiel steht
1
%.o : %.c
2
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Mein Beispiel soll nur das erste Prerequisit ausgeben, ist dass das
Problem?
Ich werd aus dem Manual nicht wirklich schlau, kannst du mir das bitte
etwas näher erklären?
"...the ‘%’ matches any nonempty substring..." welchen Substring?
Danke
Bronko
> Das bedeutet doch, dass für jedes .c file ein .o File erzeugt wird !?> Aber wo müssen die .c Files definiert sein, damit das greift?
Hm,
könnte ein grundlegendes Problem mit dem Verständnis von make sein?!
Du hast ja zum Beispiel in einem makefile ein "Haupttarget":
1
target.elf: file1.o file2.o file3.o file4.o
Hieraus erkennt make dass um "target.elf" zu erzeugen die 4 Object-Files
file1.o .. file4.o benötigt werden. Da diese (noch) nicht existieren
sucht make nach einer Regel um diese zu erzeugen. Make wird dann die
Regel
1
%.o : %.c
finden.
Diese besagt: Um eine Datei mit der Extension .o zu erzeugen muss es
eine gleichnamige Datei mit der Endung .c geben. Ist eine solche .c
Datei vorhanden kann make die Regel anwenden und erzeugt dadurch die
Object-Datei. Nachdem alle notwendigen Object-Files für das
"Haupttarget" auf diese Weise erzeugt wurden wird die
"Haupttarget"-Regel angewandt und die gewünschte Ausgabefile erzeugt...
führt dazu, dass Make lernt, dass es aus einer *.c eine *.a30 erzeugen
kann und wie. Es ist eine Regel, keine Abhängigkeit. Die Regel wird
immer dann eingesetzt, wenn irgendwo (z.B. aufgrund einer weiteren
Regel) ein *.a30 benötigt wird und ein *.c dafür existiert (oder das
passende *.c mithilfe einer anderen Regel erzeugt werden kann, was hier
aber witzlos ist).
Mit
1
all: %.r30
schreibst Du aber, dass das (Pseudo-)Ziel „all“ von genau einer Datei
abhängt, nämlich von der Datei %.r30. Und die will Make denn auch haben
und bekommt sie nicht. Da kein % links vom Doppelpunkt steht, ist das
keine allgemeine Regel, sondern eine konkrete Abhängigkeit eines Ziels
von einer Datei.
Danke für eure Feedback.
@Hc Zimmerer: So habe ich das ja auch verstanden, deshalb habe ich mit
CSRC := $(wildcard *.c)
alle c files dem CSRC zugewiesen. Wenn ich jetzt mein Pseudotarget
weglasse, also nur
1
CSRC := $(wildcard *.c)
2
3
%.r30: %.a30
4
$(ECHO) assembling $<
5
6
%.a30: %.c
7
$(ECHO) ... compiling $<
wird keines der Targets ausgewertet, da er mein clean Target weiter
unten "macht" mit ansschließendem
1
W:\R8Cdemo\*.r30 konnte nicht gefunden werden
Ich stehe granatenmäßig auf dem Schlauch vor lauter Make Manual lesen...
Ich will doch nur das alle C files im aktuellen Verzeichnis automatisch
gefunden werden und alle Objekte (.r30) IMMER neu erstellt werden. (Das
mit den Dependencies habe ich mir schon abgeschminkt)
Huaauaauaaaaaaaaa
Deine Zuweisung an CSRC ist einfach eine Variablenzuweisung. Sie bringt
nichts, solange die Variable nirgends referenziert wird (es gibt einige
Variablen wie CFLAGS, die bereits eine Sonderbedeutung haben, weil sie
in den internen (vordefinierten) Regeln von Make auftauchen, CSRC gehört
nicht dazu).
Würdest Du mit Deinen obigen Schnipseln
1
all: dingens.r30
schreiben, so würde dein Make wissen, wie es diesen aus dingens.c
erstellt, ohne dass dingens.c irgendwo im Makefile auftaucht. Probier's
mal. Aber dingens.c muss dazu existieren.
Allgemein solltest Du von der Batch-basierenden Denke herunterkommen und
Make als eine Art Expertensystem auffassen, das anhand eingebauter und
angelernter Regeln sich die nötigen Schritte zur Erzeugung eines Obejkts
selbst „ausdenkt“. Du musst also nicht die Schritte definieren, sondern
nur die Regeln mitteilen und die Abhängigkeiten.
Ganz aus dem Ärmel kann sich keiner die Handhabung eines solchen Tools
schütteln. Du wirst also nicht umhinkommen, Dich zunächst ein wenig
einzulesen, wenn Du etwas von der Mächtigkeit des Tools profitieren
möchtest. Als Beispiel wäre der Beginn der Info-Dokumentation zu GNU
make zu nennen.
Ja ich werde die Info Seite noch lesen. Ansonsten habe ich denke genug
gelesen, mir fehlt einfach noch die Übung...
Dein Hinweis mit dingens.c bringt mich jetzt weiter...
Ich habe jetzt alle Targets (.r30) in
ALL_R30 := $(patsubst %.c, %.r30, $(CSRC))
gespeichert.
Das Target %.r30
1
all: $(ALL_R30)
2
3
%.r30: %.a30
4
$(ECHO) assembling $@
5
6
%.a30: %.c
7
$(ECHO) compiling $<
wird für beide source files ausgeführt, jedoch nicht das Target %.a30.
Die Ausgabe ist:
assembling crc.r30
assembling errors.r30
Darf man diese Stems (%) evtl. nicht kaskadieren ( .c -> .a30 -> .r30)?
Im AVR Makefile gibt es nur %.o: %.c !?
@Hc Zimmerer: Du schreibst "...ist eine Regel, keine Abhängigkeit...",
wie schaffe ich hier eine Abhängigkeit, sodass für jedes r30 zuerst ein
a30 erzeugt wird? Das bringt mich jetzt etwas ins schleudern, weil ich
dachte das nachdem : sind prerequisits=Abhängigkeiten?
Du darfst Regeln natürlich wie Dargestellt kaskadieren und Make führt
sie dann nacheinander aus.
Wenn allerdings ein .a30 schon existiert und das zugehörige .c nicht
neuer ist, gibt es keinen Grund, das .a30 neu zu erzeugen. Das ist ja
einer der grundlegenden Zwecke eines Makefiles.
Wenn Du also dafür sorgst, dass crc.c neuer ist als crc.a30 (z.B. mit
„touch crc.c“), wird auch der Compile-Schritt ausgeführt.
Hc Zimmerer schrieb:> Wenn allerdings ein .a30 schon existiert und das zugehörige .c nicht> neuer ist, gibt es keinen Grund, das .a30 neu zu erzeugen. Das ist ja> einer der grundlegenden Zwecke eines Makefiles.
leider gibt es kein .a30 bisher :-(
Mit den PHONYS werde ich dafür sorgen das es immer neu erzeugt wird.
Letzter Stand:
1
CSRC := $(wildcard *.c)
2
ALL_A30 := $(patsubst %.c, %.a30, $(CSRC))
3
ALL_R30 := $(patsubst %.c, %.r30, $(CSRC))
4
5
all: $(allR30)
6
$(ECHO) 3
7
8
9
%.r30: %.a30
10
$(ECHO) assembling $@
11
12
%.a30: %.c
13
$(ECHO) compiling $@
Ausgabe:
3
Warum greifen die Regeln nicht??
1
test:
2
$(ECHO) $(ALL_R30) $(CSRC) $(ALL_A30)
bringt:
crc.r30 errors.r30 crc.c errors.c crc.a30 errors.a30
Gibt es überhaupt eine Lösung?
Das macht aus verschiedenen Gründen keinen Sinn. Ich nehme ein
Beispiel:
1
%.a30: %.c
2
$(ECHO) compiling $@
Das ist eine allgemeine Regel, wie ein einzelner *.a30 zu erzeugen ist:
durch Kompilieren des zugehörigen *.c.
1
allA30: $(CSRC)
2
$(ECHO) 1
Das teilt Make mit, dass alles, was in der Variablen $(allA30) steht,
von allem, was in $(CSRC) steht, abhängt -- und mit einem einzigen
Kommando erzeugt wird: $(ECHO) 1. Ab jetzt gibt es keinen Grund mehr,
für irgendeines der beteiligten Files die %.a30: %.c - Regel überhaupt
noch anzuwenden. Kein Wunder also, dass die nirgends mehr aufgerufen
wird.
Analog für Deine anderen Zeilen. Abhängigkeiten hinzuschreiben, die
sich aus den allgemeinen Regeln sowieso ergeben, ist meistens verkehrt.
Wenn Du Dir einen AVR-Makefile anschaust, wirst Du sehen, dass $(SRC)
(die C-Quellen) nirgendwo mit ihrer Originalendung auf der rechten Seite
eines Doppelpunkts auftreten, sondern ausschließlich mit substituierter
Endung (also zum Beispiel als *.o oder *.lst).
OK, weil ich also nur ein ECHO mache braucht er die weiteren
Abhängigkeiten nicht berücksichtigen?
1
all: $(ALL_R30)
2
$(ECHO) 3
3
4
%.r30: %.a30
5
$(ECHO) assembling $@ from $<
6
$(AS) $(AFLAGS) $<
7
8
%.a30: %.c
9
$(ECHO) compiling $@ from $<
10
$(CC) $(INCLUDES) $(CFLAGS) $<
Jetzt tue ich im %.r30 Target mittels $< auf die Erste Abhängigkeit
zugreifen, also müsste das %.a30 Target greifen, weil es noch kein .a30
file gibt! Macht ers aber nicht:
weil es noch kein .a30 gibt...
Zu deinem zweiten Absatz:
Woher kennt dann Make die Abhängigkeiten eines jeden c files? (Um daraus
zu entscheiden ob ein Objekt neu kompiliert werden muß? Oder habe ich
dich missverstanden?
Kannst du mir die Lösung nicht einfach aufschreiben, bitte?
Bronko Pavel schrieb:> Woher kennt dann Make die Abhängigkeiten eines jeden c files? (Um daraus> zu entscheiden ob ein Objekt neu kompiliert werden muß? Oder habe ich> dich missverstanden?
Make baut sich mit Hilfe seiner Regeln einen internen Baum auf, der
angibt, welche Quelldateien das gewünschte Objekt erzeugen können. Der
Baum ist vielstufig (enthält alle möglichen Zwischenschritte) und
enthält u.a. hier auch „.r30->.a30->.c.
Findet es einen Kandidaten wie hier die *.c, wird die gewünschte
Kommando-Sequenz dann erzeugt (der Baum also ab dort in umgekehrter
Richtung durchlaufen), wenn das Prerequisite (mir fällt kein
deutscher Ausdruck ein) neuer ist.
Vielen Dank für die Erklärung, die Unterverzeichnisse werden jetzt
gebaut.
Ein Problemchen bleibt noch:
Wie kann ich in Windows folgenden Ausdruck (bash?) ausführen lassen:
Besonders gut kenne ich mit der WinAVR-Umgebung zwar nicht aus. Aber im
Makefile kannst Du das einfach als Aktion hinschreiben. Das geht. Der
make des WinAVR verwendet zum Ausführen seiner Aktionen eine
POSIX-kompatible Shell (wenn mich nicht alles täuscht, ist's die aus
MinGW).