Visual Studio удаляет общий файл .pch и вопросы о настраиваемых шагах сборки

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

Однако файл .pch удаляется, если имя файла .pdb проекта PCH отличается от имен файлов .pdb других проектов.

Эта страница не отвечает на вопрос: https://devblogs.microsoft.com/cppblog/shared-pch-usage-sample-in-visual-studio/

Я не хочу использовать одно и то же имя для всех PDB.

Вопросы:

1) Почему файл .pch удаляется при старте компиляции других проектов, что приводит к ошибке C1083 (.pch не найден), если имена PDB не равны, не как на той странице?

2) Я копирую файлы pch.pdb и pch.idb с помощью команды COPY, есть ли команда RENAME или что-то в этом роде, если скопированный pch.pdb должен называться так же, как PDB зависимого проекта? И где я могу найти полный список команд Custom Build Step?

3) Я не понимаю цели «Дополнительных зависимостей» и «Выходов» на этапе пользовательской сборки. Могу ли я ввести имя файла .pch в список зависимостей, чтобы он не был удален? Должен ли выходной список содержать имя PDB зависимого проекта, pch.pdb или и то, и другое?


person Emil Kabirov    schedule 06.05.2020    source источник
comment
Интересно, почему вы удаляете файл pch, получается ошибка. Вы вносили какие-либо изменения в пример кода github? И на самом деле, если есть задача удаления, файл будет удален, и когда я тестирую на своей стороне, такой задачи нет. VS не удалит файлы из-за разных файлов pdb. И файл pch существует под SharedPchSample\Outputs\Intermediate\Shared\Win32\Debug. Структура решения изменена автором (включая выходной путь). VS не удалит этот файл по умолчанию, это бессмысленно. Поэтому, пожалуйста, проверьте свой файл xxx.vcxproj и убедитесь, что в нем нет задачи удаления.   -  person Mr Qian    schedule 07.05.2020
comment
И проект SharedPCH предназначен для создания файла pch, а проект 1 и проект 2 - для использования файла pch. Из-за того, что проект 1 и 2 ссылаются на SharedPCH, он всегда будет создаваться первым, а затем использоваться позже. Щелчок правой кнопкой мыши по каждому проекту -->Properties-->C/C++-->Precompiled Headers-->Precompiled Headers Output File одинаковы. Под Properties--›Custom Build Step можно найти. Название разработано таким образом. Этот пользовательский шаг - это просто команда CMD. И вы можете ввести Properties--›C/C++--›Output Files--›Program Database File Name, чтобы изменить его и использовать $(IntDir)$(ProjectName).pdb.   -  person Mr Qian    schedule 07.05.2020
comment
Вопрос 3. Настраиваемый шаг — скопировать выходные данные проекта SharedPCH (файлы xxx.pdb и xxx.idb) в настраиваемый выходной файл для отладки общего проекта, и он не имеет ничего общего с операцией удаления. В конце концов, эти файлы нужны для настройки отладки. Итак, как вы упомянули, они должны содержаться, поскольку на общий проект ссылаются проекты 1 и 2. Что касается проблемы удаления, она действительно не имеет ничего общего с собой, вам нужно перепроверить свой проект, чтобы увидеть, какие изменения были сделаны или вернуться к исходному проекту.   -  person Mr Qian    schedule 07.05.2020
comment
Привет! Спасибо за ваши ответы. Что ж, я решил свои проблемы. Это был первый раз, когда я изучил MSBuild и файловую структуру проекта, а также его расширенные параметры, и я был просто перегружен информацией и деталями. Да, у меня были некоторые правки в файлах проекта.   -  person Emil Kabirov    schedule 11.05.2020
comment
Во-первых, по какой-то причине (делал я это или нет) сгенерированный компилятором .pdb файл был не $(PlatformToolsetVersion).pdb, а $(ProjectName).pdb . Таким образом, скопированный общий файл .pdb в моем случае был pch.pdb, в то время как другие проекты ожидали других имен. И это запускало задачу DELETE в Microsoft.CppCommon.targets (удалить файл pch, если файл pdb был удален). Вместо изменения выходного имени .pdb я просто заглянул в команду XCOPY и заставил ее изменить имя скопированного файла на ожидаемое конкретным проектом.   -  person Emil Kabirov    schedule 11.05.2020
comment
Затем я также изменил сгенерированный компоновщиком выходной файл .pdb, просто добавив к имени суффикс Linked, чтобы не было конфликтов между pdb компилятора и компоновщика. Не уверен, что это хорошая идея - изменить настройки по умолчанию без веской причины :)   -  person Emil Kabirov    schedule 11.05.2020
comment
Спасибо за ваш подробный ответ на этот вопрос :) Вы можете отметить свой собственный ответ. В любом случае, хорошего дня!   -  person Mr Qian    schedule 12.05.2020
comment
Я не понимаю этот вопрос. PDB относится к базе данных программы для отладки, PCH — к предварительно скомпилированным заголовкам. Файл с именем pch.pdb действительно сбивает с толку. Расширение pdb, так что это файл базы данных программы для отладки. У него нет расширения .pch, поэтому он не имеет ничего общего с предварительно скомпилированными заголовками.   -  person MSalters    schedule 12.05.2020
comment
@MSalters в моем случае pch - это имя предварительно скомпилированного проекта заголовка. Он генерирует common.pch из common.hpp и common.cpp и свой pch.pdb для отладки, который копируется в другие проекты для добавления символов для предварительно скомпилированного кода.   -  person Emil Kabirov    schedule 12.05.2020


