Dienstag, 1. Oktober 2019

Wie funktioniert ein Cross-Compiler

Cross Compiling

Build -  Das System wo der Compiliervorgang stattfindet.

Host - Das System, auf welchem das Ergebnis der Compilierung lauffähig ist.

Target - Diejenigen Programme auf dem Host System, die selbst Cross-Compiler darstellen, bekommen mit diesem Argument ihr Zielsystem mitgeteilt, auf dem ihr Compilieroutput lauffähig sein soll.

Notizen:

https://www.gnu.org/software/autoconf/manual/autoconf-2.68/html_node/Hosts-and-Cross_002dCompilation.html#Hosts-and-Cross_002dCompilation

Die Defaults sind:
config.guess
    build
        host
            target

D.h. wenn target nicht definiert ist, dann basiert es auf host und wenn host seinerseits nicht definiert ist, dann basiert dies auf build. Und build wird per Heuristik Skript vom laufenden System abgeleitet.

Beispiele:

Das Ergebnis des Buildvorgangs kann Code sein, der auf dem Buildsystem selbst nicht lauffähig sein muss.
Unabhängig von der Lauffähigkeit auf dem Buildsystem nennt man Compiler dann Cross-Compiler, wenn diese Code erzeugen, deren Lauffähigkeit eine Andere ist als ihre Eigene.
Mit anderen Worten. Ein Cross-Compiler ist jeder erzeugte Compiler, dessen --host und --target System unterschiedlich war. Der Cross-Compiler kann, muss aber nicht, selbst auf dem Buildsystem lauffähig sein.

https://en.wikipedia.org/wiki/Cross_compiler

Beim Canadian Cross Compiler Erzeugungsverfahren gibt es folgende Kette:

1)
           cc --build == --host ;on machine A
gcc-source -> gcc (gcc-A-A)

2)
           gcc --build=A --host=A --target=B ;on machine A
gcc-source -> gcc-A-B

3)
            gcc-A-B --build=A --host=B --target=C ;on machine A
gcc-source -> gcc-B-C

4)
            gcc-B-C ;on machine B
any-code-c -> output-c.exe

5)
Man könnte statt der Schritt 2 + 3 auch folgendes machen:

           gcc --build=A --host=A --target=C ;on machine A
gcc-source -> gcc-A-C

und anschließend

6)
            gcc-A-C ;on machine A
any-code-c -> output-c.exe


Fragen:
Ist in 3) die Angabe von --host=B wirklich relevant? Ist denn ein gcc-A-B Compiler nicht fix auf Compilate für Machine B festgesetzt, so dass nur noch die --target Angabe damit zu erzeugender Compiler variabel sein kann? Wenn nicht, dann müßte ein gcc-A-B compiler durch --host=A und --target=C auch auf die Erzeugung eines auf A lauffähigen Crosscompilers für C Zielmaschinen einstellbar sein.


==============================================
Hinweise:

---------------------------------------------

Hier ein Beispiel für eine Crosscompilererzeugung, welches als --target auf --build verweist. D.h. ein Build-System erzeugt einen Crosscompiler mit sich als Zielsystem für eine fremde Hostplattform.

https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Hosts-and-Cross_002dCompilation.html#Hosts-and-Cross_002dCompilation
"
[...]
The following configure statement configures a cross toolchain that runs on NetBSD/alpha but generates code for GNU Hurd/sparc, which is also the build platform.
     ./configure --host=alpha-netbsd sparc-gnu
[...]   
"
--------------------------------------------

Erkenntnisse aus dem Debian Artikel zur Erstellung einer Tool Chain für eine Fremdarchitektur:

Hier ein Beispiel wie man einen Nicht Crosscompiler (und all seine Bestandteile)
für ein SH4 System erzeugt.
Dabei wird ein Crosscompiler für SH4 Zielcode benutzt um diesen Nicht-Crosscompiler (= Native Compiler) zu bauen.

https://wiki.debian.org/SH4/CrossToolchain

Schritte:

Auf dem Build System werden der Cross-Compiler und die libc-cross-sh4 installiert: gcc-4.1-sh4-linux-gnu , libc6-dev-sh4-cross.

Die Idee ist, mit Hilfe des Repository Cross-Compilers gcc-4.1-sh4-linux-gnu
einen Eigenen Cross-Compiler zu bauen. Und mit dem Eigenen wird dann ein Nativ
SH4 Toolchain gebaut.

