Кому-нибудь удалось получить предварительно скомпилированные заголовки, работающие с GCC? Мне не повезло с моими попытками, и я не видел много хороших примеров того, как это настроить. Я пробовал cygwin gcc 3.4.4 и использовал 4.0 на Ubuntu.
@Lothar какой был код? Я считаю, что g ++ примерно в 10 раз быстрее, чем последние компиляторы Visual Studio, на некотором сильно шаблонном коде.
Я не использую шаблоны в своем коде на C++. Это просто обработка исключений C + + красивые расширения C++. Даже сейчас, спустя 6 лет после этого вопроса, VS2010 на порядок быстрее. Но пока что у меня 16 ядер, так что я могу с этим жить.





Однажды мне удавалось получать предварительно скомпилированные заголовки, работающие под 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 "
Во-первых, см. Документацию здесь.
Заголовки компилируются так же, как и любой другой файл, но вывод помещается в файл с суффиксом .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.
Предварительно скомпилированные заголовки «неплохо, но не отлично» полезны, когда у вас много заголовков, которые повторно связывают друг друга, поэтому они сокращают время компиляции в очень большом проекте, который использует большие библиотеки или много библиотек.
«неплохо, но не великолепно»: с использованием 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 намного сложнее!
(продолжение) Соответствующие выходные файлы 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 для наших отладочных сборок, поэтому мне интересно, есть ли проблема с вашей настройкой.
Те же флаги применимы к Clang на Mac, если кто-то его использует. Спасибо за этот ответ, мне это очень помогло.
Спецификатор -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?
Убедитесь, что -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, чтобы проверить, находит ли / использует ли он его.
Я попробовал это, и у меня был оптимальный вариант использования для предварительно скомпилированных заголовков, потому что мой исходный код c генерируется компилятором, а не написан пользователем. Sun Studio и особенно Visual Studio значительно улучшили время сборки. В gcc было еще хуже, чем без предварительно скомпилированных заголовков. Это было с 3.4, не тестировалось с 4.x, но скорость и gcc являются взаимоисключающими.