2016-06-03 42 views
11

PrecompiledHeader.h:Come fare clang -E omettere di intestazione precompilata

#include "stdio.h" 

main.cpp:

#include "PrecompiledHeader.h" 
#include "stdio.h" 

int main() 
{ 
    return 123; 
} 

Creazione di intestazione precompilata:

clang -x c++-header PrecompiledHeader.h -o PrecompiledHeader.pch 

esecuzione clangore preprocessore sul principale .cpp:

clang main.cpp -include-pch PrecompiledHeader.pch -E 

Attualmente restituisce molte molte pagine di output (stdio.h). Tuttavia, ciò che vorrei ottenere è solo la funzione principale e il contenuto di PrecompiledHeader.h deve essere omesso dall'output.

C'è un modo per fare clang fare questo? (se qualcuno conosce la risposta alla stessa domanda per il cl.exe di visualstudio, mi piacerebbe saperlo anche io :)

+0

"Mi piacerebbe ottenere è solo la funzione principale e il contenuto di PrecompiledHeader.h deve essere omesso dall'output." Questo non è chiaro. Se ometti (solo) il contenuto di 'PrecompiledHeader.h', otterrai la funzione principale * più * il contenuto di' stdio.h'. –

risposta

4

Difficilmente esiste o verrà incorporato in clang (o qualsiasi altro compilatore C++) nel futuro. Il problema è che le intestazioni precompilate vengono utilizzate per accelerare la fase di compilazione che di solito è significativamente più costosa della fase di pre-elaborazione. Di conseguenza, se hai intenzione di pre-processare la tua fonte, l'intestazione precompilata semplicemente non verrà utilizzata. Un modo che ha una trascurabile probabilità di produrre ciò che si vuole è quello di utilizzare l'opzione anziché l'opzione -include-pch-include (si noti che è necessario specificare il *.h piuttosto che il file *.pch ad esso):

clang main.cpp -include PrecompiledHeader.h -E 

La garantito modo di risolvere il problema è quello di inviare l'output pre-elaborato attraverso un semplice programma di filtro che guarda alle # line "file" direttive e rimuove il testo proveniente dal file #include eD:

clang main.cpp -E|remove_included_code 

remove_included_code può essere facilmente ESECUZIONE nted in python, bash, C/C++, ecc Ecco un'implementazione C++ (C++ è stato scelto in modo che possa essere più facilmente utilizzato in Windows):

remove_included_code.cpp

#include <iostream> 
#include <cstdlib> 

using namespace std; 
typedef std::string Str; 

bool isLineDirective(const Str& line) 
{ 
    return line.size() >= 3 
     && line[0] == '#' 
     && line[1] == ' ' 
     && isdigit(line[2]); 
} 

Str getFile(const Str& line) 
{ 
    const Str::size_type start = line.find_first_of('"') + 1; 
    const Str::size_type end = line.find_first_of('"', start); 
    return line.substr(start, end - start); 
} 

int main() 
{ 
    Str line; 
    getline(cin, line); 
    if (!isLineDirective(line)) { 
     cerr << "Error: Input must start with a '# line \"file\"' directive\n"; 
     exit(1); 
    } 

    const Str startFile = getFile(line); 
    Str currentFile = startFile; 
    while (getline(cin, line)) { 
     if (isLineDirective(line)) 
      currentFile = getFile(line); 
     else if (currentFile == startFile) 
      cout << line << endl; 
    } 

    return 0; 
} 

Il il vantaggio di questa soluzione è che funzionerà con tutti i compilatori.

+1

Di tutte le lingue hai scelto cpp per remove_included_code? – Dani

+1

@Dani L'ho fatto per un motivo. Sebbene in effetti non sia assolutamente la lingua migliore per l'elaborazione del testo, un semplice programma scritto in C++ ha il vantaggio di richiedere meno dipendenze per l'esecuzione. Questo è importante, se OP ha bisogno di eseguirlo sotto Windows, dove python e bash non sono cittadini di prima classe. – Leon

1

modifica: Non vedo niente di speciale sulle intestazioni precompilate in questo caso - qualsiasi metodo di impedire condizionalmente l'espansione di un #include lo farà.

Io ottengo questo per l'intestazione standard include il wrapping in un ifdef, in modo che l'output preelaborato contenga # include "foo" ma non il contenuto. Ad esempio,

#ifdef PRECOMPILE 
#define TMP #include <stdio.h> 
TMP 
#undef TMP 
#else 
#include <stdio.h> 
#endif 

Quindi passare -DPRECOMPILE con -E.

L'output preelaborato contiene quindi l'inclusione # non espansa. Trovo questo più utile rispetto alla più semplice alternativa di avvolgere #include in #ifdef durante la lettura dell'output preelaborato.

Principalmente, questo significa che posso eseguire codice macro-pesante attraverso il preprocessore e poi clang-format prima di compilare normalmente, per un'esperienza di debug molto migliorata.