Forum: Compiler & IDEs make, ld, --specs und -flto


von Vincent H. (vinci)


Angehängte Dateien:

Lesenswert?

Einen schönen guten Abend

Ich entschuldige mich für den kryptischen Titel, jedoch quälen mich ein 
paar Fragen rund um Make zu denen man so gut wie keine Infos im Netz 
findet. Hintergrund ist, dass ich habe vor kurzem angefangen eigene 
Makefiles zu erstellen um einerseits meine Builds besser unter Kontrolle 
zu haben und andererseits um Clang als Compiler für ARM auszuprobieren.

Als Tools installiert ist bei mir aktuell:
- arm-none-eabi-gcc 7.3.0
- arm-none-eabi-newlib 3.0.0-1
- make 4.2.1.

1.) Anstatt arm-none-eabi-ld direkt aufzurufen wird ja gern gcc/g++ 
verwendet, dem man via -Xlinker oder -Wl auch Linker Flags mitgeben 
kann. Aus Komfortgründen werden dann auch gerne Spec-Files übergeben, 
die sich vor allem um so Dinge wie das Linken der notwendigen 
Bibliotheken kümmern. Ein Teil des Makefiles könnte also etwa so 
aussehen:
1
LDFLAGS = -T"STM32F407VGTx_FLASH.ld" -Xlinker --gc-sections --specs=nano.specs -Wl,-Map=$(MAP)

Leider kann ich das Spec-File "nano.specs" nicht entziffern. Laut Doku 
(https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html) stehen in dem File 
mehrere sogenannte "*[spec_name]:" Tokens. Welche von diesen Rules oder 
wie man das nennt wird aber dann genutzt? (Datei im Anhang, falls es 
sich wer direkt ansehen will)


2.) Um gcc/g++ aus dem Link-Prozess zu entfernen hab ich angefangen den 
Linker direkt aufzurufen. Die entsprechenden Flags hab ich dabei 
folgendermaßen gesetzt:
1
LDFLAGS = -T"STM32F407VGTx_FLASH.ld" 
2
LDFLAGS += --gc-sections
3
LDFLAGS += -Map=$(MAP)
4
LDFLAGS += -L"/usr/arm-none-eabi/lib/armv7e-m/fpu"
5
LDFLAGS += -L"/usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu"
6
LDFLAGS += /usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu/crti.o
7
LDFLAGS += /usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu/crtn.o
8
LDLIBS += --start-group -lgcc -lc_nano -lm -lstdc++_nano --end-group

Das funktioniert prinzipiell einmal soweit ich sagen kann. 
Interessanterweise ist das entstehende Binary aber 5kB kleiner als jenes 
wenn ich gcc/g++ zum Linken nutze obwohl die Optimierungseinstellungen 
sonst vollkommen ident waren. Ich werde mir morgen diesbezüglich noch 
Map und Listing ansehen... aber irgendwas kommt mir hier komisch vor. 
Erneut wäre es wohl einfacher wenn man wüsste, was "nano.specs" im 
obrigen Linkvorgang wirklich tut.


3.) Sobald ich LTO aufdrehe funktioniert der direkte Aufruf des Linkers 
nicht mehr, der Aufruf via gcc/g++ aber schon. Beim Linken via ld selbst 
bekomm ich eine Fehlermeldung:
1
...
2
cfft_q15.c.o: plugin needed to handle lto object

Von jenem "plugin" hab ich schon einmal gehört, aber meines Wissens nach 
sollte das mit meiner GCC und Linker Version schon lange obsolet sein. 
Weiß jemand wie dieser Fehler sonst entstehen kann? Was geschieht in 
Variante 1 dass LTO dort beim Linken nicht fehlschlägt?


4.) Verwendet man keinen eigenen Startup-Code, sondern jenen der 
Toolchain, dann sind 4x Objektdatein von Interesse:
- crti.o
- crtn.o
- crtbegin.o
- crtend.o

Laut GCC Doku enthalten die letzten Beiden (begin/end) den .init und 
.fini Array Teil für C++ Ctor/Dtor. Komischerweise kann ich ohne beide 
Datein problemlos Linken und Klassen anlegen wie ich lustig bin. Wie 
gibts das?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vincent H. schrieb:

Alle Fragen kann ich dir auch nicht beantworten …

> 2.) Um gcc/g++ aus dem Link-Prozess zu entfernen

