Search code examples
c++visual-studiomsbuildprecompiled-headerscustom-build-step

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


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?


Solution

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