Compilatore incrociato - Cross compiler

Un compilatore incrociato è un compilatore in grado di creare codice eseguibile per una piattaforma diversa da quella su cui è in esecuzione il compilatore. Ad esempio, un compilatore che viene eseguito su un PC ma genera codice che viene eseguito su uno smartphone Android è un compilatore incrociato.

È necessario un compilatore incrociato per compilare il codice per più piattaforme da un host di sviluppo. La compilazione diretta sulla piattaforma di destinazione potrebbe non essere fattibile, ad esempio su sistemi embedded con risorse di calcolo limitate.

I compilatori incrociati sono distinti dai compilatori da sorgente a sorgente . Un compilatore incrociato serve per la generazione di software multipiattaforma di codice macchina, mentre un compilatore da sorgente a sorgente traduce da un linguaggio di programmazione a un altro in codice di testo. Entrambi sono strumenti di programmazione .

Utilizzo

L'uso fondamentale di un compilatore incrociato consiste nel separare l'ambiente di compilazione dall'ambiente di destinazione. Questo è utile in diverse situazioni:

  • Computer incorporati in cui un dispositivo dispone di risorse estremamente limitate. Ad esempio, un forno a microonde avrà un computer estremamente piccolo per leggere la tastiera e il sensore della porta, fornire l'output a un display digitale e un altoparlante e controllare i macchinari per la cottura degli alimenti. Questo computer generalmente non è abbastanza potente per eseguire un compilatore, un file system o un ambiente di sviluppo.
  • Compilazione per più macchine. Ad esempio, un'azienda potrebbe voler supportare diverse versioni di un sistema operativo o supportare diversi sistemi operativi. Utilizzando un compilatore incrociato, è possibile impostare un singolo ambiente di compilazione per compilare per ciascuna di queste destinazioni.
  • Compilazione su una server farm . Simile alla compilazione per più macchine, una build complicata che implica molte operazioni di compilazione può essere eseguita su qualsiasi macchina libera, indipendentemente dall'hardware sottostante o dalla versione del sistema operativo in esecuzione.
  • Bootstrap su una nuova piattaforma. Quando si sviluppa software per una nuova piattaforma, o l'emulatore di una piattaforma futura, si usa un compilatore incrociato per compilare gli strumenti necessari come il sistema operativo e un compilatore nativo.
  • Compilazione di codice nativo per emulatori per piattaforme ormai obsolete come il Commodore 64 o Apple II da parte di appassionati che utilizzano compilatori incrociati eseguiti su una piattaforma corrente (come i compilatori incrociati MS-DOS 6502 di Aztec C in esecuzione su Windows XP ).

L'uso di macchine virtuali (come JVM di Java ) risolve alcuni dei motivi per cui sono stati sviluppati i compilatori incrociati. Il paradigma della macchina virtuale consente di utilizzare lo stesso output del compilatore su più sistemi di destinazione, sebbene ciò non sia sempre l'ideale perché le macchine virtuali sono spesso più lente e il programma compilato può essere eseguito solo su computer con quella macchina virtuale.

Tipicamente l' architettura hardware differisce (es. compilare un programma destinato all'architettura MIPS su un computer x86 ) ma la cross-compilazione è applicabile anche quando differisce solo l' ambiente del sistema operativo , come quando si compila un programma FreeBSD sotto Linux , o anche solo la libreria di sistema , come quando si compilano programmi con uClibc su un host glibc .

Croce canadese

La Canadian Cross è una tecnica per costruire compilatori incrociati per altre macchine. Date tre macchine A, B e C, si usa la macchina A (es. eseguendo Windows XP su un processore IA-32 ) per costruire un compilatore incrociato che gira sulla macchina B (es. eseguendo Mac OS X su un processore x86-64 ) per creare eseguibili per la macchina C (ad es. eseguendo Android su un processore ARM ). Quando si utilizza la Canadian Cross con GCC, potrebbero essere coinvolti quattro compilatori

  • Il compilatore nativo proprietario per la macchina A (1) (ad esempio il compilatore di Microsoft Visual Studio ) viene utilizzato per compilare il compilatore nativo gcc per la macchina A (2) .
  • Il compilatore nativo gcc per la macchina A (2) viene utilizzato per compilare il compilatore incrociato gcc dalla macchina A alla macchina B (3)
  • Il cross compiler gcc dalla macchina A alla macchina B (3) è usato per costruire il cross compiler gcc dalla macchina B alla macchina C (4)

Esempio di croce canadese, schema

