Visual Studio deletes a shared .pch file, and questions about custom build steps
Asked Answered
B

3

5

I try to use a shared .pch file, which is compiled in one project and used in others.

However the .pch file is deleted if a .pdb filename of the PCH project differs from .pdb filenames of the other projects.

This page doesn't answer the question: https://devblogs.microsoft.com/cppblog/shared-pch-usage-sample-in-visual-studio/

I don't want to use a same name for all PDBs.

Questions:

1) Why the .pch file is deleted at the start of other projects compilation, which leads to a C1083 error (.pch not found), if PDB names are not equal, not like in that page?

2) I copy pch.pdb and pch.idb files using COPY command, is there a RENAME comand or something, if the copied pch.pdb should be named just like a dependent project's PDB? And where can I find a complete list of Custom Build Step command?

3) I don't understand the purpose of "Additional dependencies" and "Outputs" in Custom Build Step. Can I enter the .pch filename into the dependency list, so it won't be deleted? Does the output list need to contain the dependent project's PDB name, or the pch.pdb, or both?

Billie answered 6/5, 2020 at 18:8 Comment(9)
I wonder why you delete the pch file, it turns out the error. Did you do any changes to the github sample code? And actually if there is a delete task, the file will be removed and when I test in my side,there is no such task. VS will not delete any files due to different pdb files. And the pch file exists under SharedPchSample\Outputs\Intermediate\Shared\Win32\Debug. The solution's structure is changed by the author(include the outputpath). VS will not delete this file by default, this is meaningless. So please check your xxx.vcxproj file and make sure there is no delete task.Outpoint
And SharedPCH project is to create the pch file while project 1 and project 2 to use the pch file. Due to project 1 and 2 referencing SharedPCH, it will always created first and then be used later.Right-click on every project-->Properties-->C/C++-->Precompiled Headers-->Precompiled Headers Output File are the same. Under Properties-->Custom Build Step, and you can find it. The name is designed by that.That custom step is just CMD command. And you can enter Properties-->C/C++-->Output Files-->Program Database File Name to change it and to use $(IntDir)$(ProjectName).pdb.Outpoint
Question 3. The custom step is to copy the SharedPCH project's output(xxx.pdb and xxx.idb file) into the custom output file for debugging the shared project and It has nothing to do with the delete operation. After all, debug configuration needs these files. So as you mentioned, they should be contained since the shared project is referenced by project 1 and 2.For the delete problem, it really has nothing to do with itself, you need to recheck your project to see what changes have been made or revert to the original project.Outpoint
Hello! Thanks for your answers. Well, I did solve my problems. That was the first time I had looked into MSBuild and project file structure and its advanced options, and I was just overwhelmed by information and details. Yes, I had some edits in the project files.Billie
First, for some reason (I did this or not) the generated by compiler .pdb file was not $(PlatformToolsetVersion).pdb, but $(ProjectName).pdb . So the copied shared .pdb file was pch.pdb in my case, while other projects were expecting different names. And that was triggering a DELETE task in Microsoft.CppCommon.targets , ("Delete the pch file if the pdb file has been deleted."). Instead of changing the output .pdb name I just looked into XCOPY command and made it to change the copied filename to an expected by a specific project.Billie
Then I also changed the generated by Linker output .pdb, just added "Linked" suffix to the name, so there are no conflicts between Compiler's and Linker's pdb. Not sure if that is a good idea to change the default settings without a big reason :)Billie
Thanks for your detailed answer for this issue:) You could mark your own answer. Anyway, have a nice day!Outpoint
I don't understand this question. "PDB" refers to the Program Database for debugging, "PCH" to precompiled headers. A file named pch.pdb is really confusing. The extension is pdb so it's a Program Database file for debugging. It does not have the extension .pch so it has nothing to do with precompiled headers.Exile
@Exile in my case "pch" is the name of the precompiled header project. It generates "common.pch" from "common.hpp" and "common.cpp" and its "pch.pdb" for debugging, which is copied to other projects to add symbols for the precompiled code.Billie
B
4

