Forum: Compiler & IDEs Makefile vereinfachen (Cython)


von Dennis S. (eltio)


Lesenswert?

Guten Morgen zusammen,

ich möchte mit Cython und GCC Python-Code in eine ausführbare Datei zu 
übersetzen und dies mit einem Makefile zu automatisieren. Das 
Dummyprojekt besteht aus der "Main"-Datei app.py und den Modulen add.py 
und sub.py. Hier mein aktueller Stand:
1
CC = gcc
2
INC = /usr/include/python3.5m
3
LIBS = -l python3.5m
4
OBJECTS = add.c sub.c app.c
5
CFLAGS = -O3
6
7
app: $(OBJECTS)
8
  $(CC) $(OBJECTS) -o $@ $(CFLAGS) -I $(INC) $(LIBS)
9
10
add.c: add.py
11
  cython add.py
12
13
sub.c: sub.py
14
  cython sub.py
15
16
app.c: app.py
17
  cython --embed app.py
18
19
clean:
20
  rm *.c

Die Datei app.py muss wegen des --embed-Parameters im Cython-Aufruf 
gesondert behandelt werden. Alle andere Dateien jedoch nicht. Wie kann 
ich dies elegant in dem Makefile abbilden?

Wünschenswert wäre natürlich noch die rekursive Abarbeitung und das 
Ersetzen der Dateiliste durch eine Variable oder so. Aber ich denke da 
werde ich was finden.

Gruß und Dank
Dennis

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Bei GNU-make kann man target-specific flags setzen.

Du schreibst eine allg. Regel für .c -> .py, in der Du die Variable 
bspw. EXTRAFLAGS verwendest.

Und für das target app.c
1
app.c: EXTRAFLAGS += --embed

: Bearbeitet durch User
von Dennis S. (eltio)


Lesenswert?

Cool, vielen Dank für den Hinweis. Falls es jemanden interessiert hier 
die aktuelle Version mit dem Tip von Wilhelm M. und dem automatischem 
Auflisten der Python-Codes. Fehlt nur noch die rekursive Version:
1
CC = gcc
2
INC = /usr/include/python3.5m
3
LIBS = -l python3.5m
4
OBJECTS = $(patsubst %.py,%.c,$(wildcard *.py))
5
CFLAGS = -O3
6
7
app: $(OBJECTS)
8
  $(CC) $(OBJECTS) -o $@ $(CFLAGS) -I $(INC) $(LIBS)
9
10
%.c: %.py
11
  cython $(EXTRAFLAGS) $<
12
13
app.c: EXTRAFLAGS += --embed
14
15
clean:
16
  rm *.c

von Wilhelm M. (wimalopaan)


Lesenswert?

Was meinst Du genau mit rekursivem Abarbeiten? In vielen directories?

von Dennis S. (eltio)


Lesenswert?

Wilhelm M. schrieb:
> Was meinst Du genau mit rekursivem Abarbeiten? In vielen
> directories?

Naja, ein "echtes" Python-Projekt ist ja etwas umfangreicher. Da wäre 
die Ordnerstruktur beispielsweise:
1
Modul1
2
--mod1.py
3
Module2
4
--mod2.py
5
app.py

Es gibt also auch Quellcodes in Unterordnern die mit einbezogen werden 
müssen. Ich habe jetzt folgende Lösung die zu funktionieren scheint, 
aber vielleicht habe ich etwas wichtiges übersehen:
1
CC = gcc
2
INC = /usr/include/python3.5m
3
LIBS = -l python3.5m
4
OBJECTS = $(patsubst %.py,%.c,$(shell find . -name '*.py'))
5
CFLAGS = -O3
6
7
app: $(OBJECTS)
8
  $(CC) $(OBJECTS) -o $@ $(CFLAGS) -I $(INC) $(LIBS)
9
10
%.c: %.py
11
  cython $(EXTRAFLAGS) $<
12
13
app.c: EXTRAFLAGS += --embed
14
15
clean:
16
  rm *.c

Gruß
Dennis

von Markus F. (mfro)


Lesenswert?

Dennis S. schrieb:
> OBJECTS = $(patsubst %.py,%.c,$(shell find . -name '*.py'))

Den unbedarften Leser irritiert möglicherweise, daß hier nicht drin ist, 
was draufsteht: $(OBJECTS) sind gar keine OBJECTS (und jetzt hast Du das 
gegenüber deiner ersten Version auch noch gut versteckt).

Ich jedenfalls würde davon ausgehen, daß in einer Variablen mit dem 
Namen nur *.o-Dateien drin sein können.

Darüber hinaus: das $(shell find ...) kann man machen, muß man aber 
nicht. Wenn Du dir irgendeine "unbedarfte" Python-Datei (die mit deinem 
Projekt gar nichts zu tun hat, z.B. zum Vergleich) in deine 
Verzeichnisstruktur kopierst, erlebst Du möglicherweise eine 
Überraschung.

: Bearbeitet durch User
von Dennis S. (eltio)


Lesenswert?

@Markus F.:

Du hast mit beiden Punkten Recht. Ich habe den Variablennamen geändert. 
Aber die zweite Anmerkung ignoriere ich erstmal gekonnt für dieses 
Projekt... ;-)

