Forum: Compiler & IDEs Makefile clean failed


von Alex -. (alex796)


Lesenswert?

Hi,
Makefile und ich sind immer noch keine Freunde geworden, und ich schlage 
mich gerade mit dem clean Befehl herum.

Mein Makefile:
1
# CC and MACH are variables
2
CC=arm-none-eabi-gcc
3
MACH=cortex-m4
4
# CFLAGS will be options passed to the compiler
5
CFLAGS= -c -mcpu=$(MACH) -mthumb -std=gnu11 -Wall -O0
6
7
# Target: Dependencies
8
all: main.o led.o startup_stm32f303cctx.o
9
main.o: main.c
10
  $(CC) $(CFLAGS) -o $@ $^
11
  
12
led.o: led.c
13
  $(CC) $(CFLAGS) -o $@ $^
14
15
startup_stm32f303cctx.o: startup_stm32f303cctx.s
16
  $(CC) $(CFLAGS) -o $@ $^
17
18
clean:
19
  rm -rf *.o *.elf

"make all" funktioniert, es werden .o Dateien erzeugt.

"make clean" funktioniert nicht. Ausgabe auf der Konsole:
> rm -rf *.o *.elf
> process_begin: CreateProcess(NULL, rm -rf *.o *.elf, ...) failed.
> make (e=2): The system cannot find the file specified.
> make: *** [clean] Error 2

Kann jemand erkennen, was ich falsch mache?

: Bearbeitet durch User
von 2⁵ (Gast)


Lesenswert?

Arbeitest du evtl. unter Windows? Da gibts kein "rm"

von Alex -. (alex796)


Lesenswert?

2⁵ schrieb:
> Arbeitest du evtl. unter Windows? Da gibts kein "rm"

Oh, guter Einwand. Ich arbeite mit Windows, und habe mich beim Makefile 
an einem Video gehalten.

Nach ein wenig Google, verwendet man bei Windows -del anstatt -rm

Vielen Dank für die schnelle Hilfe.

Gruß,

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Make ist ein per POSIX standardisiertes tool. (Wobei ich nur die GNU 
Make Variante brauchbar finde). Von einem Build environment mit Make 
würde ich erwarten, das zumindest die meisten der von POSIX für POSIX 
Systeme vorgeschriebenen Tools auch da sind: 
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html

Die bessere Lösung wäre also, eine Implementation der Tools zu 
installieren, oder gleich ein richtiges OS zu verwenden.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Alex -. schrieb:
>
1
> clean:
2
>   rm -rf *.o *.elf
3
>

Wenn das auf Linux wäre:

"-r" zusammen mit "*" Wildcards bei rm ist super-gefährlich.

Ein Tippfehler (* .o statt *.o) und du hast dir dein ganzes Projekt 
abgeräumt. Ohne "-r" "nur" dein aktuelles Verzeichnis.

Wenn das so in deinem Video stand, dann ist das Video Müll.

Bein jedem halbwegs vernünftigen Make:
1
clean:
2
        -$(RM) *.o *.elf
3
.PHONY: clean
Wobei:

Das führende "-" vor "$(RM)" wird nicht benötigt wenn RM richtig 
definiert ist (nicht-existierende Dateien ignoriert werden). Schadet 
aber auch nichts. Gib mal in einem leeren(!) Verzeichnis
1
make -p
ein um alle voreingestellten Regeln und Variablen zu sehen.

Weder "$(RM)", noch ".PHONY:" sind in POXIX spezifiziert, aber ein Make 
das solche Dinge heutzutage nicht kann würde ich persönlich entsorgen.

> Kann jemand erkennen, was ich falsch mache?

Na was wohl?

1. Handbuch nicht gelesen
2. Sich auf ein YT-Video verlassen
3. Windows

von Johannes S. (Gast)


Lesenswert?

Oder weiterlernen und das makefile von cmake erzeugen lassen, das 
generiert dann plattformabhängig die richtigen Befehle.

von Rolf M. (rmagnus)


Lesenswert?

Hannes J. schrieb:
> Bein jedem halbwegs vernünftigen Make:
> clean:
>         -$(RM) *.o *.elf
> .PHONY: clean

Falls das Projekt irgendwann in mehrere Verzeichnisse eingeteilt wird, 
muss man das rm dann allerdings für jedes Verzeichnis, in dem generierte 
Files liegen können, extra angeben. Und wenn die .o-Files in ein 
separates build-Verzeichnis gesteckt werden, muss man das entsprechend 
berücksichtigen.

