Предварительно скомпилированные заголовки с GCC

Кому-нибудь удалось получить предварительно скомпилированные заголовки, работающие с GCC? Мне не повезло с моими попытками, и я не видел много хороших примеров того, как это настроить. Я пробовал cygwin gcc 3.4.4 и использовал 4.0 на Ubuntu.

Я попробовал это, и у меня был оптимальный вариант использования для предварительно скомпилированных заголовков, потому что мой исходный код c генерируется компилятором, а не написан пользователем. Sun Studio и особенно Visual Studio значительно улучшили время сборки. В gcc было еще хуже, чем без предварительно скомпилированных заголовков. Это было с 3.4, не тестировалось с 4.x, но скорость и gcc являются взаимоисключающими.

Lothar 04.11.2009 15:33

@Lothar какой был код? Я считаю, что g ++ примерно в 10 раз быстрее, чем последние компиляторы Visual Studio, на некотором сильно шаблонном коде.

the swine 08.10.2014 19:30

Я не использую шаблоны в своем коде на C++. Это просто обработка исключений C + + красивые расширения C++. Даже сейчас, спустя 6 лет после этого вопроса, VS2010 на порядок быстрее. Но пока что у меня 16 ядер, так что я могу с этим жить.

Lothar 09.11.2014 08:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
92
3
64 876
7

Ответы 7

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

Как правило, безопаснее всего, чтобы ваша система сборки скомпилировала файл .gch в качестве первого шага с теми же параметрами командной строки и исполняемым файлом, что и остальная часть исходного кода. Это гарантирует актуальность файла и отсутствие незначительных отличий.

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

Вызовите gcc так же, как вы называете его для исходного файла, но с файлом заголовка.

например

g++ $(CPPFLAGS) test.h

это генерирует файл с именем test.h.gch

Каждый раз, когда gcc ищет test.h, он сначала ищет test.h.gch и, если находит, использует его автоматически.

Более подробную информацию можно найти в разделе Предварительно скомпилированные заголовки GCC.

Я использую gcc 3.4, и строка g ++ stdafx.h не будет компилироваться, вы получите ошибку «g ++: запрошена компиляция файла заголовка», но это будет компилироваться, хотя я не уверен, что это то, что я хочу: «g ++ -c -x C++ stdafx.h -o stdafx.h.pch "

stefanB 15.05.2009 05:56

Во-первых, см. Документацию здесь.

Заголовки компилируются так же, как и любой другой файл, но вывод помещается в файл с суффиксом .gch.

Так, например, если вы предварительно скомпилируете stdafx.h, у вас будет предварительно скомпилированный заголовок, который будет автоматически искать stdafx.h.gch каждый раз, когда вы включаете stdafx.h.

Пример:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

Затем скомпилируйте как:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

Ваша компиляция будет работать, даже если вы удалите stdafx.h после шага 1.

Я определенно добился успеха. Сначала я использовал следующий код:


#include <boost/xpressive/xpressive.hpp>
#include <iostream>

using namespace std;
using namespace boost::xpressive;

//A simple regex test
int main()
{
    std::string hello( "hello world!" );

    sregex rex = sregex::compile( "(\w+) (\w+)!" );
    smatch what;

    if ( regex_match( hello, what, rex ) )
    {
        std::cout << what[0] << '\n'; // whole match
        std::cout << what[1] << '\n'; // first capture
        std::cout << what[2] << '\n'; // second capture
    }
    return 0;
}

Это был просто привет от Boost Xpressive (см. Ссылку ниже). Сначала я скомпилировал опцию -H в gcc. Он показал огромный список используемых заголовков. Затем я взглянул на флаги компиляции, которые создавала моя IDE (code :: blocks), и увидел что-то вроде этого:

g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o

Поэтому я написал команду для компиляции файла Xpressive.hpp с точно такими же флагами:

sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp

Я снова скомпилировал исходный код с помощью -H и получил следующий результат:

g++ -Wall -fexceptions -H  -g     -c main.cpp -o obj/Debug/main.o
! /usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
. /usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp

! означает, что компилятор смог использовать предварительно скомпилированный заголовок. Значок x означает, что он не смог его использовать. Использование соответствующих флагов компилятора имеет решающее значение. Я снял -H и провел несколько тестов скорости. Предварительно скомпилированный заголовок улучшился с 14 до 11 секунд. Неплохо, но не отлично.

Примечание. Вот ссылка на пример: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Мне не удалось заставить его работать в сообщении.

Кстати: я использую следующий g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Добавление -Winvalid-pch поможет вам отладить, если и почему что-то пойдет не так при использовании PCH.