Ответы (2)


Использовали ли вы пример кода по ссылке на github.

Если это так, вам следует загрузить и затем использовать этот образец, а если вы создаете свой собственный проект, вам следует тщательно проверить свои проекты.

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

1) Почему файл .pch удаляется при старте компиляции других проектов, что приводит к ошибке C1083 (.pch не найден), если имена PDB не равны, не как на той странице?

Прежде всего убедитесь, что в ваших проектах нет другой возможности удалить файл PCH.

Проект PCH должен создать файл PCH, а два других проекта должны использовать такой файл. И каждый раз, когда вы создаете два проекта (ссылка на проект PCH), всегда выполняйте сборку проекта PCH, а затем стройте два проекта. Таким образом, PCH всегда создается, а затем используется в двух проектах.

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

Проект SharedPCH

введите здесь описание изображения

Консольное приложение1

введите здесь описание изображения

Консольное приложение2

введите здесь описание изображения

В примере кода файл PCH находится в папке SharedPchSample\Outputs\Intermediate\Shared\Win32\Debug.

2) Я копирую файлы pch.pdb и pch.idb с помощью команды COPY, есть ли команда RENAME или что-то в этом роде, если скопированный pch.pdb должен называться так же, как PDB зависимого проекта? И где я могу найти полный список команд Custom Build Step?

Шаг пользовательской сборки находится в каждом проекте -->Properties-->Custom Build Step-->Command Line, и затем вы можете найти его. Этот пользовательский шаг — это просто команда CMD. И вы можете выполнить CMD, чтобы выполнить дополнительную операцию.

Кроме того, я думаю, вы хотите, чтобы эти xxx.pdb и xxx.idb совпадали с именем проекта, чтобы отличать одно от другого. Вы можете щелкнуть правой кнопкой мыши по каждому проекту -->Properties-->C/C++-->Output Files-->Program Database File Name-->изменить его и использовать $(IntDir)$(ProjectName).pdb. Дополнительные сведения об шагах пользовательской сборки см. в по этой ссылке.

Я не понимаю цели «Дополнительных зависимостей» и «Выходов» на этапе пользовательской сборки. Могу ли я ввести имя файла .pch в список зависимостей, чтобы он не был удален? Должен ли выходной список содержать имя PDB зависимого проекта, pch.pdb или и то, и другое?

Additional dependencies настроен на использование содержимого файла PCH в проектах 1 и 2, что аналогично настройке адреса библиотеки эталонных классов в проекте C++. И я думаю, что это может быть излишним, и поскольку автор добавил это, это означает, что это хорошо обосновано.

И Outputs — это настраиваемый автором выходной путь, автор изменил выходной адрес проекта и запустил новый настраиваемый выходной путь и временный выходной путь.