> Wobei:
>
> Das führende "-" vor "$(RM)" wird nicht benötigt wenn RM richtig
> definiert ist (nicht-existierende Dateien ignoriert werden).

Die werden nur dann ignoriert, wenn du -f angibst, was bei dir oben aber 
fehlt. Ohne -f wird bei POSIX rm mit einer Fehlermeldung abgebrochen.

von Markus F. (mfro)


Lesenswert?

Rolf M. schrieb:
> Falls das Projekt irgendwann in mehrere Verzeichnisse eingeteilt wird,
> muss man das rm dann allerdings für jedes Verzeichnis, in dem generierte
> Files liegen können, extra angeben. Und wenn die .o-Files in ein
> separates build-Verzeichnis gesteckt werden, muss man das entsprechend
> berücksichtigen.

Makefiles sollten das (und nur das) löschen, was sie erzeugen.
Also statt:
1
clean:
2
        -$(RM) *.o *.elf

lieber
1
clean:
2
        -$(RM) $(OBJS) $(EXE)

Dann gibt's auch keine bösen Überraschungen

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Rolf M. schrieb:
> Falls das Projekt irgendwann in mehrere Verzeichnisse eingeteilt wird,
> muss man das rm dann allerdings für jedes Verzeichnis, in dem generierte
> Files liegen können, extra angeben.

Nein. Ein "-r" zusammen mit einem "*" in den Argumenten von rm ist 
trotzdem super-gefährlich. Es gab schon genug die plötzlich dumm aus der 
Wäsche geschaut haben. Das hat nichts mit Make zu tun, sondern mit der 
Shell-Syntax und dem Verhalten von rm.

> Und wenn die .o-Files in ein
> separates build-Verzeichnis gesteckt werden, muss man das entsprechend
> berücksichtigen.

Dann lässt man "*" weg. Denn gerade da braucht man es nicht:
1
$(RM) -r build

Ich rede hier von dem Unterschied ein paar Verzeichnisse kontrolliert zu 
löschen. Z.B.
1
$(RM) -r build cache tmp

und dem Fehler sich versehentlich das Projekt zu versenken:
1
$(RM) -r * .o

Am besten noch bevor man eine größere Änderung in git reingeschoben hat. 
Noch dazu dass das "-r" für die beabsichtigte Löschung "*.o" völlig 
unnütz ist und nicht benötigt wird.

>> Das führende "-" vor "$(RM)" wird nicht benötigt wenn RM richtig
>> definiert ist (nicht-existierende Dateien ignoriert werden).
>
> Die werden nur dann ignoriert, wenn du -f angibst, was bei dir oben aber
> fehlt. Ohne -f wird bei POSIX rm mit einer Fehlermeldung abgebrochen.

Ne, das passt schon. Die normale Definition von $(RM) ist "rm -f".

Markus F. schrieb:
> Makefiles sollten das (und nur das) löschen, was sie erzeugen.

Ja, und ich würde auch eine Doppel-Doppelpunkt-Regeln verwenden um 
Erzeugung und Cleanup im Makefile hintereinander zu haben. Aber ich 
wollte es nicht zu kompliziert machen.

Ansonsten geht es bei Dingen die nur teilweise oder gar nicht von Make 
erzeugt werden nicht ohne "*". Klassisches Beispiel sind Reste vom 
Editor
1
clean:
2
        $(RM) *.bak *~
3
.PHONY: clean

von Oliver S. (oliverso)


Lesenswert?

🐧 DPA 🐧 schrieb:
> Die bessere Lösung wäre also, eine Implementation der Tools zu
> installieren, oder gleich ein richtiges OS zu verwenden.

https://www.gnu.org/software/coreutils/

Oliver

von Markus F. (mfro)


Lesenswert?

Hannes J. schrieb:
> Ansonsten geht es bei Dingen die nur teilweise oder gar nicht von Make
> erzeugt werden nicht ohne "*". Klassisches Beispiel sind Reste vom
> Editor
1
make clean

sollte genau das tun, wozu es gedacht ist: eine "saubere" 
Ausgangssituation für ein folgendes make herstellen.

"Küche putzen" kann man heutzutage getrost git clean überlassen...

: Bearbeitet durch User
von Alex -. (alex796)


Lesenswert?

Vielen Dank euch allen, ich werde mich näher und tiefgründig mit make 
befassen :)

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.