Il compilatore incrociato del risultato finale (4) non sarà in grado di essere eseguito sulla macchina di compilazione A; invece verrebbe eseguito sulla macchina B per compilare un'applicazione in codice eseguibile che verrebbe quindi copiato sulla macchina C ed eseguito sulla macchina C.

Per esempio, NetBSD fornisce uno script di shell POSIX Unix chiamato build.shche prima creerà la propria toolchain con il compilatore dell'host; questo, a sua volta, sarà usato per costruire il compilatore incrociato che sarà usato per costruire l'intero sistema.

Il termine Canadian Cross è nato perché all'epoca in cui questi problemi erano in discussione, il Canada aveva tre partiti politici nazionali.

Cronologia dei primi compilatori incrociati

  • 1979 – ALGOL 68C genera ZCODE ; questo ha aiutato a portare il compilatore e altre applicazioni ALGOL 68 su piattaforme alternative. Per compilare il compilatore ALGOL 68C sono necessari circa 120 KB di memoria. Con Z80 la sua memoria da 64 KB è troppo piccola per compilare effettivamente il compilatore. Quindi, per lo Z80, il compilatore stesso doveva essere compilato in modo incrociato dal computer con capacità CAP più grande o da un mainframe IBM System/370 .

GCC e compilazione incrociata

GCC , una raccolta software gratuita di compilatori, può essere impostata per la compilazione incrociata. Supporta molte piattaforme e lingue.

GCC richiede che sia disponibile una copia compilata di binutils per ogni piattaforma di destinazione. Particolarmente importante è l' Assembler GNU . Pertanto, binutils deve prima essere compilato correttamente con lo switch --target=some-targetinviato allo script configure . Anche GCC deve essere configurato con la stessa --targetopzione. GCC può quindi essere eseguito normalmente a condizione che gli strumenti creati da binutils siano disponibili nel percorso , che può essere eseguito utilizzando quanto segue (su sistemi operativi simili a UNIX con bash):

PATH=/path/to/binutils/bin:${PATH} make

Cross-compilazione GCC richiede che una parte della piattaforma di destinazione' s libreria standard C sarà disponibile sul piattaforma host . Il programmatore può scegliere di compilare l'intera libreria C, ma questa scelta potrebbe essere inaffidabile. L'alternativa è usare newlib , che è una piccola libreria C contenente solo i componenti più essenziali necessari per compilare il codice sorgente C.

