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


91

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


Я спробував це, і у мене був оптимальний варіант використання для попередньо скомпільованих заголовків, оскільки моє джерело c створюється компілятором, а не користувачем. Sun Studio та особливо Visual Studio значно покращили час збірки. На gcc це ставало ще гірше, ніж без попередньо скомпільованих заголовків. Це було з 3.4 не тестували з 4.x, але швидкість та gcc взаємовиключні.
Лотар,

@Lothar який був код? Я знаходжу g ++ приблизно в 10 разів швидше, ніж нещодавні компілятори Visual Studio, на деяких сильно шаблонованих кодах.
свині

Я не використовую шаблони у своєму коді С ++. Це просто обробка винятків C + + приємні розширення C ++. Навіть зараз через 6 років після цього питання VS2010 набагато швидший. Але тим часом у мене є 16 ядер, щоб я міг з цим жити.
Лотар

Відповіді:


58

Я точно мав успіх. Спочатку я використав такий код:


#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 (код :: блоки), і побачив щось подібне:

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

The! означає, що компілятор зміг використовувати попередньо скомпільований заголовок. Значок х означає, що він не зміг ним скористатися. Використання відповідних прапорів компілятора є вирішальним. Я зняв -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


20
Додавання -Winvalid-pch допоможе вам налагодити, якщо і чому щось не вдається у використанні PCH.
lefticus

Попередньо скомпільовані заголовки "непогано, але не чудово" корисні, коли у вас є багато багатьох заголовків, які перев'язують один одного, тому вони скоротять час компіляції для дуже великого проекту, який використовує великі бібліотеки або багато бібліотек.
jokoon

4
"непогано, але не чудово": за допомогою gcc 4.4.7, 136 файлів .cpp загальним розміром 35,5 Мб, 148 файлів .h загальним розміром 5,5 Мб, файл .gch становить 48 Мб, збірка налагодження займає 2'20 "(проти 2 '14 "не pch), -O2 оптимізована збірка займає 4'30" (проти 5'33 "не pch) Ефект очікувався б біля налагоджувальних збірок, але це лише оптимізована збірка, яка приносить прибуток від попередньої компіляції .... Не знаю, чому. Попередня компіляція набагато драматичніша для Windows!
Андреас Вергісон,

1
(продовження) Відповідні вихідні файли pch / non-pch мають абсолютно однаковий розмір байта, це добре. Вищезазначені терміни, здається, змінюються при повторенні збірок, наприклад -O2 non-pch коливається між 3'45 "і 5'33", тому це не точна наука, можливо, через запуск у VMware. У будь-якому випадку, gcc pch у моєму випадку взагалі не виглядає вигідним. Порівняйте його з тією ж базою коду для Windows VS2012 (x64, однопотокова компіляція): налагодження 46 "pch, 2'50" non-pch, випуск 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++-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є.


3
Це повинно бути -c pch.h, чи не так -c pch.cpp?
ММ

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>

Потім я знайшов lib, скомпілювавши мій файл за допомогою -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
....
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.