1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-20 04:24:36 +08:00

pchreuse: always ask the PCH reuse target for PDB information

The property settings set things up once, but nothing ensures that
post-reuse hookup that any property changes propagate. Instead, when
computing PDB information, if PCH reuse is enabled, just always use its
values.

Also drop enforcement at generate time of property value consistency as
it is now ignored when PCH reuse is in effect.

Additionally, if a target is PCH-reused, generate a PDB output directory
for it.

The `PchReuseFromIgnoreOwnProps` test failed previously because the
post-reuse link update of the consuming `PDB` properties are no longer
considered. The `PchReuseFromUseUpdatedProps` failed because the
post-reuse link did not update the copy of the properties added to
consuming reuse target properties.
This commit is contained in:
Ben Boeckel
2025-06-15 00:07:45 +02:00
parent 6e7da8aa95
commit 1d701491a2
20 changed files with 220 additions and 56 deletions

View File

@@ -9,6 +9,9 @@ compiler while building source files.
This property specifies the base name for the debug symbols file. This property specifies the base name for the debug symbols file.
If not set, the default is unspecified. If not set, the default is unspecified.
If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property
is ignored and the reusage target's value of this property is used instead.
.. versionadded:: 4.1 .. versionadded:: 4.1
Contents of ``COMPILE_PDB_NAME`` may use Contents of ``COMPILE_PDB_NAME`` may use

View File

@@ -13,5 +13,8 @@ This is the configuration-specific version of :prop_tgt:`COMPILE_PDB_NAME`.
Contents of ``COMPILE_PDB_NAME_<CONFIG>`` may use Contents of ``COMPILE_PDB_NAME_<CONFIG>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`. :manual:`generator expressions <cmake-generator-expressions(7)>`.
If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property
is ignored and the reusage target's value of this property is used instead.
.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_<CONFIG>` .. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_<CONFIG>`
.. include:: include/COMPILE_PDB_NOTE.rst .. include:: include/COMPILE_PDB_NOTE.rst

View File

@@ -21,5 +21,8 @@ This property is initialized by the value of the
:variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY` variable if it is :variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY` variable if it is
set when a target is created. set when a target is created.
If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property
is ignored and the reusage target's value of this property is used instead.
.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY` .. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY`
.. include:: include/COMPILE_PDB_NOTE.rst .. include:: include/COMPILE_PDB_NOTE.rst

View File

@@ -20,5 +20,8 @@ if it is set when a target is created.
Contents of ``COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`` may use Contents of ``COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`. :manual:`generator expressions <cmake-generator-expressions(7)>`.
If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property
is ignored and the reusage target's value of this property is used instead.
.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>` .. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>`
.. include:: include/COMPILE_PDB_NOTE.rst .. include:: include/COMPILE_PDB_NOTE.rst

View File

@@ -1269,6 +1269,12 @@ bool cmGeneratorTarget::GetPropertyAsBool(std::string const& prop) const
std::string cmGeneratorTarget::GetCompilePDBName( std::string cmGeneratorTarget::GetCompilePDBName(
std::string const& config) const std::string const& config) const
{ {
if (cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget()) {
if (reuseTarget != this) {
return reuseTarget->GetCompilePDBName(config);
}
}
// Check for a per-configuration output directory target property. // Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(config); std::string configUpper = cmSystemTools::UpperCase(config);
std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
@@ -1290,6 +1296,12 @@ std::string cmGeneratorTarget::GetCompilePDBName(
return components.prefix + pdbName + ".pdb"; return components.prefix + pdbName + ".pdb";
} }
if (this->PchReused) {
NameComponents const& components = GetFullNameInternalComponents(
config, cmStateEnums::RuntimeBinaryArtifact);
return cmStrCat(components.prefix, this->GetName(), ".pdb");
}
return ""; return "";
} }
@@ -4441,7 +4453,14 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind,
} }
} }
if (out.empty()) { if (out.empty()) {
return false; // A target which is PCH-reused must have a stable PDB output directory so
// that the PDB can be stably referred to when consuming the PCH file.
if (this->PchReused) {
out = cmStrCat(this->GetLocalGenerator()->GetCurrentBinaryDirectory(),
'/', this->GetName(), ".dir/");
} else {
return false;
}
} }
// Convert the output path to a full path in case it is // Convert the output path to a full path in case it is

View File

@@ -692,6 +692,7 @@ public:
std::vector<BT<std::string>> GetPrecompileHeaders( std::vector<BT<std::string>> GetPrecompileHeaders(
std::string const& config, std::string const& language) const; std::string const& config, std::string const& language) const;
void MarkAsPchReused() { this->PchReused = true; }
cmGeneratorTarget const* GetPchReuseTarget() const; cmGeneratorTarget const* GetPchReuseTarget() const;
cmGeneratorTarget* GetPchReuseTarget(); cmGeneratorTarget* GetPchReuseTarget();
std::vector<std::string> GetPchArchs(std::string const& config, std::vector<std::string> GetPchArchs(std::string const& config,
@@ -1520,6 +1521,7 @@ private:
std::map<cmSourceFile const*, ClassifiedFlags> SourceFlags; std::map<cmSourceFile const*, ClassifiedFlags> SourceFlags;
}; };
mutable std::map<std::string, InfoByConfig> Configs; mutable std::map<std::string, InfoByConfig> Configs;
bool PchReused = false;
}; };
class cmGeneratorTarget::TargetPropertyEntry class cmGeneratorTarget::TargetPropertyEntry

