2016-06-03 5 views
11

PrecompiledHeader.h:Как сделать лязг -E Опустить прекомпилирована Заголовок

#include "stdio.h" 

main.cpp:

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

int main() 
{ 
    return 123; 
} 

Создание предкомпилированного заголовка:

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

Запуск лязг препроцессор на главной .cpp:

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

В настоящее время выдается много много страниц вывода (stdio.h). Однако то, что я хотел бы получить, является только основной функцией, и содержимое PrecompiledHeader.h будет опущено из вывода.

Есть ли способ сделать clang сделать это? (если кто-то знает ответ на тот же вопрос для cl.exe visualstudio, я хотел бы узнать об этом :)

+0

«Я бы хотел получить только основную функцию, и содержимое PrecompiledHeader.h будет исключено из вывода». Это неясно. Если вы опустите (просто) содержимое 'PrecompiledHeader.h', вы получите основную функцию * плюс * содержимое' stdio.h'. –

ответ

4

Вряд ли такой способ существует или будет встроен в clang (или любой другой компилятор C++) в будущее. Проблема заключается в том, что прекомпилированные заголовки используются для ускорения этапа компиляции, который обычно значительно дороже, чем шаг предварительной обработки. В результате, если вы собираетесь только предварительно обработать ваш источник, предварительно скомпилированный заголовок просто не будет использоваться. Один из способов, который имеет ничтожно малую вероятность получения того, что вы хотите использовать -include вариант вместо опции -include-pch (обратите внимание, что вы должны указать *.h, а не *.pch файла к нему):

clang main.cpp -include PrecompiledHeader.h -E 

Гарантированных способ решения вашей проблемы заключается в трубу препроцессированного выхода через простую программу-фильтр, который смотрит на # line "file" директивах и удаляет текст исходя из #include ред файлов:

clang main.cpp -E|remove_included_code 

remove_included_code можно легко impleme nted в питона, Баш, C/C++ и т.д. Вот реализация C++ (C++ был выбран так, чтобы его можно было легче всего использовать под 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; 
} 

Преимуществом этого решения является то, что он будет работать со всеми компиляторами.

+1

Из всех языков вы выбрали cpp для remove_included_code? – Dani

+1

@ Дани Я сделал это не просто так. Хотя действительно абсолютно не лучший язык для обработки текста, простая программа, написанная на C++, имеет то преимущество, что требует минимальных зависимостей для работы. Это имеет значение, если OP должен запускать его под Windows, где python и bash не являются гражданами первого класса. – Leon

1

Редактировать: В этом случае я не вижу ничего особенного в прекомпилированных заголовках - любые средства условного предотвращения расширения #include будут делать.

Я достигаю этого для стандартного заголовка, включает в себя обертывание в ifdef, так что препроцессорный вывод содержит #include "foo", но не содержимое. Например,

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

Затем пропустите -DPRECOMPILE вместе с -E.

Затем обработанный вывод содержит нерасширенный #include. Я считаю, что это более полезно, чем простая альтернатива обертывания #include в #ifdef при чтении предварительно обработанного вывода.

В первую очередь, это означает, что я могу запустить макро-тяжелый код через препроцессор, а затем clang-format перед компиляцией, как обычно, для значительно улучшенного отладочного опыта.