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

91

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

Ли Болдуин
источник
Я попробовал это, и у меня был оптимальный вариант использования для предварительно скомпилированных заголовков, потому что мой исходный код c генерируется компилятором, а не написан пользователем. Sun Studio и особенно Visual Studio значительно улучшили время сборки. В gcc было еще хуже, чем без предварительно скомпилированных заголовков. Это было с 3.4, не тестировалось с 4.x, но скорость и gcc являются взаимоисключающими.
Lothar
@Lothar какой был код? Я считаю, что g ++ примерно в 10 раз быстрее, чем последние компиляторы Visual Studio, для некоторого сильно шаблонного кода.
свинья
Я не использую шаблоны в своем коде на C ++. Это просто обработка исключений C + + красивые расширения C ++. Даже сейчас, спустя 6 лет после этого вопроса, VS2010 на порядок быстрее. Но пока что у меня 16 ядер, так что я могу с этим жить.
Lothar

Ответы:

59

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


#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

Пользователь1
источник
20
Добавление -Winvalid-pch поможет вам отладить, если и почему что-то пойдет не так при использовании PCH.
lefticus
Предварительно скомпилированные заголовки «неплохо, но не отлично» полезны, когда у вас есть много заголовков, которые повторно связывают друг друга, поэтому они сокращают время компиляции в очень большом проекте, который использует большие библиотеки или много библиотек.
jokoon
4
«неплохо, но не отлично»: с использованием 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 намного сложнее!
Андреас Верджисон
1
(продолжение) Соответствующие выходные файлы 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. И, конечно, даже намного быстрее при включении мультипроцессора ...
Андреас Верджисон
@AndreasVergison - Вы пытались использовать, -Winvalid-pchчтобы убедиться, что предварительно скомпилированный заголовок используется правильно? Мы заметили большое улучшение использования pch для наших отладочных сборок, поэтому мне интересно, есть ли проблема с вашей настройкой.
Джош Келли
52

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

Вы компилируете заголовки, как и любой другой файл, но помещаете вывод в файл с суффиксом .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.

Брайан Р. Бонди
источник
8

Спецификатор -xдля предварительно скомпилированных заголовков C ++ - -x c++-headernot -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находится.

псагелий
источник
3
Так должно быть -c pch.h, не так -c pch.cppли?
MM
7

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

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

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

Павел
источник
7

Вызовите 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
1

Убедитесь, что -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
....
Hor Mé
источник