Совместное использование предварительно скомпилированных заголовков между проектами в Visual Studio

У меня есть решение со многими проектами Visual C ++, все из которых используют PCH, но в некоторых из них включены определенные переключатели компилятора для конкретных нужд проекта.

Большинство этих проектов используют один и тот же набор заголовков в соответствующем файле stdafx.h (STL, boost и т. Д.). Мне интересно, можно ли разделить PCH между проектами, чтобы вместо компиляции каждого PCH для каждого проекта я мог бы иметь один общий PCH, который могли бы просто использовать большинство проектов в решении.

Кажется возможным указать расположение PCH в качестве общего в настройках проекта, поэтому я подозреваю, что это может сработать. Я также предполагаю, что все исходные файлы во всех проектах, использующих общий PCH, должны иметь одинаковые настройки компилятора, иначе компилятор будет жаловаться на несоответствие между PCH и компилируемым исходным файлом.

Кто-нибудь пробовал это? Это работает?

Связанный с этим вопрос: должен ли такой сегментный PCH быть чрезмерно инклюзивным, или это повлияет на общее время сборки? Например, общий PCH может включать в себя множество широко используемых заголовков STL, но для некоторых проектов могут потребоваться только <string> и <vector>. Будет ли время, сэкономленное за счет использования общего PCH, окупаться на более позднем этапе процесса сборки, когда оптимизатору придется отбросить все неиспользуемые материалы, перетаскиваемые в проект PCH?


person Assaf Lavie    schedule 14.03.2009    source источник
comment
Почему бы вам просто не попробовать и не сообщить нам об этом? за то время, которое вам потребовалось, чтобы написать этот пост, вы могли бы пройти половину пути через простое подтверждение концепции из двух проектов.   -  person shoosh    schedule 14.03.2009
comment
Я не думаю, что 2 проекта POC что-нибудь докажут. Свою роль в этом играет большое количество проектов.   -  person Assaf Lavie    schedule 14.03.2009
comment
ПОЖАЛУЙСТА, ГОЛОСОВАТЬ ЗА ЭТО: visualstudio.uservoice.com/forums/121579-visual-studio/   -  person Scott Langham    schedule 08.11.2013
comment
Согласно вышесказанному, теперь это поддерживается, но нет информации о том, как его настроить. У кого-нибудь это работает?   -  person Robin    schedule 26.10.2016


Ответы (6)


Да, это возможно, и я могу вас заверить, это значительная экономия времени. Когда вы компилируете свой PCH, вы должны скопировать файлы .pdb и .idb из проекта, который создает файл PCH. В моем случае у меня есть простой двухфайловый проект, создающий файл PCH. Заголовок будет вашим заголовком PCH, а источнику будет сказано создать PCH в настройках проекта - это похоже на то, что вы обычно делаете в любом проекте. Как вы упомянули, у вас должны быть одинаковые настройки компиляции для каждой конфигурации, иначе возникнет несоответствие, и компилятор будет жаловаться.

Копирование вышеупомянутых файлов каждый раз при перекомпиляции или при каждой перекомпиляции PCH будет проблемой, поэтому мы автоматизируем это. Чтобы автоматизировать копирование, выполните событие перед сборкой, при котором вышеупомянутые файлы копируются в соответствующий каталог. Например, если вы компилируете сборки Debug и Release своего PCH, скопируйте файлы из Debug вашего проекта PCH в файл Debug зависимого проекта. Таким образом, команда копирования будет выглядеть так

скопируйте PchPath \ Debug * .pdb Debug \ / -Y

Обратите внимание на /-Y в конце. После первой сборки каждая последующая сборка компилируется постепенно, поэтому, если вы снова замените файлы, Visual Studio будет жаловаться на поврежденные символы. Если они действительно будут повреждены, вы всегда можете выполнить перестройку, которая снова скопирует файлы (на этот раз они не будут пропущены, поскольку они больше не существуют - очистка удаляет файлы).

Надеюсь, это поможет. Мне потребовалось некоторое время, чтобы это сделать, но оно того стоило. У меня есть несколько проектов, которые зависят от одного большого фреймворка, и PCH нужно скомпилировать только один раз. Все зависимые проекты теперь компилируются очень быстро.

РЕДАКТИРОВАТЬ: вместе с несколькими другими людьми я тестировал это в VS2010 и VS2012, и, похоже, он работает правильно.

person Samaursa    schedule 13.11.2010
comment
Кто-нибудь пробовал это на vs2010? - person Hertzel Guinness; 28.02.2011
comment
Да, похоже, это не работает, я получаю сообщение об ошибке: \ vc100.pdb - это не файл pdb, который использовался при создании этого предварительно скомпилированного заголовка, воссоздайте предварительно скомпилированный заголовок. Также пришлось изменить Microsoft.Cpp.Win32.targets, иначе он попытается сначала удалить PCH! - person paulm; 20.12.2012
comment
Это абсолютно неприменимо в производственной среде, это мешает перестройке и имеет всевозможные проблемы. - person paulm; 16.11.2013
comment
Это работает для меня для сборок выпуска, но не для сборок отладки, где я получаю ту же ошибку, что и paulm. - person Jherico; 15.03.2014
comment
Мне просто интересно, компилируют ли проекты, использующие pch, свою собственную версию. Похоже, что это так, поскольку в настройке stdafx.cpp по-прежнему указано «Создать». Я попытался просто удалить stdafx.cpp, но это вызывает ошибки компоновщика: 'LNK2011: предварительно скомпилированный объект не связан; изображение может не работать ». Так что, вероятно, другие проекты должны ссылаться на созданный объектный файл для stdafx.cpp? - person imagiro; 14.05.2014

