Merge topic 'pchreuse-refactor'

11ee18b758 ci: extend msvc_v71_nmake `RunCMake.PrecompileHeaders` test timeout
1c91fadbe8 Tests/RunCMake/PrecompileHeaders: support extended timeout
42f2867b3b pchreuse: defer dependency addition until generation time
f9bc615d9a pchreuse: ban PCH reuse from targets which disable PCH
f78f592b78 pchreuse: defer target existence enforcement to generation time
3ef773490d pchreuse: defer PCH consistency checks to generation time
1d701491a2 pchreuse: always ask the PCH reuse target for PDB information
6e7da8aa95 cmGeneratorTarget: factor out reuse target computation
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Acked-by: alcroito <alexandru.croitor@qt.io>
Acked-by: Vincent X <gulackeg@gmail.com>
Merge-request: !10887
This commit is contained in:
Brad King
2025-07-23 16:06:30 +00:00
committed by Kitware Robot
40 changed files with 716 additions and 179 deletions

View File

@@ -1 +1,3 @@
set(CMake_TEST_PrecompileHeaders_TIMEOUT 1000 CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_msvc_common.cmake")

View File

@@ -9,6 +9,9 @@ compiler while building source files.
This property specifies the base name for the debug symbols file.
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
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
: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>`
.. 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
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`
.. 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
: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>`
.. include:: include/COMPILE_PDB_NOTE.rst

View File

@@ -1008,6 +1008,10 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
cmLinkItem(i.Value.first, i.Value.second, i.Backtrace));
}
}
if (cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget()) {
this->UtilityItems.insert(
cmLinkItem(reuseTarget, false, cmListFileBacktrace()));
}
}
return this->UtilityItems;
}
@@ -1269,6 +1273,12 @@ bool cmGeneratorTarget::GetPropertyAsBool(std::string const& prop) const
std::string cmGeneratorTarget::GetCompilePDBName(
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.
std::string configUpper = cmSystemTools::UpperCase(config);
std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
@@ -1290,6 +1300,14 @@ std::string cmGeneratorTarget::GetCompilePDBName(
return components.prefix + pdbName + ".pdb";
}
// If the target is PCH-reused, we need a stable name for the PDB file so
// that reusing targets can construct a stable name for it.
if (this->PchReused) {
NameComponents const& components = GetFullNameInternalComponents(
config, cmStateEnums::RuntimeBinaryArtifact);
return cmStrCat(components.prefix, this->GetName(), ".pdb");
}
return "";
}
@@ -2799,6 +2817,122 @@ std::string cmGeneratorTarget::GetClangTidyExportFixesDirectory(
return cmSystemTools::CollapseFullPath(path);
}
struct CycleWatcher
{
CycleWatcher(bool& flag)
: Flag(flag)
{
this->Flag = true;
}
~CycleWatcher() { this->Flag = false; }
bool& Flag;
};
cmGeneratorTarget const* cmGeneratorTarget::GetPchReuseTarget() const
{
if (this->ComputingPchReuse) {
// TODO: Get the full cycle.
if (!this->PchReuseCycleDetected) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Circular PCH reuse target involving '", this->GetName(),
'\''));
}
this->PchReuseCycleDetected = true;
return nullptr;
}
CycleWatcher watch(this->ComputingPchReuse);
(void)watch;
cmValue pchReuseFrom = this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (!pchReuseFrom) {
return nullptr;
}
cmGeneratorTarget const* generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
if (!generatorTarget) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Target \"", *pchReuseFrom, "\" for the \"", this->GetName(),
R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property does not exist.)"));
}
if (this->GetProperty("PRECOMPILE_HEADERS").IsOn()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("PRECOMPILE_HEADERS property is already set on target (\"",
this->GetName(), "\")\n"));
}
if (generatorTarget) {
if (generatorTarget->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Target \"", *pchReuseFrom, "\" for the \"", this->GetName(),
R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property has set "DISABLE_PRECOMPILE_HEADERS".)"));
return nullptr;
}
if (auto const* recurseReuseTarget =
generatorTarget->GetPchReuseTarget()) {
return recurseReuseTarget;
}
}
return generatorTarget;
}
cmGeneratorTarget* cmGeneratorTarget::GetPchReuseTarget()
{
if (this->ComputingPchReuse) {
// TODO: Get the full cycle.
if (!this->PchReuseCycleDetected) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Circular PCH reuse target involving '", this->GetName(),
'\''));
}
this->PchReuseCycleDetected = true;
return nullptr;
}
CycleWatcher watch(this->ComputingPchReuse);
(void)watch;
cmValue pchReuseFrom = this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (!pchReuseFrom) {
return nullptr;
}
cmGeneratorTarget* generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
if (!generatorTarget) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Target \"", *pchReuseFrom, "\" for the \"", this->GetName(),
R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property does not exist.)"));
}
if (this->GetProperty("PRECOMPILE_HEADERS").IsOn()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("PRECOMPILE_HEADERS property is already set on target (\"",
this->GetName(), "\")\n"));
}
if (generatorTarget) {
if (generatorTarget->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Target \"", *pchReuseFrom, "\" for the \"", this->GetName(),
R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property has set "DISABLE_PRECOMPILE_HEADERS".)"));
return nullptr;
}
if (auto* recurseReuseTarget = generatorTarget->GetPchReuseTarget()) {
return recurseReuseTarget;
}
}
return generatorTarget;
}
std::vector<std::string> cmGeneratorTarget::GetPchArchs(
std::string const& config, std::string const& lang) const
{
@@ -2826,24 +2960,22 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config,
return std::string();
}
cmGeneratorTarget const* generatorTarget = this;
cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget();
bool const haveReuseTarget = reuseTarget && reuseTarget != this;
if (reuseTarget) {
generatorTarget = reuseTarget;
}
auto const inserted =
this->PchHeaders.insert(std::make_pair(language + config + arch, ""));
if (inserted.second) {
std::vector<BT<std::string>> const headers =
this->GetPrecompileHeaders(config, language);
if (headers.empty() && !pchReuseFrom) {
if (headers.empty() && !haveReuseTarget) {
return std::string();
}
std::string& filename = inserted.first->second;
if (pchReuseFrom) {
generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
}
std::map<std::string, std::string> const languageToExtension = {
{ "C", ".h" },
{ "CXX", ".hxx" },
@@ -2862,7 +2994,7 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config,
languageToExtension.at(language));
std::string const filename_tmp = cmStrCat(filename, ".tmp");
if (!pchReuseFrom) {
if (!haveReuseTarget) {
cmValue pchPrologue =
this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
cmValue pchEpilogue =
@@ -2937,11 +3069,10 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config,
std::string& filename = inserted.first->second;
cmGeneratorTarget const* generatorTarget = this;
cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (pchReuseFrom) {
generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget();
bool const haveReuseTarget = reuseTarget && reuseTarget != this;
if (reuseTarget) {
generatorTarget = reuseTarget;
}
filename =
@@ -2968,7 +3099,7 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config,
}
std::string const filename_tmp = cmStrCat(filename, ".tmp");
if (!pchReuseFrom) {
if (!haveReuseTarget) {
{
cmGeneratedFileStream file(filename_tmp);
file << "/* generated by CMake */\n";
@@ -3034,11 +3165,9 @@ std::string cmGeneratorTarget::GetPchFile(std::string const& config,
};
cmGeneratorTarget* generatorTarget = this;
cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (pchReuseFrom) {
generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
cmGeneratorTarget* reuseTarget = this->GetPchReuseTarget();
if (reuseTarget) {
generatorTarget = reuseTarget;
}
std::string const pchFileObject =
@@ -4428,7 +4557,12 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind,
}
}
if (out.empty()) {
return false;
// Compile output should always have a path.
if (kind == "COMPILE_PDB"_s) {
out = this->GetSupportDirectory();
} else {
return false;
}
}
// Convert the output path to a full path in case it is

View File

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

View File

@@ -387,38 +387,15 @@ bool cmGlobalGenerator::CheckTargetsForType() const
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& target : generator->GetGeneratorTargets()) {
if (!target->CanCompileSources() ||
target->GetProperty("ghs_integrity_app").IsOn()) {
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;
if (auto* reuseTarget = target->GetPchReuseTarget()) {
reuseTarget->MarkAsPchReused();
}
}
}
return failed;
}
bool cmGlobalGenerator::IsExportedTargetsFile(
@@ -1550,6 +1527,8 @@ bool cmGlobalGenerator::Compute()
localGen->AddHelperCommands();
}
this->MarkTargetsForPchReuse();
// Add automatically generated sources (e.g. unity build).
// Add unity sources after computing compile features. Unity sources do
// not change the set of languages or features, but we need to know them
@@ -1597,10 +1576,6 @@ bool cmGlobalGenerator::Compute()
return false;
}
if (this->CheckTargetsForPchCompilePdb()) {
return false;
}
for (auto const& localGen : this->LocalGenerators) {
localGen->ComputeHomeRelativeOutputPath();
}

View File

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

View File

@@ -2779,8 +2779,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
continue;
}
cmValue ReuseFrom =
target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
auto* reuseTarget = target->GetPchReuseTarget();
bool const haveReuseTarget = reuseTarget && reuseTarget != target;
auto* pch_sf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
@@ -2789,7 +2789,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
pch_sf->SetProperty("CXX_SCAN_FOR_MODULES", "0");
if (!this->GetGlobalGenerator()->IsXcode()) {
if (!ReuseFrom) {
if (!haveReuseTarget) {
target->AddSource(pchSource, true);
}
@@ -2797,14 +2797,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
// Exclude the pch files from linking
if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
if (!ReuseFrom) {
if (!haveReuseTarget) {
pch_sf->AppendProperty(
"OBJECT_OUTPUTS",
cmStrCat("$<$<CONFIG:", config, ">:", pchFile, '>'));
} else {
auto* reuseTarget =
this->GlobalGenerator->FindGeneratorTarget(*ReuseFrom);
if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) {
std::string const compilerId =
@@ -2850,11 +2847,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
}
if (editAndContinueDebugInfo || msvc2008OrLess) {
this->CopyPchCompilePdb(config, lang, target, *ReuseFrom,
reuseTarget, { ".pdb", ".idb" });
this->CopyPchCompilePdb(config, lang, target, reuseTarget,
{ ".pdb", ".idb" });
} else if (programDatabaseDebugInfo) {
this->CopyPchCompilePdb(config, lang, target, *ReuseFrom,
reuseTarget, { ".pdb" });
this->CopyPchCompilePdb(config, lang, target, reuseTarget,
{ ".pdb" });
}
}
@@ -2906,18 +2903,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
void cmLocalGenerator::CopyPchCompilePdb(
std::string const& config, std::string const& language,
cmGeneratorTarget* target, std::string const& ReuseFrom,
cmGeneratorTarget* reuseTarget, std::vector<std::string> const& extensions)
cmGeneratorTarget* target, cmGeneratorTarget* reuseTarget,
std::vector<std::string> const& extensions)
{
std::string const pdb_prefix =
this->GetGlobalGenerator()->IsMultiConfig() ? cmStrCat(config, '/') : "";
std::string const target_compile_pdb_dir =
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
target->GetName(), ".dir/");
std::string const copy_script =
cmStrCat(target_compile_pdb_dir, "copy_idb_pdb_", config, ".cmake");
std::string const copy_script = cmStrCat(target->GetSupportDirectory(),
"/copy_idb_pdb_", config, ".cmake");
cmGeneratedFileStream file(copy_script);
file << "# CMake generated file\n";
@@ -2926,28 +2916,37 @@ void cmLocalGenerator::CopyPchCompilePdb(
<< "# by mspdbsrv. The foreach retry loop is needed to make sure\n"
<< "# the pdb file is ready to be copied.\n\n";
auto configGenex = [&](cm::string_view expr) -> std::string {
if (this->GetGlobalGenerator()->IsMultiConfig()) {
return cmStrCat("$<$<CONFIG:", config, ">:", expr, '>');
}
return std::string(expr);
};
std::vector<std::string> outputs;
auto replaceExtension = [](std::string const& path,
std::string const& ext) -> std::string {
auto const dir = cmSystemTools::GetFilenamePath(path);
auto const base = cmSystemTools::GetFilenameWithoutLastExtension(path);
if (dir.empty()) {
return cmStrCat(base, ext);
}
return cmStrCat(dir, '/', base, ext);
};
for (auto const& extension : extensions) {
std::string const from_file =
cmStrCat(reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(),
'/', ReuseFrom, ".dir/${PDB_PREFIX}", ReuseFrom, extension);
std::string const to_dir =
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
target->GetName(), ".dir/${PDB_PREFIX}");
std::string const to_file = cmStrCat(to_dir, ReuseFrom, extension);
std::string dest_file = to_file;
std::string const& prefix = target->GetSafeProperty("PREFIX");
if (!prefix.empty()) {
dest_file = cmStrCat(to_dir, prefix, ReuseFrom, extension);
}
replaceExtension(reuseTarget->GetCompilePDBPath(config), extension);
std::string const to_dir = target->GetCompilePDBDirectory(config);
std::string const to_file = cmStrCat(
replaceExtension(reuseTarget->GetCompilePDBName(config), extension),
'/');
std::string const dest_file = cmStrCat(to_dir, to_file);
file << "foreach(retry RANGE 1 30)\n";
file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \""
<< dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \""
<< dest_file << "\" OR NOT \"" << dest_file << "\" IS_NEWER_THAN \""
<< from_file << "\"))\n";
file << " file(MAKE_DIRECTORY \"" << to_dir << "\")\n";
file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy";
file << " \"" << from_file << "\""
<< " \"" << to_dir << "\" RESULT_VARIABLE result "
@@ -2956,10 +2955,6 @@ void cmLocalGenerator::CopyPchCompilePdb(
<< " execute_process(COMMAND ${CMAKE_COMMAND}"
<< " -E sleep 1)\n"
<< " else()\n";
if (!prefix.empty()) {
file << " file(REMOVE \"" << dest_file << "\")\n";
file << " file(RENAME \"" << to_file << "\" \"" << dest_file << "\")\n";
}
file << " break()\n"
<< " endif()\n";
file << " elseif(NOT EXISTS \"" << from_file << "\")\n"
@@ -2967,31 +2962,24 @@ void cmLocalGenerator::CopyPchCompilePdb(
<< " -E sleep 1)\n"
<< " endif()\n";
file << "endforeach()\n";
outputs.push_back(configGenex(dest_file));
}
auto configGenex = [&](cm::string_view expr) -> std::string {
if (this->GetGlobalGenerator()->IsMultiConfig()) {
return cmStrCat("$<$<CONFIG:", config, ">:", expr, '>');
}
return std::string(expr);
};
cmCustomCommandLines commandLines =
cmMakeSingleCommandLine({ configGenex(cmSystemTools::GetCMakeCommand()),
configGenex("-P"), configGenex(copy_script) });
cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
{ configGenex(cmSystemTools::GetCMakeCommand()),
configGenex(cmStrCat("-DPDB_PREFIX=", pdb_prefix)), configGenex("-P"),
configGenex(copy_script) });
char const* no_message = "";
std::vector<std::string> outputs;
outputs.push_back(configGenex(
cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb")));
auto const comment =
cmStrCat("Copying PDB for PCH reuse from ", reuseTarget->GetName(),
" for ", target->GetName());
;
auto cc = cm::make_unique<cmCustomCommand>();
cc->SetCommandLines(commandLines);
cc->SetComment(no_message);
cc->SetComment(comment.c_str());
cc->SetStdPipesUTF8(true);
cc->AppendDepends({ reuseTarget->GetPchFile(config, language) });
cc->AppendDepends(
{ reuseTarget->GetPchFile(config, language), copy_script });
if (this->GetGlobalGenerator()->IsVisualStudio()) {
cc->SetByproducts(outputs);
@@ -3007,9 +2995,6 @@ void cmLocalGenerator::CopyPchCompilePdb(
target->AddSource(copy_rule->ResolveFullPath());
}
}
target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
target_compile_pdb_dir);
}
cm::optional<std::string> cmLocalGenerator::GetMSVCDebugFormatName(

View File

@@ -640,7 +640,6 @@ private:
void CopyPchCompilePdb(std::string const& config,
std::string const& language,
cmGeneratorTarget* target,
std::string const& ReuseFrom,
cmGeneratorTarget* reuseTarget,
std::vector<std::string> const& extensions);

View File

@@ -1911,7 +1911,6 @@ MAKE_PROP(COMPILE_DEFINITIONS);
MAKE_PROP(COMPILE_FEATURES);
MAKE_PROP(COMPILE_OPTIONS);
MAKE_PROP(PRECOMPILE_HEADERS);
MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
MAKE_PROP(CUDA_CUBIN_COMPILATION);
MAKE_PROP(CUDA_FATBIN_COMPILATION);
MAKE_PROP(CUDA_OPTIX_COMPILATION);
@@ -2147,38 +2146,6 @@ void cmTarget::SetProperty(std::string const& prop, cmValue value)
this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
return;
}
} else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
if (this->GetProperty("PRECOMPILE_HEADERS")) {
std::ostringstream e;
e << "PRECOMPILE_HEADERS property is already set on target (\""
<< this->impl->Name << "\")\n";
this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
auto* reusedTarget = this->impl->Makefile->GetCMakeInstance()
->GetGlobalGenerator()
->FindTarget(value);
if (!reusedTarget) {
std::string const e(
"PRECOMPILE_HEADERS_REUSE_FROM set with non existing target");
this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
return;
}
std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
if (reusedFrom.empty()) {
reusedFrom = *value;
}
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);
} else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) {
@@ -2208,15 +2175,6 @@ void cmTarget::AppendProperty(std::string const& prop,
"imported targets (\"",
this->impl->Name, "\")\n"));
}
if (prop == propPRECOMPILE_HEADERS &&
this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"PRECOMPILE_HEADERS_REUSE_FROM property is already set on target (\"",
this->impl->Name, "\")\n"));
return;
}
UsageRequirementProperty* usageRequirements[] = {
&this->impl->IncludeDirectories,

View File

@@ -76,16 +76,27 @@ endif()
set(pdbs "")
foreach(t ${my_targets})
set(with_compile 0)
get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME)
get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY)
if(NOT pdb_name)
set(with_compile 1)
get_property(pdb_name TARGET ${t} PROPERTY COMPILE_PDB_NAME)
endif()
if(NOT pdb_dir)
get_property(pdb_dir TARGET ${t} PROPERTY COMPILE_PDB_OUTPUT_DIRECTORY)
endif()
if(NOT pdb_dir)
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
if (NOT with_compile)
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
elseif (CMAKE_GENERATOR MATCHES "Ninja" OR
CMAKE_GENERATOR MATCHES "Makefiles")
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${t}.dir)
elseif (CMAKE_GENERATOR MATCHES "Visual Studio")
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/${t}.dir)
else ()
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/${t}.dir)
endif ()
endif()
if (pdb_dir MATCHES "\\$<.*>")
# Skip per-configuration subdirectory if the value contained

View File

@@ -1340,6 +1340,12 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMAKE_C_SIMULATE_ID=${CMAKE_C_SIMULATE_ID}
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
# This test can take a long time due to the number of test cases.
# Provide an option to customize it.
if(DEFINED CMake_TEST_PrecompileHeaders_TIMEOUT)
set_property(TEST RunCMake.PrecompileHeaders PROPERTY TIMEOUT ${CMake_TEST_PrecompileHeaders_TIMEOUT})
endif()
add_RunCMake_test(UnityBuild -DCMake_TEST_OBJC=${CMake_TEST_OBJC} -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
set_property(TEST RunCMake.UnityBuild APPEND
PROPERTY LABELS "CUDA")

View File

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

View File

@@ -0,0 +1,60 @@
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(reuse_append ${CMAKE_BINARY_DIR}/message.cxx)
target_include_directories(reuse_append PRIVATE ${CMAKE_BINARY_DIR})
set_property(TARGET reuse_append PROPERTY PRECOMPILE_HEADERS_REUSE_FROM "pch-")
set_property(TARGET reuse_append APPEND_STRING PROPERTY PRECOMPILE_HEADERS_REUSE_FROM "generator")

View File

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

View File

@@ -0,0 +1,79 @@
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(pch_before_reuse_pch ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(pch_before_reuse_pch PRIVATE "${CMAKE_BINARY_DIR}/string.hxx")
target_precompile_headers(pch_before_reuse_pch REUSE_FROM pch-generator)
set_property(TARGET pch_before_reuse_pch PROPERTY PRECOMPILE_HEADERS_REUSE_FROM)
target_include_directories(pch_before_reuse_pch PRIVATE ${CMAKE_BINARY_DIR})
add_library(pch_before_reuse_reuse ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(pch_before_reuse_reuse PRIVATE "${CMAKE_BINARY_DIR}/string.hxx")
target_precompile_headers(pch_before_reuse_reuse REUSE_FROM pch-generator)
set_property(TARGET pch_before_reuse_reuse PROPERTY PRECOMPILE_HEADERS "")
target_include_directories(pch_before_reuse_reuse PRIVATE ${CMAKE_BINARY_DIR})
add_library(reuse_before_pch_pch ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(reuse_before_pch_pch REUSE_FROM pch-generator)
target_precompile_headers(reuse_before_pch_pch PRIVATE "${CMAKE_BINARY_DIR}/string.hxx")
set_property(TARGET reuse_before_pch_pch PROPERTY PRECOMPILE_HEADERS_REUSE_FROM)
target_include_directories(reuse_before_pch_pch PRIVATE ${CMAKE_BINARY_DIR})
add_library(reuse_before_pch_reuse ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(reuse_before_pch_reuse REUSE_FROM pch-generator)
target_precompile_headers(reuse_before_pch_reuse PRIVATE "${CMAKE_BINARY_DIR}/string.hxx")
set_property(TARGET reuse_before_pch_reuse PROPERTY PRECOMPILE_HEADERS "")
target_include_directories(reuse_before_pch_reuse PRIVATE ${CMAKE_BINARY_DIR})

View File

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

View File

@@ -0,0 +1,59 @@
enable_language(CXX)
if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
endif()
######################################################################
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(reuse_decl_order ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(reuse_decl_order REUSE_FROM pch-generator)
target_include_directories(reuse_decl_order PRIVATE ${CMAKE_BINARY_DIR})
######################################################################
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)

View File

@@ -1,4 +1,4 @@
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "")
string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -Zi")
include(PchReuseFrom-common.cmake)
include(PchReuseFrom-CMP0141-common.cmake)

View File

@@ -1,2 +1,2 @@
cmake_policy(SET CMP0141 NEW)
include(PchReuseFrom-common.cmake)
include(PchReuseFrom-CMP0141-common.cmake)

View File

@@ -1,2 +1,2 @@
cmake_policy(SET CMP0141 OLD)
include(PchReuseFrom-common.cmake)
include(PchReuseFrom-CMP0141-common.cmake)

View File

@@ -0,0 +1,2 @@
CMake Error in CMakeLists.txt:
Circular PCH reuse target involving 'first'

View File

@@ -0,0 +1,10 @@
enable_language(C)
add_library(first foo.c)
target_precompile_headers(first REUSE_FROM third)
add_library(second foo.c)
target_precompile_headers(second REUSE_FROM first)
add_library(third foo.c)
target_precompile_headers(third REUSE_FROM second)

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

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,4 @@
CMake Error in CMakeLists.txt:
Target "pch-generator" for the "reuse_from_nopch" target's
"PRECOMPILE_HEADERS_REUSE_FROM" property has set
"DISABLE_PRECOMPILE_HEADERS".

View File

@@ -0,0 +1,60 @@
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)
set_property(TARGET pch-generator PROPERTY DISABLE_PRECOMPILE_HEADERS 1)
######################################################################
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(reuse_from_nopch ${CMAKE_BINARY_DIR}/message.cxx)
target_precompile_headers(reuse_from_nopch REUSE_FROM pch-generator)
target_include_directories(reuse_from_nopch PRIVATE ${CMAKE_BINARY_DIR})

View File

@@ -8,6 +8,13 @@ function(run_test name)
run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug)
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(PchDebugGenex)
run_test(PchInterface)
@@ -22,7 +29,14 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
endif()
run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir)
run_build_verbose(PchReuseFromIgnoreOwnProps)
run_build_verbose(PchReuseFromUseUpdatedProps)
run_build_verbose(PchReuseConsistency)
run_cmake(PchReuseFromCycle)
run_cmake(PchReuseWithoutPch)
run_build_verbose(PchReuseAppend)
run_cmake(PchMultilanguage)
run_build_verbose(PchReuseDeclarationOrder)
if(RunCMake_GENERATOR MATCHES "Make|Ninja")
run_cmake(PchWarnInvalid)

View File

@@ -43,7 +43,6 @@ run_cmake(VsDpiAware)
run_cmake(VsDpiAwareBadParam)
run_cmake(VsForceInclude)
run_cmake(VsPrecompileHeaders)
run_cmake(VsPrecompileHeadersReuseFromCompilePDBName)
run_cmake(VsDeployEnabled)
run_cmake(VsSettings)
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)