Warum zum Geier™ willst du den denn eigentlich entfernen?

gcc bzw. g++ sind die Compiler-Treiber, ein Frontend, welches einfach
für den jeweiligen Zweck die richtigen Tools mit den richtigen
Optionen aufruft *).  Du compilierst doch auch nicht, indem du explizit
cpp, cc1 und as aufrufst, warum willst du dann unbedingt den Linker
manuell anwerfen?

*) OK, klappt beim ARM leider nicht so gut wie beim Compilieren eines
Programms direkt für den Host oder auch bspw. beim AVR-GCC.  Da fehlt
ein wenig Koordination der diversen Rundrum-Dateien wie eben crt,
library, includes etc.  Hätte wohl ARM als zentrale interessierte
Institution in die Hand nehmen müssen und beim GCC koordinieren, die
einzelnen Hersteller der diversen ARMs kümmern sich um sowas nicht, da
dort jeder nur seine IDE im Blick hat und dort dann den ganzen Salat
in die IDE stopft, statt den Compiler „rund“ zu machen.

> 3.) Sobald ich LTO aufdrehe funktioniert der direkte Aufruf des Linkers
> nicht mehr, der Aufruf via gcc/g++ aber schon. Beim Linken via ld selbst
> bekomm ich eine Fehlermeldung:

Völlisch logisch.

LTO braucht einen Compiler, denn es will Code erneut compilieren
können.

ps: Um nachzuvollziehen, was der Compilertreiber denn genau als
Backends aufruft und mit welchen Optionen, füge dem Aufruf einfach ein
„-v“ hinzu.

: Bearbeitet durch Moderator
von Vincent H. (vinci)


Lesenswert?

Soweit ich weiß ist Linken via ld momentan die einzige Option mit Clang 
für armv7e-m zu compilieren.

Das mit dem LTO leuchtet mir aber schonmal ein.

von Vincent H. (vinci)


Lesenswert?

Wieso genau ich für meine Fragen jetzt ein negative Bewertung bekommen 
hab versteh ich zwar nicht, aber ich hab einige Antworten die für den 
ein oder anderen vielleicht interessant sein könnten.

Ad 1.)
Die Verbose Ausgabe von dem was passiert wenn man "nano.specs" dem 
Linker übergibt ist wirklich grausam.
1
/usr/lib/gcc/arm-none-eabi/7.3.0/../../../../arm-none-eabi/bin/ld
2
-plugin /usr/lib/gcc/arm-none-eabi/7.3.0/liblto_plugin.so
3
-plugin-opt=/usr/lib/gcc/arm-none-eabi/7.3.0/lto-wrapper
4
-plugin-opt=-fresolution=/tmp/ccstDpr9.res
5
-plugin-opt=-pass-through=-lgcc
6
-plugin-opt=-pass-through=-lg_nano
7
-plugin-opt=-pass-through=-lc_nano
8
-plugin-opt=-pass-through=-lgcc
9
-plugin-opt=-pass-through=-lc_nano
10
--sysroot=/usr/arm-none-eabi
11
-EL -X -o build/TEST/TEST.elf
12
-u _printf_float
13
/usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu/crti.o
14
/usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu/crtbegin.o
15
/usr/lib/gcc/arm-none-eabi/7.3.0/../../../../arm-none-eabi/lib/armv7e-m/fpu/crt0.o 
16
-L/usr/lib/gcc/arm-none-eabi/7.3.0/armv7e-m/fpu
17
-L/usr/lib/gcc/arm-none-eabi/7.3.0/../../../../arm-none-eabi/lib/armv7e-m/fpu 
18
-L/usr/arm-none-eabi/lib/armv7e-m/fpu -L/usr/lib/gcc/arm-none-eabi/7.3.0
19
-L/usr/lib/gcc/arm-none-eabi/7.3.0/../../../../arm-none-eabi/lib
20
-L/usr/arm-none-eabi/lib
21
--gc-sections
22
-Map=./build/TEST/TEST.map
23
-v
24
25
... Objektdatein
26
27
-lstdc++_nano
28
-lm
29
--start-group
30
-lgcc
31
-lg_nano
32
-lc_nano
33
--end-group
34
--start-group
35
-lgcc
36
-lc_nano
37
--end-group

Damit sollte sich wirklich niemand auseinander setzen müssen. 
Schrecklich.


