(т. е. ClangTool),
но время перекомпиляции исходного файла занимает больше времени, чем хотелось бы.
В частности, для небольшого примера программы, приведенного ниже, компиляция этого одного файла занимает около 7
секунд, а я #included лишь голый
минимум. Как только я начинаю использовать средства сопоставления AST, время компиляции возрастает до
20 секунд и более. Это создает большие трудности в цикле разработки,
особенно при изучении нового API и, следовательно, исправлении большого количества
синтаксических ошибок.
Я нашел несколько слайдов под названием
Эффективное создание Clang/LLVM
Тилманн Шеллер из выступления на EuroLLVM 2015, которое демонстрирует скромное
улучшение (менее чем в 2 раза) за счет изменения используемого компилятора
(в частности, компиляция с помощью clang, который был скомпилирован
gcc). Я игнорирую улучшения связывания, потому что в моем случае связывание
достаточно быстро.
Я пробовал использовать предварительно скомпилированные заголовки GCC
(PCH), но результаты неоднозначные. (подробности ниже). Хотя компиляция с помощью PCH занимает
примерно вдвое меньше времени, генерация PCH в первую очередь занимает более чем в два раза больше времени, чем обычная компиляция, и создает огромный файл PCH
(300-500 МБ). , и его довольно сложно использовать (мне приходится реорганизовать
#includes в моем проекте, управлять дополнительными зависимостями и файлами
и тщательно отслеживать процесс, чтобы убедиться, что PCH используются).
В идеале я хотел бы получить время компиляции менее одной секунды. В конце концов,
мой исходный файл состоит всего из 100 строк кода (LOC). Теперь вывод
препроцессора имеет около 200 КБ LOC, а слово шаблон появляется
более чем в 5000 из этих строк, поэтому я полностью осознаю, что компилятор делает
больше, чем сразу бросается в глаза. Но мой код напрямую не использует
большую часть этого.
Для сравнения: при использовании привязок Python
0,05 секунды требуется для запуска сценария сравнительно минимальной сложности. Мне известен libclang,
привязка C для Clang, но я не хочу писать свой инструмент на C.
Более того, libclang (для обоих C и Python) предоставляет лишь небольшую часть информации, доступной в API C++. Поскольку этот вопрос был изначально написан, я потратил пару месяцев на использование libclang только для того, чтобы в конечном итоге отказаться от него как непригодного для использования из-за отсутствующей информации (пример - получение оператора двоичного выражения, хотя теперь этот вопрос уже рассмотрен). , но есть и многие другие).
Некоторые измерения в различных вариациях, измерение медианы из 5 с помощью GCC-9.3:
Параметры
Нет PCH
Получить PCH
Использовать PCH
Размер PCH
g++
6,8 с
14 с
2,5 с
342 МБ
g++ -O2
6,9 с
14 с
2,5 с
345 МБ
g++ -g
8,6 с
18 с
4,1 с
472 МБ
g++ -g -O2
8,9 с
18 с
4,3 с
478 МБ
G++ -g< Конфигурация /code> меня волнует больше всего.
@HolyBlackCat предложил попробовать использовать clang в качестве компилятора. Вот времена для Clang+LLVM-14.0.0:
Опции
Нет PCH
Полный PCH
< th>Использовать PCH
Размер PCH
clang
5,6 с
5,1 с
2,3 с
62 МБ
clang -O2
5,6 с
5,2 с
2,5 с
62 МБ
clang -g
5,6 с
5,2 с
2,4 с
62 МБ
clang -g -O2
5,7 с
5,1 с
2,6 с
62 МБ
Это, безусловно, улучшение по сравнению с g++, и вполне возможно, что я собираюсь вперед, хотя это не соответствует моей цели менее секунды.
Для полноты картины я также измерил GCC-12.1 и обнаружил, что он примерно на 2% хуже, чем GCC-9.3 для всех измеренных значений. раз.
Моя установка:
- Использование бинарного дистрибутива clang+llvm-14.0.0 загружено с github.com.
- Компиляция с помощью GCC-9.3.0 в Linux Mint 20.1 для x86_64.
- Четырехъядерный процессор Intel i5-6600K @ 3.50HGz.
- 8 ГБ ОЗУ.
- Linux работает на VMware Workstation 12. (ВМ не является
проблемой. Многие C++ проекты компилируются на виртуальной машине очень быстро, даже
быстрее, чем компиляция на хосте Windows.) - Хост — Windows 10 с 32 ГБ физической оперативной памяти.
// print-tu.cc
// Print contents of a Translation Unit.
// clang
#include "clang/AST/ASTConsumer.h" // clang::ASTConsumer
#include "clang/AST/ASTContext.h" // clang::ASTContext
#include "clang/AST/DeclBase.h" // clang::Decl
#include "clang/AST/DeclGroup.h" // clang::DeclGroupRef
#include "clang/Basic/SourceLocation.h" // clang::SourceLocation
#include "clang/Frontend/CompilerInstance.h" // clang::CompilerInstance
#include "clang/Frontend/CompilerInvocation.h" // clang::CompilerInvocation
#include "clang/Frontend/FrontendAction.h" // clang::FrontendAction, clang::ASTFrontendAction
#include "clang/Tooling/CommonOptionsParser.h" // clang::tooling::CommonOptionsParser
#include "clang/Tooling/Tooling.h" // clang::tooling::ClangTool, clang::tooling::newFrontendActionFactory
// llvm
#include "llvm/ADT/StringRef.h" // llvm::StringRef
#include "llvm/Support/CommandLine.h" // llvm:
// libc++
#include // std::cout, etc.
// libc
#include // assert
using clang::tooling::CommonOptionsParser;
using clang::tooling::ClangTool;
using clang::tooling::newFrontendActionFactory;
using clang::ASTConsumer;
using clang::ASTContext;
using clang::ASTFrontendAction;
using clang::CompilerInstance;
using clang::CompilerInvocation;
using clang::Decl;
using clang::DeclGroupRef;
using clang::DiagnosticConsumer;
using clang::FileManager;
using clang::FrontendAction;
using clang::PCHContainerOperations;
using clang::SourceLocation;
using clang::TargetOptions;
using llvm::StringRef;
using std::cout;
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm:
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static llvm:
// A help message for this specific tool can be added afterwards.
static llvm:
// Implement ASTConsumer
class MyASTConsumer : public ASTConsumer {
public: // data
// The context for the TU, as established by 'Initialize'.
ASTContext *m_astContext;
public: // methods
MyASTConsumer()
: m_astContext(NULL)
{}
// This is called at the start of the TU.
virtual void Initialize(ASTContext &ctx) override
{
m_astContext = &ctx;
}
// This is called at the end of the TU.
virtual void HandleTranslationUnit(ASTContext &ctx) override
{
cout
Подробнее здесь: https://stackoverflow.com/questions/726 ... based-tool
Мобильная версия