PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C mit Makefile unter Linux (noob)


Gast
2006-03-31, 16:27:51
Hi!
Ich wollte etwas den Umgang mit Linux erlernen und habe nebenbei noch etwas mit Makefiles herumspielen wollen. Aber schon beim ersten, einfachen Schritt stolpere ich :/ :

Hier mein geniales Superprogramm 'test.c':
#include <stdio.h>

int main(int argc; char** argv)
{
printf("testausgabe\n");
return 0;
} // end main


Inhalt meiner 'Makefile'-Datei:
CFLAGS=-Wall -g
test: test.c

Hier die Ausgabe nach 'make test':
>make test
cc -Wall -g test.c -o test
test.c:3: error: parameter ‘argc’ has just a forward declaration
test.c:4: warning: first argument of ‘main’ should be ‘int’
test.c:4: warning: ‘main’ takes only zero or two arguments
test.c:7:14: warning: no newline at end of file
make: *** [test] Fehler 1

argc hat eine forward declaration? Was ist das?
First arg of main is doch int?!
Kein oder zwei Argumente? Wieso?
Keine neue Zeile am Ende der Datei? Wie?!

Marscel
2006-03-31, 16:34:05
Das ist aber kein Problem des Makefiles, sondern deines Quellcodes.

Es ist

