GenEx: Add support for PDB_NAME and COMPILE_PDB_NAME

Closes: #26729
This commit is contained in:
Giacomo Rombaut 2025-03-03 14:57:42 +01:00 committed by Brad King
parent aab6f9f3f4
commit 15a1769bd8
12 changed files with 95 additions and 37 deletions

View File

@ -9,5 +9,10 @@ compiler while building source files.
This property specifies the base name for the debug symbols file.
If not set, the default is unspecified.
.. versionadded:: 4.1
Contents of ``COMPILE_PDB_NAME`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME`
.. include:: COMPILE_PDB_NOTE.txt

View File

@ -8,5 +8,10 @@ generated by the compiler while building source files.
This is the configuration-specific version of :prop_tgt:`COMPILE_PDB_NAME`.
.. versionadded:: 4.1
Contents of ``COMPILE_PDB_NAME_<CONFIG>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_<CONFIG>`
.. include:: COMPILE_PDB_NOTE.txt

View File

@ -8,5 +8,10 @@ This property specifies the base name for the debug symbols file.
If not set, the :prop_tgt:`OUTPUT_NAME` target property value or
logical target name is used by default.
.. versionadded:: 4.1
Contents of ``PDB_NAME`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME`
.. include:: PDB_NOTE.txt

View File

@ -6,5 +6,10 @@ generated by the linker for an executable or shared library target.
This is the configuration-specific version of :prop_tgt:`PDB_NAME`.
.. versionadded:: 4.1
Contents of ``PDB_NAME_<CONFIG>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME_<CONFIG>`
.. include:: PDB_NOTE.txt

View File

@ -0,0 +1,5 @@
pdb-name-genex-support
----------------------
* The :prop_tgt:`PDB_NAME` and :prop_tgt:`COMPILE_PDB_NAME` target properties
now support :manual:`generator expressions <cmake-generator-expressions(7)>`.

View File