Хотя это старый вопрос, я хочу дать новый ответ, который работает в Visual Studio 2017 и не требует копирования. Единственный недостаток: Edit and continue больше не работает.

По сути, вам нужно создать новый проект для предварительно скомпилированного заголовка, и все остальные проекты будут зависеть от него. Вот что я сделал:

Шаг за шагом:

  1. Создайте новый проект в своем решении, которое включает заголовок (далее pch.h) и однострочный файл cpp, который включает pch.h. В проекте должна быть создана статическая библиотека. Настройте новый проект для создания предварительно скомпилированного заголовка. Выходной файл должен быть доступен для всех проектов. для меня это относительно IntDir, но для настроек по умолчанию это может быть относительно $ (SolutionDir). У проекта pch должно быть только определение, которое есть у всех остальных проектов.

    настройки проекта pch

  2. Все остальные проекты зависят от этого нового проекта. В противном случае порядок сборки может быть неправильным.

    ссылки на проекты

  3. Настройте все остальные проекты на использование pch.h. Посмотрите, как параметры выходного файла такие же, как в проекте pch. Дополнительные каталоги include также должны указывать на каталог pch.h. При желании вы можете принудительно включить файл pch в каждый cpp (или вы включаете его вручную в первую строку каждого файла cpp).

    pch  include  включить

    1. Setup all projects (including the pch project) to use the same compiler symbol file (the linker symbol file is not affected). Again, in my example this is OutDir but in your solution this might vary. It has to point to the same file on disk. The Debug Information Format needs to be set to C7 (see screenshot above), otherwise Visual Studio will not be able to compile projects in parallel. pdb

Надеюсь, я ничего не забыл. Для моего решения (130k loc, 160 проектов) это привело к времени компиляции ~ 2:30 минут вместо ~ 3:30 минут.

person Nick Papagiorgio    schedule 13.03.2017
comment
Любопытно, что происходит, когда вы используете команду «Изменить и продолжить» с этой настройкой? - person Ramkumar; 14.03.2017
comment
Вам придется переключить формат отладочной информации, что приведет к невозможности параллельной компиляции Visual Studio, что, в свою очередь, снижает любые преимущества в производительности. - person Nick Papagiorgio; 14.03.2017
comment
Ой. Пропустил твой пост о переходе на / Z7. Спасибо за разъяснения. - person Ramkumar; 20.03.2017
comment
Отлично работает даже в vs2010 - person Daniel Laügt; 18.05.2017
comment
Кто-нибудь смог это сделать с помощью CMake? Мои попытки потерпели неудачу, и поскольку ссылки больше не работают, я не могу проверить, что то, что я делаю в CMake, переводится на VS. - person spellmansamnesty; 30.08.2018
comment
Можно ли повторно использовать предварительно скомпилированный заголовок в исполняемых файлах? ссылка на общий предварительно скомпилированный заголовок в исполняемых файлах дала мне предупреждения компилятора о несовпадении параметров компилятора. - person Elad Maimoni; 25.01.2021

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

person Assaf Lavie    schedule 18.03.2009
comment
Да, я тоже попал. :-( Ошибка C2859: vc90.pdb не является файлом pdb, который использовался при создании этого предварительно скомпилированного заголовка, воссоздайте предварительно скомпилированный заголовок. msdn.microsoft.com/en-us/library/3bw58yy6.aspx - person Trevor Robinson; 06.06.2010
comment
Возможно, посмотрите мой ответ. - person Samaursa; 13.11.2010

Ответ Самаурсы сработал для меня.

Я также видел эту ссылку это работает (найдите ответ Реджинальда внизу).

Этот использует copy, в то время как Реджинальд использует xcopy (я предпочитаю xcopy). В любом случае, спасибо - это значительно ускорило мои сборки.

person Brad W    schedule 16.12.2010
comment
+1, этот еще лучше, потому что он автоматически перестраивается при изменении stdafxes. - person Yakov Galka; 17.07.2011

Для меня это звучит как «убывающая отдача». Предположим, включение общих заголовков напрямую приводит к потере 1 секунды на файл .cpp, а каждая цель (DLL / EXE) имеет 10 файлов .cpp. Используя .pch на цель, вы экономите 10 секунд на цель. Если весь ваш проект имеет 10 целей, вы сэкономите 1,5 минуты на всей сборке, и это хорошо.

Но уменьшив его до одного файла .pch для всего проекта, вы сэкономите еще 9 секунд. Стоит ли оно того? Дополнительные усилия (которые могут быть намного сложнее настроить, поскольку это нестандартная конфигурация, не поддерживаемая мастерами VS) дают только 10-ю часть экономии.

person Daniel Earwicker    schedule 14.03.2009
comment
Подумайте, 200 проектов в решении с pch, компиляция которого может занять 10 секунд, и тогда будет не так ясно, так ли уменьшена отдача. - person Assaf Lavie; 14.03.2009
comment
Сколько времени занимает вся сборка? - person Daniel Earwicker; 14.03.2009
comment
Это также вопрос экономии времени на инкрементных сборках. Изменение может вынудить только один файл в каждом проекте перекомпилировать, тогда загрузка каждого pch займет много времени, чтобы выполнить быструю компиляцию. - person Macke; 14.03.2009
comment
@DanielEarwicker: 40-50 минут для одной конфигурации x (32,64 бит) x (отладка, выпуск). А это уже ~ 400 проектов. - person Yakov Galka; 23.06.2013

В 2012 году вы можете использовать PDB и просто построить pch из проекта библиотеки, который строит только pch и основной проект, который зависит от pch lib в одном каталоге (без копирования), к сожалению, это не работает с 2013+ кроме как через долгую и запутанную работу.

person Richard Broadhurst    schedule 20.11.2019