Forum: Compiler & IDEs Frage zu %.o : %.c im Makefile


von Bronko P. (bronko99)


Lesenswert?

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

von G a s t (Gast)


Lesenswert?


von Bronko P. (bronko99)


Lesenswert?

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

von LostMind (Gast)


Lesenswert?

> 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...

von Hc Z. (mizch)


Lesenswert?

Du bringst zwei Dinge durcheinander:
1
%.a30 : %.c
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.

von LostMind (Gast)


Lesenswert?

PS:

> all: %.r30

Das geht so leider nicht... hier liegt dein Problem

von Bronko P. (bronko99)


Lesenswert?

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

von Hc Z. (mizch)


Lesenswert?

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.

von Bronko P. (bronko99)


Lesenswert?

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?

von Hc Z. (mizch)


Lesenswert?

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.

von Bronko P. (bronko99)


Lesenswert?

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?

von Hc Z. (mizch)


Lesenswert?

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).

von Bronko P. (bronko99)


Lesenswert?

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:
1
assembling crc.r30 from crc.a30
2
C:\Renesas\nc30wa\v545r01/bin/as30.exe -. -S -LM crc.a30
3
 Error (as30.exe): Can't open file 'crc.a30'
4
make: *** [crc.r30] Error 2
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?

von Hc Z. (mizch)


Lesenswert?

Das würde ich schon. Allein:

Mit folgendem Makefile
1
CSRC := $(wildcard *.c)
2
ALL_A30 := $(patsubst %.c, %.a30, $(CSRC))
3
ALL_R30 := $(patsubst %.c, %.r30, $(CSRC))
4
ECHO = @echo
5
AS = @echo Assembler
6
CC = @echo CC
7
8
all: $(ALL_R30)
9
  $(ECHO) 3  
10
  
11
%.r30: %.a30
12
  $(ECHO) assembling $@ from $<
13
  $(AS) $(AFLAGS) $<
14
  
15
%.a30: %.c
16
  $(ECHO) compiling $@ from $<
17
  $(CC) $(INCLUDES) $(CFLAGS) $<
passiert in einem Verzeichnis, in dem nur Makefile und x.c (leer) sich 
befinden:
1
hcz@Xelzbrot:/home/hcz/x/x$ make
2
compiling x.a30 from x.c
3
CC x.c
4
assembling x.r30 from x.a30
5
Assembler x.a30
6
3
7
hcz@Xelzbrot:/home/hcz/x/x$
Also das, was ich (und vermutlich Du) erwarten würde.

von Hc Z. (mizch)


Lesenswert?

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.

von Bronko P. (bronko99)


Lesenswert?

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:
1
for dir in $(SUBDIRS); do make -C $$dir; done

Danke u. Gruß
Bronko

von Hc Z. (mizch)


Lesenswert?

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).

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.