von I <3 Makefiles (Gast)


Lesenswert?

>> Darüber hinaus: das $(shell find ...) kann man machen, muß man aber nicht.
>> Wenn Du dir irgendeine "unbedarfte" Python-Datei (die mit deinem Projekt gar
>> nichts zu tun hat, z.B. zum Vergleich) in deine Verzeichnisstruktur kopierst,
>> erlebst Du möglicherweise eine Überraschung.

> Du hast mit beiden Punkten Recht. Ich habe den Variablennamen geändert.
> Aber die zweite Anmerkung ignoriere ich erstmal gekonnt für dieses
> Projekt... ;-)

So sehr dieses "Sammeln per Globbing" aus programmatischer Sicht 
attraktiv weil "algorithmisch" und konzis erscheint, es ist ein No-Go.

Bedienen wir uns der Analogie dass ein Makefile wie ein Kochrezept 
wirkt, so bedeutet obige Zeile das als Kochzutaten "alles was Rot ist" 
und gerade auf der Küchenarbeitsfläche herumliegt ins Gericht kommt. Die 
Warnung von Markus weist darauf hin das eventuell Paprika- und 
Karottenabschnitte im Kirschkuchen landen können.

Gute Makefiles listen die Projekt"Zutaten" explizit und abschliessend 
auf; ja das verpflichtet zur Pflege. Das erlaubt aber auch 
(plausibilitäts-)Kontrolle.

Globbing ist nützlich zur Selektion von Teilmengen.

Eine alternative Herangehensweise könnte sein, dass im Makefile ein 
neues, leeres Arbeitsverzeichnis erstellt wird und z.B. aus einem 
SourcecodeRepo (git, svn, ...) mit den "Zutaten bestückt" wird.

von Dennis S. (eltio)


Lesenswert?

I <3 Makefiles schrieb:
> Bedienen wir uns der Analogie dass ein Makefile wie ein Kochrezept
> wirkt, so bedeutet obige Zeile das als Kochzutaten "alles was Rot ist"
> und gerade auf der Küchenarbeitsfläche herumliegt ins Gericht kommt. Die
> Warnung von Markus weist darauf hin das eventuell Paprika- und
> Karottenabschnitte im Kirschkuchen landen können.
Eine nette Analogie. Aber konkreter steht da ja "alles was .py" ist, 
wird verarbeitet. Und das ist in diesem Fall absolut korrekt.

> Gute Makefiles listen die Projekt"Zutaten" explizit und abschliessend
> auf; ja das verpflichtet zur Pflege. Das erlaubt aber auch
> (plausibilitäts-)Kontrolle.
Ich wollte gerade rummäkeln... aber ja, der Linux-Kernel macht dies in 
der Tat so.

> Eine alternative Herangehensweise könnte sein, dass im Makefile ein
> neues, leeres Arbeitsverzeichnis erstellt wird und z.B. aus einem
> SourcecodeRepo (git, svn, ...) mit den "Zutaten bestückt" wird.
Das ist hier der Fall. Das ganze wird mit einem VCS verwaltet.

Ich danke dir für deine Anmerkung. Ich denke drüber nach, allerdings 
habe ich das Gefühl, dass die Bequemlichkeit vorerst siegen wird...

Gruß
Dennis

von Bernd K. (prof7bit)


Lesenswert?

I <3 Makefiles schrieb:
> So sehr dieses "Sammeln per Globbing" aus programmatischer Sicht
> attraktiv weil "algorithmisch" und konzis erscheint, es ist ein No-Go.

Das ist Geschmackssache. Der Pragmatiker verwendet Ordner um 
zusammengehörige Dateien zu gruppieren und Dateinamenerweiterungen um 
ihren Dateityp zu kennzeichnen. Anstatt Listen dafür zu führen verwendet 
er einfach die ohnehin vorhandenen Mechanismen des Dateisystems.

> Bedienen wir uns der Analogie dass ein Makefile wie ein Kochrezept
> wirkt, so bedeutet obige Zeile das als Kochzutaten "alles was Rot ist"
> und gerade auf der Küchenarbeitsfläche herumliegt ins Gericht kommt.

genausogut kann man vereinbaren daß alles was in den Schüsseln die mit 
"Zutaten/Kirschkuchen" und der Schüssel "Zutaten/Kuchen" beschriftet ist 
in den Kirschkuchen gelinkt wird. Egal was es ist. Es ist ja nicht so 
daß die Zutaten lustig auf dem Tisch herumspringen wenn gerade mal 
keiner hinschaut und von selbst in diese Schüsseln hüpfen. Man kann 
problemlos vereinbaren daß nichts in der Schüssel sich ohne guten Grund 
dort befindet.

Dann muss man auch nicht dauernd am Makefile herumschrauben wenn man mal 
eine Datei umbenennt oder eine neue hinzukommt, man wirft sie einfach in 
den richtigen Ordner. Die Anwesenheit oder Abwesenheit einer Datei in 
einem bestimmten Ordner ist exakt genauso explizit wie das 
Aufschreiben ihres Namens in einer Liste, kein bisschen weniger und auch 
kein bisschen mehr.

: Bearbeitet durch User
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.