Ad 2.)
Der Größenunterschied kam daher, weil ich aus versehen printf mit 
Floating Point Unterstützung mitcompiliert hab. Ja, die kostet 
tatsächlich 5kB...


Clang kommt mittlerweile übrigens auch mit Linker, nur leider findet man 
wenn man Richtung "Clang Cortex M" googled zu viele alte Einträge in 
denen eben noch manuell via dem GNU Linker gearbeitet wird. Kann nun 
auch einwandfrei mit Clang compilieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vincent H. schrieb:

> Damit sollte sich wirklich niemand auseinander setzen müssen.
> Schrecklich.

Vieles davon kommt aber auch von diesem nano-Kram.  Ich mag den nicht
besonders und würde die nano-Bibliothek nur nutzen, wenn es platzmäßig
wirklich nicht anders geht.

> Kann nun
> auch einwandfrei mit Clang compilieren.

Falls es dafür noch irgendwelcher besonderer Optionen bedarf, wäre es
natürlich nett, wenn du das hier im Thread noch mit vermerkst, damit
andere ggf. davon profitieren können, wenn sie das über eine 
Suchmaschine
finden.

von Johannes S. (Gast)


Lesenswert?

wenn bei 1MB flash noch die nano lib nötig ist und man sich kein fp bei 
printf gönnenn kann muss das ja ein riesen Programm sein... Man sollte 
auch Bedenken das es für die Sparsamkeit Einschränkungen gibt, zB ist 
die nano lib nicht thread safe. Für einen Cortex-M0 benutze ich die 
auch, aber der hat nur 16 kB flash.
Mit -lto stehe ich aber auch auf Kriegsfuss, wenn ich das aktiviere wird 
der generierte Code oft grösser als ohne.

von Vincent H. (vinci)


Lesenswert?

Johannes S. schrieb:
> wenn bei 1MB flash noch die nano lib nötig ist und man sich kein fp bei
> printf gönnenn kann muss das ja ein riesen Programm sein... Man sollte
> auch Bedenken das es für die Sparsamkeit Einschränkungen gibt, zB ist
> die nano lib nicht thread safe. Für einen Cortex-M0 benutze ich die
> auch, aber der hat nur 16 kB flash.
> Mit -lto stehe ich aber auch auf Kriegsfuss, wenn ich das aktiviere wird
> der generierte Code oft grösser als ohne.

Der STM32F4 war nur ein Beispiel... Ich muss erstmal lernen vernünftig 
mit Make umzugehn bevor ich mich da auf ein echtes Projekt einschießen 
kann.

-flto ist für mich als C++ Template Süchtler ein Must-Have.

Bei Zeiten post ich eventuell mal das ganze Makefile und ein 
Testprojekt. Vor allem was modernes C++ im Embedded Bereich angeht gibts 
kaum Vergleiche zw. GCC und Clang.

von Johannes S. (Gast)


Lesenswert?

ok, das hört sich gut an, dann will ich nix gesagt haben.

von Wilhelm M. (wimalopaan)


Lesenswert?

Vincent H. schrieb:
> Johannes S. schrieb:
>> wenn bei 1MB flash noch die nano lib nötig ist und man sich kein fp bei
>> printf gönnenn kann muss das ja ein riesen Programm sein... Man sollte
>> auch Bedenken das es für die Sparsamkeit Einschränkungen gibt, zB ist
>> die nano lib nicht thread safe. Für einen Cortex-M0 benutze ich die
>> auch, aber der hat nur 16 kB flash.
>> Mit -lto stehe ich aber auch auf Kriegsfuss, wenn ich das aktiviere wird
>> der generierte Code oft grösser als ohne.
>
> Der STM32F4 war nur ein Beispiel... Ich muss erstmal lernen vernünftig
> mit Make umzugehn bevor ich mich da auf ein echtes Projekt einschießen
> kann.
>
> -flto ist für mich als C++ Template Süchtler ein Must-Have.

Warum? Schreib doch header-only, dann brauchst Du das doch gar nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vincent H. schrieb:
> -flto ist für mich als C++ Template Süchtler ein Must-Have.

Dann würde ich aber an deiner Stelle in der Tat auf nanolib und
Gefummel mit nicht-FP-printf verzichten.  Das Zeug macht's nicht
gerade übersichtlicher.

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.