Also:
1)Kompilieren des binutil-cross-sh4 mit gcc-4.1-sh4-linux-gnu aus dem Sourcecode für binutils.
2)Kompilieren des gcc-cross-sh4 mit normalem gcc, statt gcc-4.1-sh4-linux-gnu, aus dem Sourcecode für gcc. Denn benützte man gcc-4.1-sh4-linux-gnu, dann würde der erzeugte Compiler nur auf SH4 Systemen laufen können, stimmts?
Dabei wird die libc6-dev-sh4-cross benötigt, da der zu generierende gcc-cross-sh4 Compiler Funktionen der libc6-sh4 zu benutzen zu scheint.
3)Kompilieren der libc6-sh4 mit Hilfe des gcc-cross-sh4. Diese libc6-sh4 wird dann als xxx.deb Paket dpkg-cross -A -a sh4 -b xxx.deb auf dem Build Rechner installiert. Benötigt wird diese libc6-sh4 dann für Schritt 4.
4)Kompilieren des Nativ gcc-sh4 Compilers mit gcc-cross-sh4 und libc6-sh4.
Dieser Nicht Cross-Compiler ist für das ausführen auf einem SH4 System bestimmt.
5)Kompilieren der bin-utils-sh4 mit gcc-cross-sh4 aus dem binutil Source Code
6)Nicht erwähnt, aber: Eigentlich gehört der libc6-sh4, welcher in Schritt 3) erzeugt wurde vielleicht auch noch zu der nativ toolchain des SH4 Systems dazu. Also wird diese sowohl auf dem Buildsystem zur Erzeugung des Nativ gcc-sh4 Compilers als auch für das Target SH4 System bei der gcc-sh4 Compilerbenutzung benötigt und dementsprechend gespeichert.

-------------------------------------------------------------------------------
Revidierung der Erkenntnisse des Debian Artikel zur ...

1) Die binutils werden mit dem Target sh4-cross per makefile erzeugt. Dabei wird vermutlich der gcc-A-A compiler mit --host=A --target=sh4 benutzt

2) Es wird ein gcc-A-B-nonlibc compiler aus dem gcc Quellcode per gcc-A-A compiler --host=A --target=B erzeugt. Dabei werden die erstellten binutils-sh4-cross aus 1) in den gcc-A-B-nonlibc fest referenziert.

3) Mit dem gcc-A-B-nonlibc werden die libc Sourcen ins sh4 Zielsystem kompiliert. Es entsteht eine passive libc-sh4 Bibliothek. Frage: Ist es wirklich eine passive libc sh4 Bibliothek oder unterscheidet sie sich dann, wenn Sie von einem Cross-Compiler eingebunden wird. Wenn ja, dann wäre es kein passives Element per Se und man müsste unterscheiden in libc-sh4-cross und libc-sh4 Bibliotheken.

4) Es wird ein gcc-A-B-libc compiler aus dem gcc Quellcode per gcc-A-A compiler --host=A --target=B erzeugt. Dabei werden die erstellten binutils-sh4-cross aus 1) und die libc-sh4 aus 3) in den gcc-A-B-libc fest referenziert.

5) Es werden die binutils-sh4 mit dem gcc-A-B-libc compiler erzeugt.

6) Es wird die libc-sh4 mit dem gcc-A-B-libc compiler erzeugt.

7) Es wird der gcc-sh4 compiler mit dem gcc-A-B-libc compiler erzeugt.

8) Die Outputs 5-7 stellen die Nativ Toolchain für das Sh4 System dar, welche per Crosscompiler auf dem Host System ertsellt wurden.

9) Frage: Sollte es sich bei der libc-sh4 in Schritt 3 und 6 um das gleiche Kompilat handeln (Stichwort passiver Compilerbestandteil im Gegensatz zu den binutils), dann ist Schritt 6 unnötig und man kann einfach kopieren.