View File

@@ -387,38 +387,15 @@ bool cmGlobalGenerator::CheckTargetsForType() const
return failed; return failed;
} }
bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const void cmGlobalGenerator::MarkTargetsForPchReuse() const
{ {
if (!this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX")) {
return false;
}
bool failed = false;
for (auto const& generator : this->LocalGenerators) { for (auto const& generator : this->LocalGenerators) {
for (auto const& target : generator->GetGeneratorTargets()) { for (auto const& target : generator->GetGeneratorTargets()) {
if (!target->CanCompileSources() || if (auto* reuseTarget = target->GetPchReuseTarget()) {
target->GetProperty("ghs_integrity_app").IsOn()) { reuseTarget->MarkAsPchReused();
continue;
}
std::string const& reuseFrom =
target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM");
std::string const& compilePdb =
target->GetSafeProperty("COMPILE_PDB_NAME");
if (!reuseFrom.empty() && reuseFrom != compilePdb) {
std::string const e = cmStrCat(
"PRECOMPILE_HEADERS_REUSE_FROM property is set on target (\"",
target->GetName(),
"\"). Reusable precompile headers requires the COMPILE_PDB_NAME"
" property to have the value \"",
reuseFrom, "\"\n");
this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
target->GetBacktrace());
failed = true;
} }
} }
} }
return failed;
} }
bool cmGlobalGenerator::IsExportedTargetsFile( bool cmGlobalGenerator::IsExportedTargetsFile(
@@ -1550,6 +1527,8 @@ bool cmGlobalGenerator::Compute()
localGen->AddHelperCommands(); localGen->AddHelperCommands();
} }
this->MarkTargetsForPchReuse();
// Add automatically generated sources (e.g. unity build). // Add automatically generated sources (e.g. unity build).
// Add unity sources after computing compile features. Unity sources do // Add unity sources after computing compile features. Unity sources do
// not change the set of languages or features, but we need to know them // not change the set of languages or features, but we need to know them
@@ -1597,10 +1576,6 @@ bool cmGlobalGenerator::Compute()
return false; return false;
} }
if (this->CheckTargetsForPchCompilePdb()) {
return false;
}
for (auto const& localGen : this->LocalGenerators) { for (auto const& localGen : this->LocalGenerators) {
localGen->ComputeHomeRelativeOutputPath(); localGen->ComputeHomeRelativeOutputPath();
} }

View File

@@ -858,7 +858,7 @@ private:
void CheckTargetLinkLibraries() const; void CheckTargetLinkLibraries() const;
bool CheckTargetsForMissingSources() const; bool CheckTargetsForMissingSources() const;
bool CheckTargetsForType() const; bool CheckTargetsForType() const;
bool CheckTargetsForPchCompilePdb() const; void MarkTargetsForPchReuse() const;
void CreateLocalGenerators(); void CreateLocalGenerators();

View File

@@ -2172,12 +2172,6 @@ void cmTarget::SetProperty(std::string const& prop, cmValue value)
this->impl->Properties.SetProperty(prop, reusedFrom); this->impl->Properties.SetProperty(prop, reusedFrom);
reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom);
reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
cmStrCat(reusedFrom, ".dir/"));
cmValue tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
this->SetProperty("COMPILE_PDB_NAME", tmp);
this->AddUtility(reusedFrom, false, this->impl->Makefile); this->AddUtility(reusedFrom, false, this->impl->Makefile);
} else if (prop == propC_STANDARD || prop == propCXX_STANDARD || } else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
prop == propCUDA_STANDARD || prop == propHIP_STANDARD || prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||

View File

@@ -0,0 +1,19 @@
if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC"))
find_file(pdb_file
NAMES NOT_USED.pdb
PATHS "${RunCMake_TEST_BINARY_DIR}"
PATH_SUFFIXES NOT_USED NOT_USED_DEBUG)
if (EXISTS "${pdb_file}")
list(APPEND RunCMake_TEST_FAILED
"PDB file was created from properties meant to be ignored")
endif ()
if (EXISTS "${RunCMake_TEST_BINARY_DIR}/mycustomdir")
list(APPEND RunCMake_TEST_FAILED
"PDB output directory ('mycustomdir') was created (should have used debug variant)")
endif ()
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/mycustomdir_debug")
list(APPEND RunCMake_TEST_FAILED
"PDB output directory ('mycustomdir_debug') was not created (separate PDBs required)")
endif ()
endif ()

View File

@@ -0,0 +1,2 @@
((Classic Intel)?Warning #672: the command line options do not match those used[^
]*)?

View File