For some reason (I did this or not) the generated by compiler .pdb file was not $(PlatformToolsetVersion).pdb, but $(ProjectName).pdb . So the copied into other project folders shared .pdb file was pch.pdb in my case, while other projects were expecting different names. And that was triggering a DELETE task in Microsoft.CppCommon.targets , ("Delete the pch file if the pdb file has been deleted."). Instead of changing the output .pdb name I just looked into XCOPY command and made it to change the copied filename to an expected by a specific project (actually then I just added a custom Target with a renaming Copy task right into the project file instead of using the CustomBuildStep calling a xcopy OS's command, as now I learned more about MSBuild).

Then I also changed the generated by Linker output .pdb, just added "Linked" suffix to the name, so there are no conflicts between Compiler's and Linker's PDBs. Not sure if that is a good idea to change the default settings without a big reason.

I guess it's better just to change the Compiler's output PDB to $(PlatformToolsetVersion).pdb , so all projects will use the same name.

That was the first time I had looked into MSBuild and advanced project settings, now it seems to be obvious, that a project using a shared .pdb wants some familiar .pdb name, not a random pch.pdb

Here is my custom Target imported into project files copying the shared .pdb only if it was rebuilt (.idb is not generated in my case):

<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>
Billie answered 11/5, 2020 at 8:31 Comment(0)
O
2

Did you use the sample code under the github link.

If so, you should download and then use that sample and if you create your own project, you should check your projects carefully.

Borrowing from this tutorial to your project, I think you need to pay attention to whether you have any additional custom targets in your xxx.vcxproj file to delete the PCH file. Therefore, you need to check each xxx.vcxproj file carefully. In vs, there will be no deletion of certain files due to the different .pdb file names of the PCH project and other projects, so check whether there are additional operations of your own.

1) Why the .pch file is deleted at the start of other projects compilation, which leads to a C1083 error (.pch not found), if PDB names are not equal, not like in that page?

First of All, make sure that there are no other option to delete PCH file in your projects.

The PCH project is to create a PCH file and the other two projects are to use such file. And every time when you build the two projects(reference the PCH project), and always execute the build of PCH project and then build the two project. So the PCH is always created and later be used in two projects.

Based on it, you should ensure that all three projects create and use the same address for the file.

SharedPCH project

enter image description here

ConsoleApplication1

enter image description here

ConsoleApplication2

enter image description here

In the sample code,the PCH file exists under SharedPchSample\Outputs\Intermediate\Shared\Win32\Debug.

2) I copy pch.pdb and pch.idb files using COPY command, is there a RENAME comand or something, if the copied pch.pdb should be named just like a dependent project's PDB? And where can I find a complete list of Custom Build Step command?

Custom Build Step is under every project-->Properties-->Custom Build Step-->Command Line, and then you can find it.That custom step is just CMD command. And you can execute CMD in that to do extra opertion.

Besides, I guess you want to make those xxx.pdb and xxx.idb be the same name of the project name in order to distinguish one from another. You can right-click on every project-->Properties-->C/C++-->Output Files-->Program Database File Name-->change it and to use $(IntDir)$(ProjectName).pdb. More about Custom Build Steps, you can refer to this link.

I don't understand the purpose of "Additional dependencies" and "Outputs" in Custom Build Step. Can I enter the .pch filename into the dependency list, so it won't be deleted? Does the output list need to contain the dependent project's PDB name, or the pch.pdb, or both?

Additional dependencies is set to use the PCH file's content in the project 1 and 2 which is similar to configuring the address of a reference class library in a c++ project. And I think it might be redundant and since the author has add it which implies that it is well-founded.

And Outputs is the author customized output path, the author changed the output address of the project, and started a new custom output path and a temporary output path.

Actually, the xxx.pch and its pdb and idb file will not be copied into outputpath. So the custom build step is to copied the files into temporary output path. And if you want to copied them into the final outputpath, you can also use these in CustomBuildStep.targets file:

<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>

And in fact, one project references another project, and the output files of the referenced project are automatically copied to the main project. Perhaps this is because the author's SharePCH project does not generate the pdb and idb files, so those files of the dependent project will not be found in the main project.

Outpoint answered 8/5, 2020 at 8:7 Comment(2)
" You can right-click on every project-->Properties-->C/C++-->Output Files-->Program Database File Name-->change it and to use $(IntDir)$(ProjectName).pdb" . Well that was the issue, every project want's its specific .pdb name , but the default name is $(IntDir)vc$(PlatformToolsetVersion).pdb . And as the copied pch.pdb (in my case) doesn't match a project's, It triggers a DELETE task for the shared .pch fileBillie
So yes, the renaming after copying fixed itBillie
W
0

I'd like to add that I had a similar situation where a shared .pch file was being deleted but for a different reason related to the .pdb file.

The reason was that the pdb formats were different across the exe and the PCH.lib. The PCH library project has its 'Project Properties -> C/C++ -> General -> Debug Information Format' set to 'C7 compatible (/Z7)'.

When I added a new project exe that depended on the PCH library I had forgotten that new projects default to using 'Program Database (/Zi)' for its 'Debug Information Format'.

So now when the main project is being built and linked with the PCH it would delete the PCH.pch file and complain that the .PCH is missing.

Having all projects with the same matching Debug Information Format was the fix to prevent the PCH from being deleted.

Wailoo answered 16/11, 2022 at 3:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.