mikrocontroller.net

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


Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht 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:
CSRC := $(wildcard *.c)

Den Asudruck verstehe ich scheinbar flasch:
%.o: %.c
   $(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:
all: %.r30

%.r30: %.a30
  $(ECHO) assembling $<

%.a30 : %.c
        $(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

Autor: G a s t (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht 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
 %.o : %.c
             $(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

Autor: LostMind (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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":
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
%.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...

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du bringst zwei Dinge durcheinander:
%.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
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.

Autor: LostMind (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS:

> all: %.r30

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

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht 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
CSRC := $(wildcard *.c)

%.r30: %.a30
  $(ECHO) assembling $<

%.a30: %.c
  $(ECHO) ... compiling $<   
wird keines der Targets ausgewertet, da er mein clean Target weiter 
unten "macht" mit ansschließendem
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

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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
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.

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht 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
all: $(ALL_R30)

%.r30: %.a30
  $(ECHO) assembling $@

%.a30: %.c
  $(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?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht 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:
CSRC := $(wildcard *.c)
ALL_A30 := $(patsubst %.c, %.a30, $(CSRC))
ALL_R30 := $(patsubst %.c, %.r30, $(CSRC))

all: $(allR30)
  $(ECHO) 3

  
%.r30: %.a30
  $(ECHO) assembling $@
  
%.a30: %.c
  $(ECHO) compiling $@

Ausgabe:
3

Warum greifen die Regeln nicht??
test:
  $(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?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das macht aus verschiedenen Gründen keinen Sinn.  Ich nehme ein 
Beispiel:
%.a30: %.c
  $(ECHO) compiling $@
Das ist eine allgemeine Regel, wie ein einzelner *.a30 zu erzeugen ist: 
durch Kompilieren des zugehörigen *.c.
allA30:  $(CSRC)
  $(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).

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, weil ich also nur ein ECHO mache braucht er die weiteren 
Abhängigkeiten nicht berücksichtigen?
all: $(ALL_R30)
  $(ECHO) 3  
  
%.r30: %.a30
  $(ECHO) assembling $@ from $<
  $(AS) $(AFLAGS) $<
  
%.a30: %.c
  $(ECHO) compiling $@ from $<
  $(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:
assembling crc.r30 from crc.a30
C:\Renesas\nc30wa\v545r01/bin/as30.exe -. -S -LM crc.a30
 Error (as30.exe): Can't open file 'crc.a30'
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?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das würde ich schon. Allein:

Mit folgendem Makefile
CSRC := $(wildcard *.c)
ALL_A30 := $(patsubst %.c, %.a30, $(CSRC))
ALL_R30 := $(patsubst %.c, %.r30, $(CSRC))
ECHO = @echo
AS = @echo Assembler
CC = @echo CC

all: $(ALL_R30)
  $(ECHO) 3  
  
%.r30: %.a30
  $(ECHO) assembling $@ from $<
  $(AS) $(AFLAGS) $<
  
%.a30: %.c
  $(ECHO) compiling $@ from $<
  $(CC) $(INCLUDES) $(CFLAGS) $<
passiert in einem Verzeichnis, in dem nur Makefile und x.c (leer) sich 
befinden:
hcz@Xelzbrot:/home/hcz/x/x$ make
compiling x.a30 from x.c
CC x.c
assembling x.r30 from x.a30
Assembler x.a30
3
hcz@Xelzbrot:/home/hcz/x/x$ 
Also das, was ich (und vermutlich Du) erwarten würde.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bronko Pavel (bronko99)
Datum:

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

Danke u. Gruß
Bronko

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.