@@ -0,0 +1,66 @@
enable_language(CXX)
if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
endif()
######################################################################
file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[
void nothing()
{
}
]=])
file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[
#include <string.h>
namespace std {
struct string
{
char storage[20];
string(const char* s) {
strcpy(storage, s);
}
const char* c_str() const {
return storage;
}
};
}
]=])
add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx)
target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx)
######################################################################
file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[
#include "message.hxx"
#ifndef HAVE_PCH_SUPPORT
#include "string.hxx"
#endif
const char* message()
{
static std::string greeting("hi there");
return greeting.c_str();
}
]=])
file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[
const char* message();
]=])
add_library(ignored_props ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(ignored_props REUSE_FROM pch-generator)
target_include_directories(ignored_props PRIVATE ${CMAKE_BINARY_DIR})
set_target_properties(ignored_props
PROPERTIES
COMPILE_PDB_NAME "NOT_USED"
COMPILE_PDB_NAME_DEBUG "NOT_USED_DEBUG"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/mycustomdir"
COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/mycustomdir_debug")

View File

@@ -0,0 +1,16 @@
if(MSVC)
find_file(pdb_file
NAMES custom-post.pdb custom-post-debug.pdb
PATHS "${RunCMake_TEST_BINARY_DIR}"
PATH_SUFFIXES custom custom-debug)
if (NOT EXISTS "${pdb_file}")
list(APPEND RunCMake_TEST_FAILED
"PDB file was not created from properties updated after reuse link")
endif ()
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/custom" AND
NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/custom-debug")
list(APPEND RunCMake_TEST_FAILED
"Updated PDB output directory ('custom' or 'custom-debug') was not created")
endif ()
endif ()

View File

@@ -0,0 +1,2 @@
((Classic Intel)?Warning #672: the command line options do not match those used[^
]*)?

View File

@@ -0,0 +1,66 @@
enable_language(CXX)
if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
endif()
######################################################################
file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[
void nothing()
{
}
]=])
file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[
#include <string.h>
namespace std {
struct string
{
char storage[20];
string(const char* s) {
strcpy(storage, s);
}
const char* c_str() const {
return storage;
}
};
}
]=])
add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx)
target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx)
######################################################################
file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[
#include "message.hxx"
#ifndef HAVE_PCH_SUPPORT
#include "string.hxx"
#endif
const char* message()
{
static std::string greeting("hi there");
return greeting.c_str();
}
]=])
file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[
const char* message();
]=])
add_library(updated_props ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(updated_props REUSE_FROM pch-generator)
target_include_directories(updated_props PRIVATE ${CMAKE_BINARY_DIR})
set_target_properties(pch-generator
PROPERTIES
COMPILE_PDB_NAME "custom-post"
COMPILE_PDB_NAME_DEBUG "custom-post-debug"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/custom"
COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/custom-debug")

View File

@@ -8,6 +8,13 @@ function(run_test name)
run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug) run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug)
endfunction() endfunction()
function(run_build_verbose name)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
run_cmake(${name})
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --verbose --config Debug)
endfunction()
run_cmake(DisabledPch) run_cmake(DisabledPch)
run_cmake(PchDebugGenex) run_cmake(PchDebugGenex)
run_test(PchInterface) run_test(PchInterface)
@@ -22,6 +29,8 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
endif() endif()
run_test(PchReuseFromPrefixed) run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir) run_test(PchReuseFromSubdir)
run_build_verbose(PchReuseFromIgnoreOwnProps)
run_build_verbose(PchReuseFromUseUpdatedProps)
run_cmake(PchMultilanguage) run_cmake(PchMultilanguage)
if(RunCMake_GENERATOR MATCHES "Make|Ninja") if(RunCMake_GENERATOR MATCHES "Make|Ninja")
run_cmake(PchWarnInvalid) run_cmake(PchWarnInvalid)

View File

@@ -43,7 +43,6 @@ run_cmake(VsDpiAware)
run_cmake(VsDpiAwareBadParam) run_cmake(VsDpiAwareBadParam)
run_cmake(VsForceInclude) run_cmake(VsForceInclude)
run_cmake(VsPrecompileHeaders) run_cmake(VsPrecompileHeaders)
run_cmake(VsPrecompileHeadersReuseFromCompilePDBName)
run_cmake(VsDeployEnabled) run_cmake(VsDeployEnabled)
run_cmake(VsSettings) run_cmake(VsSettings)
run_cmake(VsSourceSettingsTool) run_cmake(VsSourceSettingsTool)

View File

@@ -1,7 +0,0 @@
CMake Error at VsPrecompileHeadersReuseFromCompilePDBName.cmake:6 \(add_library\):
PRECOMPILE_HEADERS_REUSE_FROM property is set on target \("b"\). Reusable
precompile headers requires the COMPILE_PDB_NAME property to have the value
"a"
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@@ -1,9 +0,0 @@
project(VsPrecompileHeadersReuseFromCompilePDBName CXX)
add_library(a SHARED empty.cxx)
target_precompile_headers(a PRIVATE <windows.h>)
add_library(b SHARED empty.cxx)
target_precompile_headers(b REUSE_FROM a)
set_target_properties(b PROPERTIES COMPILE_PDB_NAME b)