staging.inyokaproject.org

makefile - clean: rm *.o

Status: Gelöst | Ubuntu-Version: Ubuntu 20.04 (Focal Fossa)
Antworten |

Data2006

Anmeldungsdatum:
7. November 2021

Beiträge: 939

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 Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Der Befehl zum "clean" (also das rm) muss in die nächste Zeile.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

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

1
clean: ; rm -f *.o

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 939

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

1
clean: ; rm -f *.o

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: 11278

Bei mir klappt das, wenn ich z.B. so ein Makefile anlege:

1
2
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: 939

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: 11278

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: 939

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: 939

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: 11278

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:

1
2
3
4
5
6
7
default: main.o test.o
        g++ main.o test.o -o linked_test

%.o : %.c %.cpp
        g++ -c $<

clean: ; rm -f *.o

test.cpp:

1
2
3
4
5
6
#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:

1
2
3
4
5
#include <stdio.h>

void foo(void) {
    printf("Hello, World!\n");
}

main.c:

1
2
3
4
5
6
7
8
#include "foo.hpp"
#include "test.hpp"

int main() {
    foo();
    bar();
    return 0;
};

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 939

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:

1
2

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: 939

Warum heißt es %.c %.cpp und nicht *.c *.cpp ?

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

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: 11278

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

1
2
3
4
5
6
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: 939

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.

Antworten |