int main(int argc, char** argv) { //... }

richtig, das muss ein Kommata sein, kein Semikolon.

Die Warnung der "newline" kannst du vernachlässigen.

Gast
2006-03-31, 16:43:14
*legt 5€ in die Deppenkasse*

division
2006-04-01, 12:42:09
Die Warnung der "newline" kannst du vernachlässigen.

Kann man nicht. Zumindest wenn man etwas gewissenhaft das ganze lernen will.

Am Ende bekommt man noch raus, das da 234MB Speicherleck irgendwo rumgammelt und man sich dann denkt.... :" Ist doch egal.... ich hab ja 2 GB".

Marscel
2006-04-01, 13:19:59
Am Ende bekommt man noch raus, das da 234MB Speicherleck irgendwo rumgammelt und man sich dann denkt.... :" Ist doch egal.... ich hab ja 2 GB".

Es handelt sich um eine fehlende Freizeile am Ende der Quelldatei, nicht um Warnung, dass z.B. eine Zuweisung vorliegt, bei der Nachkommastellen verloren gehen oder Pointer ins nichts zeigen.

Sicher, keine Warnungen sind auch gut, aber bei einer fehlenden Freizeile am Ende geht die Welt nicht unter. Bis jetzt ist bei mir noch nie daran ein Programm gescheitert, korrigieren tu ich es immer bei der nächsten Gelegenheit.

division
2006-04-01, 22:21:10
Das ist mir schon klar....

Aber ich bin der meinung man sollte sich da schon die Zeit nehmen um zu gucken warum der Compiler Warnungen ausgibt.

Nächstes mal ist es vieleicht was anderes, was später in einer Weiterentwicklung des Codes zum fehler führt und man dann suchen muss wie ein Held.

Also kurz: Es ist anzustreben, ein Programm ohne Felher und Warnungen zu compilieren.

Coda
2006-04-02, 01:31:39
Er sagte "Die Warning mit der Newline kannst du vergessen" - und das ist definitiv richtig.

SamStone
2006-04-02, 12:42:49
Inhalt meiner 'Makefile'-Datei:
CFLAGS=-Wall -g
test: test.c
Funktioniert die Makefile tatsächlich so? Ich dachte immer man muss da auch noch angeben, wie man die test.c überhaupt erstellen kann (also explizit einen compileraufruf da hin schreiben)

SethGecko
2006-04-02, 17:59:39
Was hat das denn für einen Hintergrund, dass vor der fehlenden Newline am Ende gewarnt wird?

mfg Seth

Xmas
2006-04-02, 18:08:17
Funktioniert die Makefile tatsächlich so? Ich dachte immer man muss da auch noch angeben, wie man die test.c überhaupt erstellen kann (also explizit einen compileraufruf da hin schreiben)
Für einige Dateitypen gibt es bereits implizite Regeln.

Coda
2006-04-02, 18:13:58
Was hat das denn für einen Hintergrund, dass vor der fehlenden Newline am Ende gewarnt wird?
Das sollte so sein bei Unix-Textdateien, ist für den C-Standard aber eigentlich irrelevant, da Newlines etc. sowieso überlesen werden.

zeckensack
2006-04-03, 00:56:44
Was hat das denn für einen Hintergrund, dass vor der fehlenden Newline am Ende gewarnt wird?

mfg SethWenn eine Datei mit einem //-Kommentar endet, aber ohne Newline, und in eine andere Datei per #include eingebunden wird, ist der Effekt dass die nächste Zeile verloren geht.

Bisschen esoterisch, aber könnte irgendjemanden mal irritiert haben.

Ich habe persönlich auch kein Problem mit dieser Warnung, dh ich behebe diesen "Fehler" ~gerne wenn GCC deswegen motzt. Es gibt viel unsinnigere Warnungen als diese (bsw die die jeder C++-Programmierer erstmal zu sehen bekommt wenn er versucht Präambeln richtig zu benutzen).

Coda
2006-04-03, 01:05:55
Wenn eine Datei mit einem //-Kommentar endet, aber ohne Newline, und in eine andere Datei per #include eingebunden wird, ist der Effekt dass die nächste Zeile verloren geht.
Warnt GCC denn auch wenn das bei einem Header so ist?

Gast
2006-04-03, 22:28:10
Wo wir gerade beim Thema Makefiles sind:
Woher kriegt make eigentlich die Information, dass sich eine .c Dateien seit dem erstellen der letzten .o Dateien verändert hat?

Xmas
2006-04-03, 22:37:33
Vom Änderungsdatum der Dateien.

Gast
2006-04-03, 22:41:31
Vom Änderungsdatum der Dateien.
Irgendwie naheliegend :P Bin ich trotzdem nicht drauf gekommen.
Danke!

Gast
2006-04-08, 12:35:41
Wie kann ich mehrere .cpp- und .hh-Dateien (zB test.cpp, test.hh und mainprog.cpp) mittels make und gcc übersetzen?
Ich wühle seit 10min durch die Man-pages, aber ich finde die Beispiele nicht. :(

zeckensack
2006-04-08, 19:23:38
Wie kann ich mehrere .cpp- und .hh-Dateien (zB test.cpp, test.hh und mainprog.cpp) mittels make und gcc übersetzen?
Ich wühle seit 10min durch die Man-pages, aber ich finde die Beispiele nicht. :(Du definierst mehrere Make-Targets.ZBtest.o: test.cpp test.hh
g++ -c -o test.o test.cpp

mainprog.o: mainprog.cpp test.hh
g++ -c -o mainprog.o mainprog.cppBitte daran denken Tabs statt Leerzeichen zu benutzen!

Aus den Headern alleine wird kein Kompilat, also brauchst du dafür auch kein Ziel. Edit: Allerdings sind die Kompilate wahrscheinlich von den Headern abhängig, von daher: Abhängigkeit setzen, wie oben geschehen.

Dann einfach make all.

Wenn du das ganze zu einem Programm zusammenlinken möchtest, kannst du auch dafür noch ein Ziel angeben.fertiges_programm: test.o mainprog.o
g++ blabla ... (dein Linker-Kommando)Und dann kannst du mit "make fertiges_prorgramm" a)"veraltete" o-Dateien neu kompilieren, also die wo der Quellcode seit dem letzten Kompilieren geändert wurde und b)am Ende das ganze zusammenlinken.

Coda
2006-04-08, 19:31:04
Gibts für Linux eigentlich auch ein modernes Buildsystem das die Abhängigkeiten automatisch erkennt?

Xmas
2006-04-08, 19:53:52
Aus den Headern alleine wird kein Kompilat, also brauchst du dafür auch kein Ziel.
Aber es kann sinnvoll sein, sie in die Abhängigkeitenliste zu setzen, damit auch dann neu kompiliert wird wenn sich nur die Header ändern.

Trap
2006-04-09, 12:41:43
Gibts für Linux eigentlich auch ein modernes Buildsystem das die Abhängigkeiten automatisch erkennt?
Ja, sogar mehrere. Aber nur make+autotools funktioniert überall, auch auf den allerexotischsten Systemen.

Coda
2006-04-09, 13:22:30
Kannst du mir die nennen, ich such schon länger danach...

Trap
2006-04-09, 13:55:05
Scons und Jam sind 2 die mir so spontan einfallen. Gibt aber noch einige mehr, hab mich aber bis jetzt nicht drum gekümmert herauszufinden welches Tool besonders gut ist.

Coda
2006-04-09, 14:25:31
Also Jam hab ich mir schonmal angeschaut, aber das versteht ja kein Mensch.

zeckensack
2006-04-09, 16:56:06
Aber es kann sinnvoll sein, sie in die Abhängigkeitenliste zu setzen, damit auch dann neu kompiliert wird wenn sich nur die Header ändern.Jo stimmt, ich werd's mal editieren :)

Uuuund ... da ich weiß wie bescheuert und unnütz die Make-Dokumentation ist, wenn man Make noch nicht verstanden hat :rolleyes:
... möchte ich mal kurz zusammengefasst erklären was Make eigentlich tut.

Make löst (hierarchische) Abhängigkeiten auf. Ein "Ziel" in einem Makefile sieht immer so aus:Zu_erzeugende_Datei: Quelldatei1 Quelldatei2 ... beliebig_viele_davon
[TAB] Kommando um Zu_erzeugende_Datei zu erzeugen
Wenn ich das in ein Makefile schreibe und dann "make Zu_erzeugende_Datei" aufrufe, passiert folgendes:
Zu_erzeugende_Datei wird gesucht. Falls vorhanden, wird das Datum der letzten Änderung dieser Datei mit allen Daten letzter Änderung der Abhängigkeiten (Quelldatei1 etc) verglichen.
Falls Zu_erzeugende_Datei gar nicht existiert, oder die letzte Änderung länger her ist als bei der zuletzt geänderten Abhängigkeit, gilt Zu_erzeugende_Datei als veraltet.
Wenn sie nicht veraltet ist, brechen wir an dieser Stelle ab!

Für Fortgeschrittene: falls die Abhängigkeiten selbst (oder nur ein Teil davon) selbst Make-Ziele sind, wird der gesamte Prozess, den ich noch gar nicht zu Ende erklärt habe, zuerst für dieses Ziel ausgeführt. Ja, das kann zu Rekursionen führen. Zu_erzeugende_Datei wird in dieser Kette von Rekursionen als letztes zu Ende ... aktualisiert ...
Das Aktualisieren: Make führt das/die mit Tab eingerückte(n ) Kommandos (auf der Shell) aus.

Beim Aktualisieren ist es btw völlig unerheblich ob das Kommando tatsächlich Zu_erzeugende_Datei aus den Abhängigkeiten erzeugt. Dies ist die Konvention, und der ganze Make-Prozess wird irgendwo auch absurd wenn dies nicht der Fall ist, aber es besteht kein Zwang. Wenn Zu_erzeugende_Datei nicht durch Ausführen des Kommandos tatsächlich aktualisiert oder zumindest mal angelegt wird, wird "make Zu_erzeugende_Datei" immer dazu führen dass Make "denkt" die Datei sei mittlerweile veraltet, und das Kommando ausführen.

ZB:immer_machen: klaus.cpp
[TAB] g++ -c klaus.o klaus.cpp"make immer_machen" wird immer klaus.cpp kompilieren, weil das Kommando keine Datei mit dem Namen immer_machen erzeugt.

Xmas
2006-04-09, 19:07:07
Wobei man solcherlei bezeichnete Targets der Phony-Liste hinzufügen sollte, sondst funktioniert es nicht wenn einmal tatsächlich eine Datei "immer_machen" existiert.

.PHONY: all clean reallyclean
Insgesamt halte ich makefiles ab einer bestimmten Komplexität aber eher für eine Qual, da die Möglichkeiten zum Debuggen mangelhaft sind. Dann schreibe ich doch lieber ein prozedurales Build-Script.