I pacchetti GNU autotools (cioè autoconf , automake e libtool ) usano la nozione di piattaforma di compilazione , piattaforma host e piattaforma di destinazione . La piattaforma di compilazione è dove viene effettivamente compilato il compilatore. Nella maggior parte dei casi, build dovrebbe essere lasciata indefinita (verrà predefinita dall'host). La piattaforma host è sempre il luogo in cui verranno eseguiti gli artefatti di output dal compilatore, indipendentemente dal fatto che l'output sia un altro compilatore o meno. La piattaforma di destinazione viene utilizzata durante la compilazione incrociata dei compilatori incrociati, rappresenta il tipo di codice oggetto che il pacchetto stesso produrrà; in caso contrario, l' impostazione della piattaforma di destinazione è irrilevante. Ad esempio, considera la compilazione incrociata di un videogioco che verrà eseguito su un Dreamcast . La macchina in cui viene compilato il gioco è la piattaforma di costruzione mentre il Dreamcast è la piattaforma host . I nomi host e target sono relativi al compilatore utilizzato e spostati come son e grandson .

Un altro metodo comunemente usato dagli sviluppatori di Linux embedded comporta la combinazione di compilatori GCC con sandbox specializzati come Scratchbox , scratchbox2 o Proot . Questi strumenti creano una sandbox " chrooted " in cui il programmatore può creare strumenti, libc e librerie necessari senza dover impostare percorsi aggiuntivi. Sono inoltre fornite funzionalità per "ingannare" il runtime in modo che "creda" di essere effettivamente in esecuzione sulla CPU di destinazione prevista (come un'architettura ARM); questo consente agli script di configurazione e simili di essere eseguiti senza errori. Scratchbox viene eseguito più lentamente rispetto ai metodi "non chroot" e la maggior parte degli strumenti che si trovano sull'host devono essere spostati in Scratchbox per funzionare.

Compilatori incrociati Manx Aztec C

Manx Software Systems , di Shrewsbury , New Jersey , ha prodotto compilatori C a partire dagli anni '80 destinati a sviluppatori professionisti per una varietà di piattaforme fino a PC e Mac inclusi .

Il linguaggio di programmazione Aztec C di Manx era disponibile per una varietà di piattaforme tra cui MS-DOS , Apple II , DOS 3.3 e ProDOS , Commodore 64 , Macintosh 68XXX e Amiga .

Dagli anni '80 e continuando per tutti gli anni '90 fino alla scomparsa di Manx Software Systems, la versione MS-DOS di Aztec C è stata offerta sia come compilatore in modalità nativa che come compilatore incrociato per altre piattaforme con processori diversi tra cui il Commodore 64 e l'Apple II. Esistono ancora distribuzioni Internet per Aztec C, inclusi i loro compilatori incrociati basati su MS-DOS. Sono ancora in uso oggi.

Aztec C86 di Manx, il loro compilatore MS-DOS 8086 in modalità nativa , era anche un compilatore incrociato. Sebbene non compilasse codice per un processore diverso come i loro compilatori incrociati Aztec C65 6502 per Commodore 64 e Apple II, creava eseguibili binari per sistemi operativi allora legacy per la famiglia di processori 8086 a 16 bit.

Quando il PC IBM fu introdotto per la prima volta, era disponibile con una scelta di sistemi operativi, CP/M-86 e PC DOS erano due di questi. Aztec C86 è stato dotato di librerie di collegamento per la generazione di codice per entrambi i sistemi operativi per PC IBM . Durante gli anni '80 le versioni successive di Aztec C86 (3.xx, 4.xx e 5.xx) hanno aggiunto il supporto per le versioni "transitorie" di MS-DOS 1 e 2 e che erano meno robuste della versione 3 e 3 di MS-DOS "di base". più tardi che Aztec C86 ha preso di mira fino alla sua scomparsa.

Infine, Aztec C86 disponibile sviluppatori linguaggio C con la capacità di produrre ROM-grado "HEX" codice che potrebbe poi essere trasferita usando un bruciatore ROM direttamente a un processore in base 8086. La paravirtualizzazione può essere più comune oggi, ma la pratica della creazione di codice ROM di basso livello era più comune pro-capite durante quegli anni in cui lo sviluppo dei driver di dispositivo veniva spesso eseguito da programmatori di applicazioni per singole applicazioni e i nuovi dispositivi equivalevano a un'attività artigianale . Non era raro che i programmatori di applicazioni si interfacciassero direttamente con l'hardware senza il supporto del produttore. Questa pratica era simile all'odierno sviluppo di sistemi integrati .

Thomas Fenwick e James Goodnow II sono stati i due principali sviluppatori di Aztec-C. Fenwick in seguito divenne famoso come l'autore del kernel Microsoft Windows CE o NK ("Nuovo Kernel") come veniva chiamato allora.

Compilatori incrociati Microsoft C

Storia antica - anni '80

Microsoft C (MSC) ha una storia più breve rispetto ad altri risalenti agli anni '80. I primi compilatori Microsoft C sono stati realizzati dalla stessa azienda che ha creato Lattice C e sono stati rinominati da Microsoft come propri, fino al rilascio di MSC 4, che è stata la prima versione prodotta da Microsoft.

Nel 1987, molti sviluppatori iniziarono a passare a Microsoft C e molti altri seguirono durante lo sviluppo di Microsoft Windows fino al suo stato attuale. Sono emersi prodotti come Clipper e successivamente Clarion che offrivano un facile sviluppo di applicazioni di database utilizzando tecniche multilingua, consentendo la compilazione di parte dei loro programmi con Microsoft C.

Borland C (società californiana) era disponibile per l'acquisto anni prima che Microsoft rilasciasse il suo primo prodotto C.

Molto prima di Borland, BSD Unix (Berkeley University) aveva ottenuto il C dagli autori del linguaggio C: Kernighan e Ritchie che lo scrissero all'unisono mentre lavoravano per AT&T (laboratori). Le esigenze originali di K&R non erano solo l'elegante sintassi parsed di secondo livello per sostituire la sintassi parsed di asm di primo livello: era stata progettata in modo che fosse scritta una quantità minima di asm per supportare ogni piattaforma (il design originale del C era la capacità di compilare in modo incrociato usando C con il codice di supporto minimo per piattaforma, di cui avevano bisogno.). Anche il C di ieri era direttamente correlato al codice ASM ovunque non dipendesse dalla piattaforma. Il C di oggi (o più c++) non è più compatibile con il C e il codice asm sottostante può essere estremamente diverso da quello scritto su una determinata piattaforma (in Linux: a volte sostituisce e devia le chiamate di libreria con le scelte del distributore). Il C di oggi è un linguaggio di 3° o 4° livello che viene usato alla vecchia maniera come un linguaggio di 2° livello.

1987

I programmi C erano stati a lungo collegati a moduli scritti in linguaggio assembly . La maggior parte dei compilatori C (anche i compilatori attuali) offrono un passaggio per il linguaggio assembly (che può essere ottimizzato per l'efficienza e quindi collegato al resto del programma dopo l'assemblaggio).

I compilatori come Aztec-C convertivano tutto in linguaggio assembly come un passaggio distinto e poi assemblavano il codice in un passaggio distinto, e si distinguevano per il loro codice molto efficiente e piccolo, ma nel 1987 l'ottimizzatore integrato in Microsoft C era molto buono, e solo Le parti "mission critical" di un programma venivano solitamente prese in considerazione per la riscrittura. In effetti, la programmazione in linguaggio C aveva assunto il ruolo di linguaggio di "livello più basso", con la programmazione che diventava un settore in crescita multidisciplinare e progetti che diventavano più grandi, con i programmatori che scrivevano interfacce utente e interfacce di database in linguaggi di livello superiore, e un bisogno aveva è emerso per lo sviluppo linguistico incrociato che continua fino ad oggi.

Nel 1987, con il rilascio di MSC 5.1, Microsoft ha offerto un ambiente di sviluppo multilingua per MS-DOS. Codice oggetto binario a 16 bit scritto in linguaggio assembly ( MASM ) e altri linguaggi Microsoft tra cui QuickBASIC , Pascal e Fortran potrebbero essere collegati insieme in un programma, in un processo chiamato "Programmazione in linguaggio misto" e ora "Chiamata interlingua". Se BASIC è stato utilizzato in questo mix, il programma principale doveva essere in BASIC per supportare il sistema runtime interno che ha compilato il BASIC richiesto per la garbage collection e le sue altre operazioni gestite che simulavano un interprete BASIC come QBasic in MS-DOS.

La convenzione di chiamata per il codice C, in particolare, consisteva nel passare i parametri in "ordine inverso" sullo stack e restituire i valori nello stack anziché in un registro del processore . C'erano altre regole di programmazione per far funzionare tutti i linguaggi insieme, ma questa particolare regola è rimasta attraverso lo sviluppo multilingua che è continuato nelle versioni di Windows a 16 e 32 bit e nello sviluppo di programmi per OS/2 , e che persiste fino a questo giorno. È nota come convenzione di chiamata Pascal .

Un altro tipo di compilazione incrociata per cui Microsoft C è stato utilizzato durante questo periodo è stato nelle applicazioni al dettaglio che richiedono dispositivi palmari come il Symbol Technologies PDT3100 (utilizzato per fare l' inventario ), che forniva una libreria di collegamenti mirata a un lettore di codici a barre basato su 8088 . L'applicazione è stata costruita sul computer host poi trasferita al dispositivo palmare (tramite un cavo seriale ) dove è stata eseguita, in modo simile a quanto viene fatto oggi per quello stesso mercato utilizzando Windows Mobile da aziende come Motorola , che ha acquistato Symbol.

Primi anni '90

Per tutti gli anni '90 ea partire da MSC 6 (il loro primo compilatore compatibile con ANSI C ) Microsoft ha riorientato i propri compilatori C sul mercato emergente di Windows, e anche su OS/2 e nello sviluppo di programmi GUI . La compatibilità con le lingue miste è rimasta tramite MSC 6 sul lato MS-DOS, ma l' API per Microsoft Windows 3.0 e 3.1 è stata scritta in MSC 6. MSC 6 è stato anche esteso per fornire supporto per assembly a 32 bit e supporto per l'emergente Windows for Workgroups e Windows NT che costituirebbe la base per Windows XP . È stata introdotta una pratica di programmazione chiamata thunk per consentire il passaggio tra programmi a 16 e 32 bit che sfruttavano l'associazione di runtime ( collegamento dinamico ) anziché l' associazione statica preferita nelle applicazioni MS-DOS monolitiche a 16 bit. Il binding statico è ancora preferito da alcuni sviluppatori di codice nativo, ma generalmente non fornisce il grado di riutilizzo del codice richiesto dalle migliori pratiche più recenti come il Capability Maturity Model (CMM).

Il supporto per MS-DOS era ancora fornito con il rilascio del primo compilatore C++ di Microsoft, MSC 7, che era retrocompatibile con il linguaggio di programmazione C e MS-DOS e supportava la generazione di codice sia a 16 che a 32 bit.

MSC ha ripreso da dove l' Aztec C86 aveva lasciato. La quota di mercato per i compilatori C si era rivolta ai compilatori incrociati che sfruttavano le più recenti e migliori funzionalità di Windows, offrivano C e C++ in un unico pacchetto e supportavano ancora i sistemi MS-DOS che avevano già un decennio, e le aziende più piccole che compilatori prodotti come Aztec C non potevano più competere e si sono rivolti a mercati di nicchia come i sistemi embedded o sono scomparsi.

Il supporto per MS-DOS e la generazione di codice a 16 bit è continuato fino a MSC 8.00c, che è stato fornito in bundle con Microsoft C++ e Microsoft Application Studio 1.5, il precursore di Microsoft Visual Studio, che è l'ambiente di sviluppo incrociato fornito da Microsoft oggi.

Fine anni '90

MSC 12 è stato rilasciato con Microsoft Visual Studio 6 e non ha più fornito supporto per i binari MS-DOS a 16 bit, fornendo invece supporto per applicazioni console a 32 bit, ma ha fornito supporto per la generazione di codice Windows 95 e Windows 98 , nonché per Windows NT . Le librerie di collegamento erano disponibili per altri processori che eseguivano Microsoft Windows; una pratica che Microsoft continua ancora oggi.

MSC 13 è stato rilasciato con Visual Studio 2003 e MSC 14 è stato rilasciato con Visual Studio 2005 , entrambi i quali producono ancora codice per sistemi meno recenti come Windows 95, ma produrranno codice per diverse piattaforme target, tra cui il mercato mobile e l' architettura ARM .

.NET e oltre

Nel 2001 Microsoft ha sviluppato Common Language Runtime (CLR), che ha costituito il nucleo del compilatore .NET Framework nell'IDE di Visual Studio. Questo livello sul sistema operativo che si trova nell'API consente la combinazione di linguaggi di sviluppo compilati su piattaforme che eseguono il sistema operativo Windows.

Il runtime di .NET Framework e CLR forniscono un livello di mapping alle routine principali per il processore e i dispositivi nel computer di destinazione. Il compilatore C da riga di comando in Visual Studio compilerà il codice nativo per una varietà di processori e può essere usato per creare le routine principali.

Le applicazioni Microsoft .NET per piattaforme di destinazione come Windows Mobile sull'architettura ARM vengono compilate in modo incrociato su macchine Windows con una varietà di processori e Microsoft offre anche emulatori e ambienti di distribuzione remota che richiedono pochissima configurazione, a differenza dei compilatori incrociati dei tempi passati altre piattaforme.

Le librerie di runtime, come Mono , forniscono compatibilità per programmi .NET cross-compilati con altri sistemi operativi, come Linux .

Librerie come Qt e i suoi predecessori, incluso XVT, forniscono capacità di sviluppo incrociato a livello di codice sorgente con altre piattaforme, pur utilizzando Microsoft C per creare le versioni di Windows. Anche altri compilatori come MinGW sono diventati popolari in quest'area poiché sono più direttamente compatibili con gli Unix che comprendono il lato non Windows dello sviluppo software, consentendo a quegli sviluppatori di indirizzare tutte le piattaforme utilizzando un ambiente di compilazione familiare.

Pascal gratis

Free Pascal è stato sviluppato fin dall'inizio come compilatore incrociato. L'eseguibile del compilatore (ppcXXX dove XXX è un'architettura di destinazione) è in grado di produrre eseguibili (o solo file oggetto se non esiste un linker interno, o anche solo file assembly se non esiste un assembler interno) per tutti i sistemi operativi della stessa architettura. Ad esempio, ppc386 è in grado di produrre eseguibili per i386-linux, i386-win32, i386-go32v2 (DOS) e tutti gli altri sistemi operativi (vedi ). Per la compilazione in un'altra architettura, tuttavia, è necessario creare prima una versione multiarchitettura del compilatore. L'eseguibile del compilatore risultante avrebbe "ross" aggiuntivo prima dell'architettura di destinazione nel suo nome. cioè se il compilatore è costruito per indirizzare x64, allora l'eseguibile sarebbe ppcrossx64.

Per compilare per un'architettura-OS scelta, è possibile utilizzare l'opzione del compilatore (per il driver del compilatore fpc) -P e -T. Questa operazione viene eseguita anche durante la compilazione incrociata del compilatore stesso, ma viene impostata tramite l'opzione make CPU_TARGET e OS_TARGET. L'assemblatore GNU e il linker per la piattaforma di destinazione sono necessari se Free Pascal non dispone ancora di una versione interna degli strumenti per la piattaforma di destinazione.

clangore

Clang è nativamente un compilatore incrociato, in fase di compilazione puoi selezionare quali architetture vuoi che Clang sia in grado di indirizzare.

Guarda anche

Riferimenti

link esterno