10) Die Zweifel und Hinweise in 3) und 9) beruhen auch auf dem Guide Kommentar, dass die libc-sh4 bereits als debian Paket installiert vorliegt und man sich den Schritt des Erzeugens des gcc-A-B-nonlibc ersparen kann. Durch das debian libc-sh4 könne man direkt den gcc-A-B-libc aus den gcc Quellen erstellen; implizit unter Verwendung des gcc-A-A --host=A --target=B mit Referenzierung von binutils-sh4 und libc-sh4. Diese meine implizite Vermutung beruht darauf, dass die Verwendung des debian Paket installierten gcc-sh4-cross-gcc compilers hierfür nicht einen lauffähigen eigene gcc-sh4-cross compiler erzeugen kann. Denn ein Cross-compiler ist ja deswegen ein Cross-compiler, weil sein Kompilat auf einer fremden Architektur nur lauffähig ist. Damit würde ein mit einem Cross-Compiler erzeugter Cross-Compiler nur auf einem anderen Wirtssystem einen lauffähigen Cross-Compiler darstellen.

----------------------------------------------------
Ergo unter Einbeziehung von www.preshing.com How to build a gcc Cross-Compiler

Schritte:

1) building cross binutils: sh4-ld, sh4-asm etc. mit make und --host=A --target=sh4 mittels gcc-A-A

2) install kernel headers for target sh4

3) building sh4-gcc-nolibc mit gcc sourcen unter Einsatz von gcc-A-A und --target=sh4. Durch Letzteres werden die cross-binutils aus 1) verwendet

4) glibc-sh4-startup und -header files als passiven (auch Cross-)Compiler Bestandteil aus den glibc Quellen unter Einsatz des sh4-gcc-nolibc erzeugen. Dabei sind --build=A, --host=sh4 und --target=sh4 gesetzt. Also ist ein Cross-libc-sh4 gleich einem libc-sh4.

5) sh4-gcc-nolibc-with-compiler-suport-libraries libgcc.a und libgcc_s.so durch Benutzung von sh4-gcc-nolibc unter Einbeziehung der in 4) erzeugten Dateien erstellen als weiteren Bestandteil für den zukünftigen endgültigen sh4-gcc-libc compiler. An der Benutzung von sh4-gcc-nolibc statt gcc-A-A für die Erstellung der libgcc.a und libgcc_s.so erkennt man, dass auch diese libraries passive Bestandteile des zukünftigen Cross-Compilers sind und daher nicht auf dem Host System lauffähig sein müssen.

6) Endgültige glibc-sh4 Library erzeugen unter Einsatz des sh4-gcc-nolibc zusammen mit libgcc.a und libgcc_s.so aus 5). 

7) Unter Verwendung des gcc makefiles wird durch Benutzung des gcc-A-A --target=sh4 und Verwendung der glibc-sh4 Bibliothek aus 6) der sh4-gcc (= sh4-gcc-withlibc) fertiggestellt. Dabei wird zusätzlich auch noch der passive Compilerbestandteil der sh4-c++-libs (static und shared Biblios) für den Cross-Compiler sh4-g++ erstellt.

8) Zum Schluss sind alle Cross-Compiler Bestandteile in /opt/cross/sh4/ mit ausfühbaren Dateien im Unterordner bin untergebracht. Die Crosscompiler haben alle den sh4- Präfix vor dem eigentlichen Namen und ihr system root zeigt auf /opt/cross/sh4-linux . In diesem system root liegen zum Beispiel in opt/cross/sh4-linux/bin/ hardlinks ohne Präfix Notation der Werkzeuge, die auf die Präfixed Varianten in opt/cross/bin zeigen.

================================================
Szenarien:

A)
Spezifikation:
    Ausgangsrechner ist x86_64 System. Es wird ein Crosscompiler für 32bit Arm Code benötigt. Der Compiler soll auf dem Ausgangsrechner x86_64 ausgeführt werden.

Ergebnis: Crosscompiler läuft auf Build-System: x86_64 -> arm-32
Build - x86_64 , Host - x86_64 , Target arm-32

B)
Spezifikation:
    Wie A) aber der Compiler soll auf Motorolla 32bit CPU ausgeführt werden

Ergebnis: Crosscompiler läuft auf Host-System: 68000_32 -> arm-32
Build - x86_64 , Host - 68000_32 , Target arm-32

C)
Spezifikation:
    Wie A) aber der Compiler soll auf arm 32bit CPU ausgeführt werden.

Ergebnis: (kein Cross) Compiler läuft auf Host: arm-32 -> arm-32
Build - x86_64 , Host - arm-32 (, impliziert Target = Host )


     

Keine Kommentare:

Kommentar veröffentlichen