Data2006
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
Moin zusammen, ich weiß noch nicht was für eine IDE für mein virtuelles Ubuntu 22.04 benutzen werde (s. anderes Posting) Ich habe mal was programmiert unter Ubuntu 20.04:
main.cpp
void funktion1();
void funktion2();
int main(void)
{
funktion1();
funktion2();
return 0;
} funktion1.cpp
#include <iostream>
void funktion1()
{
std::cout << "Dies ist die" << std::endl;
std::cout << "1. Funktion" << std::endl << std::endl;
} funktion2.cpp
#include <iostream>
void funktion2()
{
std::cout << "Dies ist die" << std::endl;
std::cout << "2. Funktion" << std::endl << std::endl;
}
Dazu habe ich folgendes makefile erstellt
programm_funktionen: main.o funktion1.o funktion2.o
g++ main.o funktion1.o funktion2.o -lm -o programm_funktionen2
main.o: main.cpp
g++ -c main.cpp
funktion1.o: funktion1.cpp
g++ -c funktion1.cpp
funktion2.o: funktion2.cpp
g++ -c funktion2.cpp
clean: rm *.o
Das Kompilieren klappt nach ersten Startschwierigkeiten auch. Und mein Miniprogramm läuft auch, nur die 3 *.o Dateien werden nicht gelöscht. Diese Anweisung habe ich in einem Buch gefunden. Wie immer, lieben Dank Euch.
Heiko
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Der Befehl zum "clean" (also das rm ) muss in die nächste Zeile.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Um das noch etwas weiter auszuführen: Du hast Targets, denen nach dem Doppelpunkt Voraussetzungen (bzw. Abhängigkeiten) zugeordnet werden können und in den nachfolgenden Zeilen kommen dann die Befehle, die für das Target aufgerufen werden sollen - vgl. https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax. Alternativ kannst du auch ein Semikolon vor den Befehl setzen, wenn du das in einer Zeile halten willst, also z.B.:
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
seahawk1986 schrieb: Um das noch etwas weiter auszuführen: Du hast Targets, denen nach dem Doppelpunkt Voraussetzungen (bzw. Abhängigkeiten) zugeordnet werden können und in den nachfolgenden Zeilen kommen dann die Befehle, die für das Target aufgerufen werden sollen - vgl. https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax. Alternativ kannst du auch ein Semikolon vor den Befehl setzen, wenn du das in einer Zeile halten willst, also z.B.:
Guten Abend! Ich habe das ausprobiert:
clean: ; rm -f *.o Leider löscht der Befehl nicht die *.o Dateien. LG Heiko
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Bei mir klappt das, wenn ich z.B. so ein Makefile anlege:
| default: ; echo "Hallo"
clean: ; rm -f *.o
|
Und dann die einzelnen Targets aufrufe:
$ touch {foo,bar}.o
$ ls
bar.o foo.o Makefile
$ make
echo "Hallo"
Hallo
$ make clean
rm -f *.o
$ ls
Makefile
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
Guten Abend. Ich kann zwar mit dem touch {foo, bar}.o nicht viel anfangen.
Aber ich habe den "Fehler" gefunden. Ich muß nach make noch ein make clean aufrufen. Das stand in dem Buch nicht drin. Man kann sich das clean: ; rm -f *.o auch sparen, wenn man den Befehl nach Linken der Objektdateien aufruft:
programm: main.o textausgabe1.o textausgabe2.o
g++ main.o textausgabe1.o textausgabe2.o -lm -o programm
rm -f *.o
...
So hat es jetzt funktioniert. Kann man eigentlich auch
g++ -c *.c *.cpp
aufrufen? Gute Nacht,
Heiko
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Data2006 schrieb: Guten Abend. Ich kann zwar mit dem touch {foo, bar}.o nicht viel anfangen.
Aber ich habe den "Fehler" gefunden. Ich muß nach make noch ein make clean aufrufen. Das stand in dem Buch nicht drin. Man kann sich das clean: ; rm -f *.o auch sparen, wenn man den Befehl nach Linken der Objektdateien aufruft:
Das hat halt den Nachteil, dass ein erneutes Kompilieren unnötig langsam wird - make ist schlau genug zu erkennen, wenn sich an einer Quelltext-Date etwas geändert hat und kann dann eine object-Datei neu aus dem Target erstellen. Kann man eigentlich auch
g++ -c *.c *.cpp
aufrufen?
Können tut man schon, aber damit verliert man die Optimierungen von make nur die Dinge zu bauen, die tatsächlich benötigt werden.
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
seahawk1986 schrieb: Data2006 schrieb: Guten Abend. Ich kann zwar mit dem touch {foo, bar}.o nicht viel anfangen.
Aber ich habe den "Fehler" gefunden. Ich muß nach make noch ein make clean aufrufen. Das stand in dem Buch nicht drin. Man kann sich das clean: ; rm -f *.o auch sparen, wenn man den Befehl nach Linken der Objektdateien aufruft:
Das hat halt den Nachteil, dass ein erneutes Kompilieren unnötig langsam wird - make ist schlau genug zu erkennen, wenn sich an einer Quelltext-Date etwas geändert hat und kann dann eine object-Datei neu aus dem Target erstellen. Kann man eigentlich auch
g++ -c *.c *.cpp
aufrufen?
Können tut man schon, aber damit verliert man die Optimierungen von make nur die Dinge zu bauen, die tatsächlich benötigt werden.
Guten Morgen. Danke für die Antwort. Das heißt also doch ein clean: ; rm -f *.o machen.
Und für jede .c und .cpp Datei eine eigene Zeile?! LG
Heiko
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
PS: Wenn ich ein make clean mache und alle *.o Dateien lösche, woher weiß make dann welche *.c und *.cpp Datei neu kompiliert werden muß? Danke.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Data2006 schrieb: Und für jede .c und .cpp Datei eine eigene Zeile?!
Das muss nicht sein, dafür kann man in einem Makefile auch mit Wildcards arbeiten (am besten mal die Dokumentation zu GNU Make lesen) - kleines Beispiel:
| default: main.o test.o
g++ main.o test.o -o linked_test
%.o : %.c %.cpp
g++ -c $<
clean: ; rm -f *.o
|
test.cpp:
| #include <iostream>
#include "test.hpp"
void bar(void) {
std::cout << "Hello, Bar" << std::endl;
}
|
test.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #ifndef TEST
#define TEST
#ifdef __cplusplus
extern "C" {
#endif
void bar(void);
#ifdef __cplusplus
}
#endif
#endif
|
sowie foo.hpp:
| #include <stdio.h>
void foo(void) {
printf("Hello, World!\n");
}
|
main.c:
| #include "foo.hpp"
#include "test.hpp"
int main() {
foo();
bar();
return 0;
};
|
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
Das habe ich jetzt nicht verstanden. Ich hatte doch *.c *.cpp in einer Zeile. Oder meinst Du *.c und *.cpp in 2 Zeilen? clean: ; rm -f *.o mache ich auch so. Danke für den Tip mit GNU make. Habe das hier gefunden:
|
https://wiki.ubuntuusers.de/Makefile/
|
Ich muß aber zugeben das ich da nicht alles verstehe.
Naja, das mit makefile war nur ein kleines Beispiel in dem Buch. LG Heiko
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
Warum heißt es %.c %.cpp und nicht *.c *.cpp ?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Data2006 schrieb: Warum heißt es %.c %.cpp und nicht *.c *.cpp ?
Weil das die Syntax ist, die GNU Make für Pattern Rules haben will - am besten mal einen Blick in die Dokumentation werfen: https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html#Pattern-Rules
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Da das generelle Ziel ist, sich möglichst wenig zu wiederholen, könnte man die Objekt-Dateien noch in einer Variablen hinterlegen und den Compiler generischer angeben ($(CXX) liefert standardmäßig g++ , $(CC) liefert cc ):
| OBJECTS := main.o test.o
default: $(OBJECTS)
$(CXX) $(OBJECTS) -o linked_test
%.o : %.c %.cpp
$(CXX) -c $<
clean: ; rm -f *.o
|
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 455
|
Ok. Ich habe es langsam verstanden, aber kann ich OBJECTS nicht so schreiben:
OBJECTS:=%.o
? Und statt $(CXX) nicht lieber direkt g++ schreiben? Das ist doch kürzer. Werde mir nachher ein Muster mit den Quelldateien und makefile machen und ausdrucken.
|