lefticus 13.01.2012 18:40

Предварительно скомпилированные заголовки «неплохо, но не отлично» полезны, когда у вас много заголовков, которые повторно связывают друг друга, поэтому они сокращают время компиляции в очень большом проекте, который использует большие библиотеки или много библиотек.

jokoon 28.09.2013 22:15

«неплохо, но не великолепно»: с использованием gcc 4.4.7, 136 файлов .cpp Общий размер 35,5 МБ, 148 файлов .h Общий размер 5,5 МБ, файл .gch - 48 МБ, сборка отладки занимает 2'20 »(vs 2 '14 "non-pch), оптимизированная сборка -O2 занимает 4'30" (против 5'33 "non-pch) Эффект можно было бы ожидать около отладочных сборок, но это просто оптимизированная сборка, которая выигрывает от предварительной компиляции .... Не знаю почему. Предварительная компиляция в Windows намного сложнее!

Andreas Vergison 23.04.2014 17:45

(продолжение) Соответствующие выходные файлы pch / non-pch имеют точно такой же размер в байтах, это хорошо. Вышеупомянутые тайминги, похоже, меняются при повторении сборок, например -O2 non-pch варьируется от 3'45 "до 5'33", так что это не точная наука, возможно, из-за работы в VMware. В любом случае, в моем случае gcc pch не выглядит выгодным. Сравните его с той же базой кода в Windows VS2012 (x64, однопоточная компиляция): debug 46 "pch, 2'50" non-pch, release 2'13 "pch, 5'02" non-pch. И, конечно, даже намного быстрее при включении мультипроцессора ...

Andreas Vergison 23.04.2014 18:27

@AndreasVergison - Пробовали ли вы использовать -Winvalid-pch, чтобы убедиться, что предварительно скомпилированный заголовок используется правильно? Мы заметили большое улучшение использования pch для наших отладочных сборок, поэтому мне интересно, есть ли проблема с вашей настройкой.

Josh Kelley 12.09.2014 16:58

Те же флаги применимы к Clang на Mac, если кто-то его использует. Спасибо за этот ответ, мне это очень помогло.

Sri Harsha Chilakapati 12.11.2014 11:34

Спецификатор -x для предварительно скомпилированных заголовков C++ - -x c++-header, а не -x c++. Ниже приводится пример использования PCH.

pch.h:

// Put your common include files here: Boost, STL as well as your project's headers.

main.cpp:

#include "pch.h"
// Use the PCH here.

Создайте PCH следующим образом:

$ g++ -x c++-header -o pch.h.gch -c pch.h

pch.h.gch должен находиться в том же каталоге, что и pch.h, чтобы его можно было использовать, поэтому убедитесь, что вы выполняете указанную выше команду из каталога, в котором находится pch.h.

Это должен быть -c pch.h, а не -c pch.cpp?

M.M 07.11.2017 02:46

Убедитесь, что -include your_header.h

Вот как я предварительно скомпилировал и использовал коллекцию bits/stdc++.h.

Код

#include <bits/stdc++.h>

Затем я нашел библиотеку, скомпилировав свой файл с помощью -H и просмотрев вывод

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

где я видел

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

Итак, я создал новый каталог bits внутри текущего и скопировал оттуда stdc++.h.

Затем я побежал

g++ bits/stdc++.h -O3 -std=c++14  -pthread

который сгенерировал bits/stdc++.gch

Обычно я компилировал свой код через

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

, но мне пришлось изменить это на

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

поскольку он разрешен только в файл .gch вместо .h с -include bits/stdc++.h Это было для меня ключевым моментом. Также следует иметь в виду, что вам нужно скомпилировать файл заголовка *.h почти с теми же параметрами, что и при компиляции *.cpp. Когда я не включал -O3 или -pthread, он игнорировал предварительно скомпилированный заголовок *.gch.

Чтобы проверить, все ли правильно, вы можете измерить разницу во времени, сравнив результат

time g++ sol.cpp ...

или беги

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

снова и ищите пути заголовков, и если теперь вы получите ! до пути к библиотеке, например

! ./bits/stdc++.h.gch
....

Тонкий совет о расширении файла, который сбил меня с толку, потому что я не уделял достаточно внимания: расширение .gch добавляется к полному имени предварительно скомпилированного файла, оно не заменяет .h. Если вы ошиблись, компилятор не найдет его и не сработает.

precomp.h => precomp.h.gch

Нет:

precomp.h => precomp.гч

Используйте gcc -H, чтобы проверить, находит ли / использует ли он его.

Другие вопросы по теме