Преглед изворни кода

GenEx: Add support for PDB_NAME and COMPILE_PDB_NAME

Closes: #26729
Giacomo Rombaut пре 8 месеци
родитељ
комит
15a1769bd8

+ 5 - 0
Help/prop_tgt/COMPILE_PDB_NAME.rst

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

+ 5 - 0
Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst

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

+ 5 - 0
Help/prop_tgt/PDB_NAME.rst

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

+ 5 - 0
Help/prop_tgt/PDB_NAME_CONFIG.rst

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

+ 5 - 0
Help/release/dev/pdb-name-genex-support.rst

@@ -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)>`.

+ 47 - 33
Source/cmGeneratorTarget.cxx

@@ -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);
-  }
+    // 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");
+    // PDB_NAME
+    props.emplace_back("PDB_NAME");
 
-  for (std::string const& p : props) {
-    if (cmValue outName = this->GetProperty(p)) {
-      base = *outName;
-      break;
+    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);
-  }
-
-  // PDB_NAME
-  props.emplace_back("PDB_NAME");
+  std::string base = this->GetPDBOutputName(config);
 
-  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(

+ 3 - 0
Source/cmGeneratorTarget.h

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

+ 1 - 2
Tests/RunCMake/GenEx-TARGET_FILE/OUTPUT_NAME-recursion-stderr.txt

@@ -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\):

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/PDB_NAME-recursion-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/GenEx-TARGET_FILE/PDB_NAME-recursion-stderr.txt

@@ -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\)

+ 6 - 0
Tests/RunCMake/GenEx-TARGET_FILE/PDB_NAME-recursion.cmake

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

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake

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