2012-01-31 14 views
23

Ho letto della proposta di moduli C++ (latest draft) ma non capisco perfettamente quale/i problema/i si intende risolvere.C++ Modules e C++ ABI

Il suo scopo è quello di consentire a un modulo compilato da un compilatore di essere utilizzato da qualsiasi altro compilatore (sullo stesso OS/architettura, ovviamente)? Cioè, la proposta equivale a standardizzare l'ABI C++?

In caso contrario, è prevista un'altra proposta che standardizzerebbe l'ABI C++ e consentirà ai compilatori di interoperare?

risposta

31

Le intestazioni precompilate (PCH) sono file speciali che alcuni compilatori possono generare per un file .cpp. Quello che sono è esattamente questo: codice sorgente precompilato. Sono codice sorgente che è stato alimentato tramite il compilatore e incorporato in un formato dipendente dal compilatore.

I PCH vengono comunemente utilizzati per velocizzare la compilazione. Inserisci le intestazioni comunemente utilizzate nel PCH, quindi includi solo il PCH. Quando fai un #include sul PCH, il tuo compilatore in realtà non fa il solito #include lavoro. Carica invece questi simboli precompilati direttamente nel compilatore. Non è in esecuzione un preprocessore C++. Non eseguire un compilatore C++. No # include un milione di file diversi. Un file viene caricato e simboli appaiono completamente formata direttamente nell'area di lavoro del compilatore.

Menziono tutto questo perché i moduli sono PCHS nella loro perfetta forma. I PCH sono fondamentalmente un hack gigante costruito su un sistema che non consente moduli reali. Lo scopo dei moduli è in ultima analisi essere in grado di prendere un file, generare un file di modulo specifico del compilatore che contiene simboli, e poi qualche altro file carica quel modulo secondo necessità. I simboli sono precompilati, quindi, di nuovo, non c'è bisogno di includere un po 'di cose, eseguire un compilatore, ecc. Il tuo codice dice, import thing.foo, e appare.

Controllare qualsiasi intestazione di libreria standard derivata da STL. Prendete <map> per esempio. Le probabilità sono buone che questo file sia gigantesco o abbia molte #inclusioni di altri file che rendono il file risultante gigantesco. Questo è un sacco di parsing in C++ che deve accadere. Deve succedere per ogni file .cpp che contiene #include <map>. Ogni volta che compili un file sorgente, il compilatore deve ricompilare la stessa cosa. Al di sopra di. E oltre. E ancora.

<map> cambia tra le compilation? No, ma il tuo compilatore non può saperlo. Quindi deve continuare a ricompilarlo.Ogni volta che tocchi un file .cpp, deve compilare ogni intestazione che include questo file .cpp. Anche se non hai toccato le intestazioni o i file di origine che interessano quelle intestazioni.

I file PCH erano un modo per ovviare a questo problema. Ma sono limitati, perché sono solo un hack. Puoi includerne solo uno per ogni file .cpp, perché deve essere la prima cosa inclusa nei file .cpp. E poiché c'è un solo PCH, se si fa qualcosa che cambia il PCH (come aggiungere una nuova intestazione ad esso), è necessario ricompilare di tutto in quel PCH.

I moduli non hanno sostanzialmente nulla a che fare con il cross-compiler ABI (anche se uno di questi sarebbe bello, ei moduli renderebbero un po 'più facile definirne uno). Il loro scopo fondamentale è accelerare i tempi di compilazione.

+1

Lo scopo fondamentale va oltre la semplice accelerazione dei tempi di compilazione .....: D –

10

I moduli sono ciò che Java, C# e molti altri linguaggi moderni offrono. Riducono immensamente il tempo di compilazione semplicemente perché il codice contenuto nell'intestazione di oggi non deve essere analizzato più e più volte, ogni volta che viene incluso. Quando dici #include <vector>, il contenuto di <vector> verrà copiato nel file corrente. #include non è altro che copia e incolla.

Nel mondo del modulo, ad esempio, si dice semplicemente import std.vector; e il compilatore carica la tabella query/simbolo di quel modulo. Il file di modulo ha un formato che rende facile per il compilatore per analizzare e usarlo. Viene anche analizzato solo una volta, quando il modulo è compilato. Successivamente, il file del modulo generato dal compilatore viene appena interrogato per le informazioni necessarie.

Poiché i file di modulo sono generato dal compilatore, saranno abbastanza strettamente legata alla rappresentazione interna del compilatore del codice C++ (AST) e avrà come tale molto probabilmente non essere portatili (proprio come .o/.so/.a file di oggi , a causa del nome mangling ecc.).

7

I moduli in C++ devono essere principalmente una soluzione migliore rispetto alle soluzioni odierne, ovvero quando una libreria è costituita da un file * .so e un file * .h con API. Devono risolvere i problemi che sono oggi con #includes, cioè:

  • richiedono macroguards (macro che impediscono che le definizioni sono forniti più volte)
  • sono rigorosamente basata su testo (in modo che possano essere ingannati e in condizioni normali vengono reinterpretati, il che dà anche la possibilità di apparire in modo diverso in diverse unità di compilazione per essere collegati tra loro)
  • non distinguere tra le librerie dipendenti utilizzate solo strumentalmente e derivate da (in particolare se l'intestazione fornisce funzione inline modelli)

Nonostante ciò che dice Xeo, i moduli non esistono in Java o C#. Infatti, in questi linguaggi "moduli di caricamento" si basa su questo "ok, qui hai il CLASSPATH e cerca attraverso di esso per trovare qualsiasi modulo possa fornire simboli che il file sorgente effettivamente utilizza". La dichiarazione "import" in Java non è affatto una "richiesta di modulo" - lo stesso di "using" in C++ ("import ns.ns2. *" In Java è uguale a "using namespace ns: ns2" in C++) . Non penso che una tale soluzione possa essere usata in C++. L'approssimazione più vicina che posso immaginare sono i pacchetti in Vala o moduli in Tcl (quelli dalla versione 8.5).

Immagino che i moduli C++ non siano possibili per essere multipiattaforma, né caricati dinamicamente (richiede un caricatore di moduli dinamici C++ dedicato - non è impossibile, ma oggi difficile da definire). Sicuramente dipenderanno dalla piattaforma e dovrebbero anche essere configurabili quando richiesto. Ma un ABI C++ stabile è praticamente richiesto solo all'interno del raggio di un sistema, proprio come è ora con ABI C++.