На самом деле файл xxx.pch и его файлы pdb и idb не будут скопированы в выходной путь. Таким образом, шаг пользовательской сборки заключается в копировании файлов во временный выходной путь. И если вы хотите скопировать их в окончательный выходной путь, вы также можете использовать их в файле CustomBuildStep.targets:

<CustomBuildStep>
<Command>
if EXIST "$(SharedPdb)" xcopy /Y /F "$(SharedPdb)" "$(IntDir)"
if EXIST "$(SharedIdb)" xcopy /Y /F "$(SharedIdb)" "$(IntDir)"
if EXIST "$(SharedPdb)" xcopy /Y /F "$(SharedPdb)" "$(OutDir)"
if EXIST "$(SharedIdb)" xcopy /Y /F "$(SharedIdb)" "$(OutDir)"
</Command>
<Outputs>$(IntDir)vc$(PlatformToolsetVersion).pdb;</Outputs>
<Inputs>$(SharedPdb)</Inputs>
</CustomBuildStep>

И на самом деле один проект ссылается на другой проект, и выходные файлы упомянутого проекта автоматически копируются в основной проект. Возможно, это связано с тем, что авторский проект SharePCH не генерирует файлы pdb и idb, поэтому файлы зависимого проекта не будут найдены в основном проекте.

person Mr Qian    schedule 08.05.2020
comment
Вы можете щелкнуть правой кнопкой мыши на каждом проекте-->Свойства-->C/C++-->Выходные файлы-->Имя файла базы данных программы-->изменить его и использовать $(IntDir)$(ProjectName).pdb . Ну, это была проблема, каждый проект хочет свое конкретное имя .pdb, но имя по умолчанию — $(IntDir)vc$(PlatformToolsetVersion).pdb. И поскольку скопированный pch.pdb (в моем случае) не соответствует проекту, он запускает задачу DELETE для общего файла .pch. - person Emil Kabirov; 11.05.2020
comment
Так что да, переименование после копирования исправило это - person Emil Kabirov; 11.05.2020

По какой-то причине (делал я это или нет) сгенерированный компилятором файл .pdb был не $(PlatformToolsetVersion).pdb, а $(ProjectName).pdb . Таким образом, скопированный в другие папки проекта общий файл .pdb в моем случае был pch.pdb, в то время как другие проекты ожидали другие имена. И это вызывало задачу DELETE в Microsoft.CppCommon.targets («Удалить файл pch, если файл pdb был удален».). Вместо того, чтобы изменить выходное имя .pdb, я просто заглянул в команду XCOPY и заставил ее изменить имя скопированного файла на ожидаемое конкретным проектом (на самом деле тогда я просто добавил пользовательскую цель с переименованием задачи копирования прямо в файл проекта вместо используя CustomBuildStep, вызывающий команду ОС xcopy, так как теперь я узнал больше о MSBuild).

Затем я также изменил сгенерированный компоновщиком выходной файл .pdb, просто добавив к имени суффикс «Linked», чтобы не возникало конфликтов между PDB-файлами компилятора и компоновщика. Не уверен, что это хорошая идея - изменить настройки по умолчанию без веской причины.

Думаю, лучше просто изменить выходную PDB компилятора на $(PlatformToolsetVersion).pdb , чтобы все проекты использовали одно и то же имя.

Это был первый раз, когда я заглянул в MSBuild и расширенные настройки проекта, теперь кажется очевидным, что проект, использующий общий .pdb, хочет какое-то знакомое имя .pdb, а не случайный pch.pdb

Вот моя пользовательская цель, импортированная в файлы проекта, копирующая общий .pdb, только если он был перестроен (в моем случае .idb не создается):

<Target Name="CopyFreshPchPdb" BeforeTargets="ClCompile" 
    Inputs="$(PchDir)\pch.pdb"
    Outputs="$(IntDir)\$(ProjectName).pdb">
    <Message  Importance="High" Text="Copying shared pch.pdb" />
    <Copy
        SourceFiles="$(PchDir)\pch.pdb"
        DestinationFiles="$(IntDir)\$(ProjectName).pdb">
    </Copy>
</Target>
person Emil Kabirov    schedule 11.05.2020