소스 검색

Make internal TARGET_PROPERTY generator expressions more robust

While collecting usage requirements from the `INTERFACE_*` properties of
directly linked targets, we internally generate `TARGET_PROPERTY:` and
`TARGET_OBJECTS:` generator expressions to refer to those properties on
those targets.  At the point we generate these expressions we already
have a pointer to an exact `cmGeneratorTarget` instance.

Switch from using the target name in these generator expressions to
using an internal unique name generated for each `cmGeneratorTarget`
instance to be referenced.  This avoids depending on the user-facing
target name to find the same target we already have.
Brad King 7 년 전
부모
커밋
2f708f5d65
4개의 변경된 파일33개의 추가작업 그리고 3개의 파일을 삭제
  1. 3 1
      Source/cmGeneratorExpressionNode.cxx
  2. 8 2
      Source/cmGeneratorTarget.cxx
  3. 18 0
      Source/cmGlobalGenerator.cxx
  4. 4 0
      Source/cmGlobalGenerator.h

+ 3 - 1
Source/cmGeneratorExpressionNode.cxx

@@ -1054,7 +1054,9 @@ std::string getLinkedTargetsContent(
     // Don't follow such link interface entries so as not to create a
     // self-referencing loop.
     if (l.Target && l.Target != target) {
-      depString += sep + "$<TARGET_PROPERTY:" + l.Target->GetName() + "," +
+      std::string uniqueName =
+        target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target);
+      depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," +
         interfacePropertyName + ">";
       sep = ";";
     }

+ 8 - 2
Source/cmGeneratorTarget.cxx

@@ -819,8 +819,11 @@ static void AddInterfaceEntries(
         thisTarget->GetLinkImplementationLibraries(config)) {
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target) {
+        std::string uniqueName =
+          thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+            lib.Target);
         std::string genex =
-          "$<TARGET_PROPERTY:" + lib.AsStr() + "," + prop + ">";
+          "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">";
         cmGeneratorExpression ge(lib.Backtrace);
         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
         cge->SetEvaluateForBuildsystem(true);
@@ -840,7 +843,10 @@ static void AddObjectEntries(
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target &&
           lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-        std::string genex = "$<TARGET_OBJECTS:" + lib.AsStr() + ">";
+        std::string uniqueName =
+          thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+            lib.Target);
+        std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
         cmGeneratorExpression ge(lib.Backtrace);
         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
         cge->SetEvaluateForBuildsystem(true);

+ 18 - 0
Source/cmGlobalGenerator.cxx

@@ -2155,6 +2155,24 @@ void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt)
   }
 }
 
+std::string cmGlobalGenerator::IndexGeneratorTargetUniquely(
+  cmGeneratorTarget const* gt)
+{
+  // Use the pointer value to uniquely identify the target instance.
+  // Use a "T" prefix to indicate that this identifier is for a target.
+  // We must satisfy cmGeneratorExpression::IsValidTargetName so use no
+  // other special characters.
+  char buf[64];
+  sprintf(buf, "::T%p",
+          static_cast<void const*>(gt)); // cast avoids format warning
+  std::string id = gt->GetName() + buf;
+  // We internally index pointers to non-const generator targets
+  // but our callers only have pointers to const generator targets.
+  // They will give up non-const privileges when looking up anyway.
+  this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt);
+  return id;
+}
+
 void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
 {
   // FIXME: add_subdirectory supports multiple build directories

+ 4 - 0
Source/cmGlobalGenerator.h

@@ -303,6 +303,10 @@ public:
   void IndexTarget(cmTarget* t);
   void IndexGeneratorTarget(cmGeneratorTarget* gt);
 
+  // Index the target using a name that is unique to that target
+  // even if other targets have the same name.
+  std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);
+
   static bool IsReservedTarget(std::string const& name);
 
   virtual const char* GetAllTargetName() const { return "ALL_BUILD"; }