@ -1274,16 +1274,20 @@ std::string cmGeneratorTarget::GetCompilePDBName(
std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
cmValue config_name = this->GetProperty(configProp);
if (cmNonempty(config_name)) {
std::string pdbName = cmGeneratorExpression::Evaluate(
*config_name, this->LocalGenerator, config, this);
NameComponents const& components = GetFullNameInternalComponents(
config, cmStateEnums::RuntimeBinaryArtifact);
return components.prefix + *config_name + ".pdb";
return components.prefix + pdbName + ".pdb";
}
cmValue name = this->GetProperty("COMPILE_PDB_NAME");
if (cmNonempty(name)) {
std::string pdbName = cmGeneratorExpression::Evaluate(
*name, this->LocalGenerator, config, this);
NameComponents const& components = GetFullNameInternalComponents(
config, cmStateEnums::RuntimeBinaryArtifact);
return components.prefix + *name + ".pdb";
return components.prefix + pdbName + ".pdb";
}
return "";
@ -3771,27 +3775,50 @@ bool cmGeneratorTarget::LinkerEnforcesNoAllowShLibUndefined(
std::string cmGeneratorTarget::GetPDBOutputName(
std::string const& config) const
{
std::string base =
this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact) +
this->GetFilePostfix(config);
// Lookup/compute/cache the pdb output name for this configuration.
auto i = this->PdbOutputNameMap.find(config);
if (i == this->PdbOutputNameMap.end()) {
// Add empty name in map to detect potential recursion.
PdbOutputNameMapType::value_type entry(config, "");
i = this->PdbOutputNameMap.insert(entry).first;
std::vector<std::string> props;
std::string configUpper = cmSystemTools::UpperCase(config);
if (!configUpper.empty()) {
// PDB_NAME_<CONFIG>
props.push_back("PDB_NAME_" + configUpper);
}
// PDB_NAME
props.emplace_back("PDB_NAME");
for (std::string const& p : props) {
if (cmValue outName = this->GetProperty(p)) {
base = *outName;
break;
// Compute output name.
std::vector<std::string> props;
std::string configUpper = cmSystemTools::UpperCase(config);
if (!configUpper.empty()) {
// PDB_NAME_<CONFIG>
props.push_back("PDB_NAME_" + configUpper);
}
// PDB_NAME
props.emplace_back("PDB_NAME");
std::string outName;
for (std::string const& p : props) {
if (cmValue outNameProp = this->GetProperty(p)) {
outName = *outNameProp;
break;
}
}
// Now evaluate genex and update the previously-prepared map entry.
if (outName.empty()) {
i->second =
this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact) +
this->GetFilePostfix(config);
} else {
i->second =
cmGeneratorExpression::Evaluate(outName, this->LocalGenerator, config);
}
} else if (i->second.empty()) {
// An empty map entry indicates we have been called recursively
// from the above block.
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR,
"Target '" + this->GetName() + "' PDB_NAME depends on itself.",
this->GetBacktrace());
}
return base;
return i->second;
}
std::string cmGeneratorTarget::GetPDBName(std::string const& config) const
@ -3799,22 +3826,9 @@ std::string cmGeneratorTarget::GetPDBName(std::string const& config) const
NameComponents const& parts = this->GetFullNameInternalComponents(
config, cmStateEnums::RuntimeBinaryArtifact);
std::vector<std::string> props;
std::string configUpper = cmSystemTools::UpperCase(config);
if (!configUpper.empty()) {
// PDB_NAME_<CONFIG>
props.push_back("PDB_NAME_" + configUpper);
}
std::string base = this->GetPDBOutputName(config);
// PDB_NAME
props.emplace_back("PDB_NAME");
for (std::string const& p : props) {
if (cmValue outName = this->GetProperty(p)) {
return parts.prefix + *outName + ".pdb";
}
}
return parts.prefix + parts.base + ".pdb";
return parts.prefix + base + ".pdb";
}
std::string cmGeneratorTarget::GetObjectDirectory(

View File

@ -1372,6 +1372,9 @@ private:
using OutputInfoMapType = std::map<std::string, OutputInfo>;
mutable OutputInfoMapType OutputInfoMap;
using PdbOutputNameMapType = std::map<std::string, std::string>;
mutable PdbOutputNameMapType PdbOutputNameMap;
using ModuleDefinitionInfoMapType =
std::map<std::string, ModuleDefinitionInfo>;
mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap;

View File

@ -2,8 +2,7 @@ CMake Error at OUTPUT_NAME-recursion.cmake:[0-9]+ \(add_executable\):
Target 'empty1' OUTPUT_NAME depends on itself.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
.*
CMake Error at OUTPUT_NAME-recursion.cmake:[0-9]+ \(add_executable\):
Target 'empty2' OUTPUT_NAME depends on itself.
Call Stack \(most recent call first\):

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,9 @@
CMake Error at PDB_NAME-recursion.cmake:[0-9]+ \(add_executable\):
Target 'empty1' PDB_NAME depends on itself.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
.*
CMake Error at PDB_NAME-recursion.cmake:[0-9]+ \(add_executable\):
Target 'empty2' PDB_NAME depends on itself.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,6 @@
enable_language(C)
add_executable(empty1 empty.c)
set_property(TARGET empty1 PROPERTY PDB_NAME $<TARGET_PDB_FILE_NAME:empty1>)
add_executable(empty2 empty.c)
set_property(TARGET empty2 PROPERTY OUTPUT_NAME $<TARGET_PDB_FILE_BASE_NAME:empty2>)

View File

@ -32,6 +32,7 @@ run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)
run_cmake(ImportedTarget-TARGET_PDB_FILE)
run_cmake(ImportedTarget-TARGET_PDB_FILE_BASE_NAME)
if(LINKER_SUPPORTS_PDB)
run_cmake(PDB_NAME-recursion)
run_cmake(NonValidTarget-TARGET_PDB_FILE)
run_cmake(ValidTarget-TARGET_PDB_FILE)
run_cmake(NonValidTarget-TARGET_PDB_FILE_BASE_NAME)