浏览代码

Merge topic 'use-generator-target'

c2b7336f cmGeneratorTarget: Move GetConfigCommonSourceFiles from cmTarget.
69329fff cmGeneratorTarget: Move GetLanguages from cmTarget.
0431f2c4 cmGeneratorTarget: Move ComputeLinkImplementationLanguages from cmTarget.
abe9505d cmGeneratorTarget: Move HaveBuildTreeRPath from cmTarget.
d4a24c0e cmGeneratorTarget: Move GetLinkImplementation from cmTarget.
83981cf5 cmTarget: Add GetLinkImplMap method.
771e79a2 cmLinkItem: Add cmOptionalLinkImplementation type.
3846ebcf cmLinkItem: Add cmLinkImplementation type.
a7f5d70d cmGeneratorTarget: Move compile defintions processing from cmTarget.
d051086c cmGeneratorTarget: Move compile features processing from cmTarget.
db4cb92b cmGeneratorTarget: Move compile options processing from cmTarget.
e6ccbf6f cmGeneratorTarget: Move include directory processing from cmTarget.
8bfb0c53 cmGeneratorTarget: Move link iface helpers from cmTarget.
2cb3e574 cmGeneratorTarget: Move GetImportLinkInterface from cmTarget.
6d3d099b cmGeneratorTarget: Move ComputeLinkInterfaceLibraries from cmTarget.
0db9d927 cmGeneratorTarget: Move GetLinkInterfaceLibraries from cmTarget.
...
Brad King 10 年之前
父节点
当前提交
27e4b21dfa

+ 15 - 9
Source/cmComputeLinkDepends.cxx

@@ -362,9 +362,11 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
   // Follow the item's dependencies.
   if(entry.Target)
     {
+    cmGeneratorTarget* gtgt =
+        this->GlobalGenerator->GetGeneratorTarget(entry.Target);
     // Follow the target dependencies.
-    if(cmTarget::LinkInterface const* iface =
-       entry.Target->GetLinkInterface(this->Config, this->Target->Target))
+    if(cmLinkInterface const* iface =
+       gtgt->GetLinkInterface(this->Config, this->Target->Target))
       {
       const bool isIface =
                       entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY;
@@ -398,7 +400,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
 //----------------------------------------------------------------------------
 void
 cmComputeLinkDepends
-::FollowSharedDeps(int depender_index, cmTarget::LinkInterface const* iface,
+::FollowSharedDeps(int depender_index, cmLinkInterface const* iface,
                    bool follow_interface)
 {
   // Follow dependencies if we have not followed them already.
@@ -461,8 +463,10 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
   // Target items may have their own dependencies.
   if(entry.Target)
     {
-    if(cmTarget::LinkInterface const* iface =
-       entry.Target->GetLinkInterface(this->Config, this->Target->Target))
+    cmGeneratorTarget* gtgt =
+        this->GlobalGenerator->GetGeneratorTarget(entry.Target);
+    if(cmLinkInterface const* iface =
+       gtgt->GetLinkInterface(this->Config, this->Target->Target))
       {
       // Follow public and private dependencies transitively.
       this->FollowSharedDeps(index, iface, true);
@@ -552,8 +556,8 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
 void cmComputeLinkDepends::AddDirectLinkEntries()
 {
   // Add direct link dependencies in this configuration.
-  cmTarget::LinkImplementation const* impl =
-    this->Target->Target->GetLinkImplementation(this->Config);
+  cmLinkImplementation const* impl =
+    this->Target->GetLinkImplementation(this->Config);
   this->AddLinkEntries(-1, impl->Libraries);
   for(std::vector<cmLinkItem>::const_iterator
         wi = impl->WrongConfigLibraries.begin();
@@ -932,8 +936,10 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
     {
     if(cmTarget const* target = this->EntryList[*ni].Target)
       {
-      if(cmTarget::LinkInterface const* iface =
-         target->GetLinkInterface(this->Config, this->Target->Target))
+      cmGeneratorTarget* gtgt =
+          this->GlobalGenerator->GetGeneratorTarget(target);
+      if(cmLinkInterface const* iface =
+         gtgt->GetLinkInterface(this->Config, this->Target->Target))
         {
         if(iface->Multiplicity > count)
           {

+ 1 - 1
Source/cmComputeLinkDepends.h

@@ -102,7 +102,7 @@ private:
   std::queue<SharedDepEntry> SharedDepQueue;
   std::set<int> SharedDepFollowed;
   void FollowSharedDeps(int depender_index,
-                        cmTarget::LinkInterface const* iface,
+                        cmLinkInterface const* iface,
                         bool follow_interface = false);
   void QueueSharedDependencies(int depender_index,
                                std::vector<cmLinkItem> const& deps);

+ 1 - 1
Source/cmComputeLinkInformation.cxx

@@ -1925,7 +1925,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
     (outputRuntime && this->Target->Target->HaveInstallTreeRPATH() &&
      linking_for_install);
   bool use_build_rpath =
-    (outputRuntime && this->Target->Target->HaveBuildTreeRPATH(this->Config) &&
+    (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
      !linking_for_install);
   bool use_link_rpath =
     outputRuntime && linking_for_install &&

+ 3 - 4
Source/cmComputeTargetDepends.cxx

@@ -252,8 +252,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
         }
       }
 
-    cmTarget::LinkImplementation const* impl =
-      depender->Target->GetLinkImplementation(*it);
+    cmLinkImplementation const* impl = depender->GetLinkImplementation(*it);
 
     // A target should not depend on itself.
     emitted.insert(depender->GetName());
@@ -296,8 +295,8 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
                                              std::set<std::string> &emitted)
 {
   cmGeneratorTarget const* depender = this->Targets[depender_index];
-  if(cmTarget::LinkInterface const* iface =
-                                dependee->Target->GetLinkInterface(config,
+  if(cmLinkInterface const* iface =
+                                dependee->GetLinkInterface(config,
                                                            depender->Target))
     {
     for(std::vector<cmLinkItem>::const_iterator

+ 4 - 6
Source/cmExportFileGenerator.cxx

@@ -796,9 +796,8 @@ cmExportFileGenerator
                     std::vector<std::string>& missingTargets)
 {
   // Add the transitive link dependencies for this configuration.
-  cmTarget::LinkInterface const* iface = target->Target->GetLinkInterface(
-                                                              config,
-                                                              target->Target);
+  cmLinkInterface const* iface = target->GetLinkInterface(config,
+                                                          target->Target);
   if (!iface)
     {
     return;
@@ -909,9 +908,8 @@ cmExportFileGenerator
     }
 
   // Add the transitive link dependencies for this configuration.
-  if(cmTarget::LinkInterface const* iface =
-                            target->Target
-                                  ->GetLinkInterface(config, target->Target))
+  if(cmLinkInterface const* iface =
+                            target->GetLinkInterface(config, target->Target))
     {
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_INTERFACE_LANGUAGES",

+ 1 - 1
Source/cmExtraCodeBlocksGenerator.cxx

@@ -609,7 +609,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
 
     // the compilerdefines for this target
     std::vector<std::string> cdefs;
-    target->GetCompileDefinitions(cdefs, buildType, "C");
+    gtgt->GetCompileDefinitions(cdefs, buildType, "C");
 
     // Expand the list.
     for(std::vector<std::string>::const_iterator di = cdefs.begin();

+ 2 - 2
Source/cmGeneratorExpressionNode.cxx

@@ -1108,8 +1108,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 
     if(isInterfaceProperty)
       {
-      if(cmTarget::LinkInterfaceLibraries const* iface =
-         target->GetLinkInterfaceLibraries(context->Config, headTarget, true))
+      if(cmLinkInterfaceLibraries const* iface =
+         gtgt->GetLinkInterfaceLibraries(context->Config, headTarget, true))
         {
         linkedTargetsContent =
           getLinkedTargetsContent(iface->Libraries, target,

+ 1209 - 12
Source/cmGeneratorTarget.cxx

@@ -34,6 +34,18 @@
 #define UNORDERED_SET std::set
 #endif
 
+class cmGeneratorTarget::TargetPropertyEntry {
+  static cmLinkImplItem NoLinkImplItem;
+public:
+  TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
+                      cmLinkImplItem const& item = NoLinkImplItem)
+    : ge(cge), LinkImplItem(item)
+  {}
+  const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
+  cmLinkImplItem const& LinkImplItem;
+};
+cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
+
 //----------------------------------------------------------------------------
 void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
                      cmGeneratorTarget const* target, cmake *cm)
@@ -227,18 +239,64 @@ struct TagVisitor
   }
 };
 
+void CreatePropertyGeneratorExpressions(
+    cmStringRange const& entries,
+    cmBacktraceRange const& backtraces,
+    std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
+    bool evaluateForBuildsystem = false)
+{
+  std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin();
+  for (std::vector<std::string>::const_iterator it = entries.begin();
+       it != entries.end(); ++it, ++btIt)
+    {
+    cmGeneratorExpression ge(*btIt);
+    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*it);
+    cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
+    items.push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
+    }
+}
+
 //----------------------------------------------------------------------------
 cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
   : Target(t),
-  SourceFileFlagsConstructed(false)
+  SourceFileFlagsConstructed(false),
+  PolicyWarnedCMP0022(false),
+  DebugIncludesDone(false),
+  DebugCompileOptionsDone(false),
+  DebugCompileFeaturesDone(false),
+  DebugCompileDefinitionsDone(false)
 {
   this->Makefile = this->Target->GetMakefile();
   this->LocalGenerator = lg;
   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
+
+  CreatePropertyGeneratorExpressions(
+        t->GetIncludeDirectoriesEntries(),
+        t->GetIncludeDirectoriesBacktraces(),
+        this->IncludeDirectoriesEntries);
+
+  CreatePropertyGeneratorExpressions(
+        t->GetCompileOptionsEntries(),
+        t->GetCompileOptionsBacktraces(),
+        this->CompileOptionsEntries);
+
+  CreatePropertyGeneratorExpressions(
+        t->GetCompileFeaturesEntries(),
+        t->GetCompileFeaturesBacktraces(),
+        this->CompileFeaturesEntries);
+
+  CreatePropertyGeneratorExpressions(
+        t->GetCompileDefinitionsEntries(),
+        t->GetCompileDefinitionsBacktraces(),
+        this->CompileDefinitionsEntries);
 }
 
 cmGeneratorTarget::~cmGeneratorTarget()
 {
+  cmDeleteAll(this->IncludeDirectoriesEntries);
+  cmDeleteAll(this->CompileOptionsEntries);
+  cmDeleteAll(this->CompileFeaturesEntries);
+  cmDeleteAll(this->CompileDefinitionsEntries);
   cmDeleteAll(this->LinkInformation);
   this->LinkInformation.clear();
 }
@@ -851,7 +909,7 @@ cmGeneratorTarget::NeedRelinkBeforeInstall(const std::string& config) const
   // If either a build or install tree rpath is set then the rpath
   // will likely change between the build tree and install tree and
   // this target must be relinked.
-  return this->Target->HaveBuildTreeRPATH(config)
+  return this->HaveBuildTreeRPATH(config)
       || this->Target->HaveInstallTreeRPATH();
 }
 
@@ -1172,9 +1230,11 @@ public:
       {
       return;
       }
-
-    cmTarget::LinkInterface const* iface =
-      item.Target->GetLinkInterface(this->Config, this->HeadTarget);
+    cmGeneratorTarget* gtgt =
+        this->Target->GetLocalGenerator()->GetGlobalGenerator()
+            ->GetGeneratorTarget(item.Target);
+    cmLinkInterface const* iface =
+      gtgt->GetLinkInterface(this->Config, this->HeadTarget);
     if(!iface) { return; }
 
     for(std::vector<std::string>::const_iterator
@@ -1275,8 +1335,8 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
 {
   // Get languages built in this target.
   UNORDERED_SET<std::string> languages;
-  cmTarget::LinkImplementation const* impl =
-                            this->Target->GetLinkImplementation(config);
+  cmLinkImplementation const* impl =
+                            this->GetLinkImplementation(config);
   assert(impl);
   for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
       li != impl->Languages.end(); ++li)
@@ -1505,20 +1565,22 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result,
 void processILibs(const std::string& config,
                   cmTarget const* headTarget,
                   cmLinkItem const& item,
+                  cmGlobalGenerator* gg,
                   std::vector<cmTarget const*>& tgts,
                   std::set<cmTarget const*>& emitted)
 {
   if (item.Target && emitted.insert(item.Target).second)
     {
     tgts.push_back(item.Target);
-    if(cmTarget::LinkInterfaceLibraries const* iface =
-       item.Target->GetLinkInterfaceLibraries(config, headTarget, true))
+    cmGeneratorTarget* gt = gg->GetGeneratorTarget(item.Target);
+    if(cmLinkInterfaceLibraries const* iface =
+       gt->GetLinkInterfaceLibraries(config, headTarget, true))
       {
       for(std::vector<cmLinkItem>::const_iterator
             it = iface->Libraries.begin();
           it != iface->Libraries.end(); ++it)
         {
-        processILibs(config, headTarget, *it, tgts, emitted);
+        processILibs(config, headTarget, *it, gg, tgts, emitted);
         }
       }
     }
@@ -1543,7 +1605,9 @@ cmGeneratorTarget::GetLinkImplementationClosure(
           it = impl->Libraries.begin();
         it != impl->Libraries.end(); ++it)
       {
-      processILibs(config, this->Target, *it, tgts , emitted);
+      processILibs(config, this->Target, *it,
+                   this->LocalGenerator->GetGlobalGenerator(),
+                   tgts , emitted);
       }
     }
   return tgts;
@@ -1957,13 +2021,536 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
     }
   return "";
 }
+//----------------------------------------------------------------------------
+static void processIncludeDirectories(cmGeneratorTarget const* tgt,
+      const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &includes,
+      UNORDERED_SET<std::string> &uniqueIncludes,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugIncludes,
+      const std::string& language)
+{
+  cmMakefile *mf = tgt->Target->GetMakefile();
+
+  for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator
+      it = entries.begin(), end = entries.end(); it != end; ++it)
+    {
+    cmLinkImplItem const& item = (*it)->LinkImplItem;
+    std::string const& targetName = item;
+    bool const fromImported = item.Target && item.Target->IsImported();
+    bool const checkCMP0027 = item.FromGenex;
+    std::vector<std::string> entryIncludes;
+    cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+                                              config,
+                                              false,
+                                              tgt->Target,
+                                              dagChecker, language),
+                                    entryIncludes);
+
+    std::string usedIncludes;
+    for(std::vector<std::string>::iterator
+          li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
+      {
+      if (fromImported
+          && !cmSystemTools::FileExists(li->c_str()))
+        {
+        std::ostringstream e;
+        cmake::MessageType messageType = cmake::FATAL_ERROR;
+        if (checkCMP0027)
+          {
+          switch(tgt->Target->GetPolicyStatusCMP0027())
+            {
+            case cmPolicies::WARN:
+              e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
+            case cmPolicies::OLD:
+              messageType = cmake::AUTHOR_WARNING;
+              break;
+            case cmPolicies::REQUIRED_ALWAYS:
+            case cmPolicies::REQUIRED_IF_USED:
+            case cmPolicies::NEW:
+              break;
+            }
+          }
+        e << "Imported target \"" << targetName << "\" includes "
+             "non-existent path\n  \"" << *li << "\"\nin its "
+             "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
+             "* The path was deleted, renamed, or moved to another "
+             "location.\n"
+             "* An install or uninstall procedure did not complete "
+             "successfully.\n"
+             "* The installation package was faulty and references files it "
+             "does not provide.\n";
+        tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+        return;
+        }
+
+      if (!cmSystemTools::FileIsFullPath(li->c_str()))
+        {
+        std::ostringstream e;
+        bool noMessage = false;
+        cmake::MessageType messageType = cmake::FATAL_ERROR;
+        if (!targetName.empty())
+          {
+          e << "Target \"" << targetName << "\" contains relative "
+            "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
+            "  \"" << *li << "\"";
+          }
+        else
+          {
+          switch(tgt->Target->GetPolicyStatusCMP0021())
+            {
+            case cmPolicies::WARN:
+              {
+              e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n";
+              messageType = cmake::AUTHOR_WARNING;
+              }
+              break;
+            case cmPolicies::OLD:
+              noMessage = true;
+            case cmPolicies::REQUIRED_IF_USED:
+            case cmPolicies::REQUIRED_ALWAYS:
+            case cmPolicies::NEW:
+              // Issue the fatal message.
+              break;
+            }
+          e << "Found relative path while evaluating include directories of "
+          "\"" << tgt->GetName() << "\":\n  \"" << *li << "\"\n";
+          }
+        if (!noMessage)
+          {
+          tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+          if (messageType == cmake::FATAL_ERROR)
+            {
+            return;
+            }
+          }
+        }
+
+      if (!cmSystemTools::IsOff(li->c_str()))
+        {
+        cmSystemTools::ConvertToUnixSlashes(*li);
+        }
+      std::string inc = *li;
+
+      if(uniqueIncludes.insert(inc).second)
+        {
+        includes.push_back(inc);
+        if (debugIncludes)
+          {
+          usedIncludes += " * " + inc + "\n";
+          }
+        }
+      }
+    if (!usedIncludes.empty())
+      {
+      mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+                            std::string("Used includes for target ")
+                            + tgt->GetName() + ":\n"
+                            + usedIncludes, (*it)->ge->GetBacktrace());
+      }
+    }
+}
+
+
+//----------------------------------------------------------------------------
+static void AddInterfaceEntries(
+  cmGeneratorTarget const* thisTarget, std::string const& config,
+  std::string const& prop,
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+{
+  if(cmLinkImplementationLibraries const* impl =
+     thisTarget->Target->GetLinkImplementationLibraries(config))
+    {
+    for (std::vector<cmLinkImplItem>::const_iterator
+           it = impl->Libraries.begin(), end = impl->Libraries.end();
+         it != end; ++it)
+      {
+      if(it->Target)
+        {
+        std::string genex =
+          "$<TARGET_PROPERTY:" + *it + "," + prop + ">";
+        cmGeneratorExpression ge(it->Backtrace);
+        cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+        cge->SetEvaluateForBuildsystem(true);
+        entries.push_back(
+          new cmGeneratorTarget::TargetPropertyEntry(cge, *it));
+        }
+      }
+    }
+}
 
 //----------------------------------------------------------------------------
 std::vector<std::string>
 cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
                                          const std::string& lang) const
 {
-  return this->Target->GetIncludeDirectories(config, lang);
+  std::vector<std::string> includes;
+  UNORDERED_SET<std::string> uniqueIncludes;
+
+  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
+                                             "INCLUDE_DIRECTORIES", 0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugIncludes = !this->DebugIncludesDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "INCLUDE_DIRECTORIES")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsConfigured())
+    {
+    this->DebugIncludesDone = true;
+    }
+
+  processIncludeDirectories(this,
+                            this->IncludeDirectoriesEntries,
+                            includes,
+                            uniqueIncludes,
+                            &dagChecker,
+                            config,
+                            debugIncludes,
+                            lang);
+
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+    linkInterfaceIncludeDirectoriesEntries;
+  AddInterfaceEntries(
+    this, config, "INTERFACE_INCLUDE_DIRECTORIES",
+    linkInterfaceIncludeDirectoriesEntries);
+
+  if(this->Makefile->IsOn("APPLE"))
+    {
+    cmLinkImplementationLibraries const* impl =
+        this->Target->GetLinkImplementationLibraries(config);
+    for(std::vector<cmLinkImplItem>::const_iterator
+        it = impl->Libraries.begin();
+        it != impl->Libraries.end(); ++it)
+      {
+      std::string libDir = cmSystemTools::CollapseFullPath(*it);
+
+      static cmsys::RegularExpression
+        frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
+      if(!frameworkCheck.find(libDir))
+        {
+        continue;
+        }
+
+      libDir = frameworkCheck.match(1);
+
+      cmGeneratorExpression ge;
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                ge.Parse(libDir.c_str());
+      linkInterfaceIncludeDirectoriesEntries
+              .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
+      }
+    }
+
+  processIncludeDirectories(this,
+                            linkInterfaceIncludeDirectoriesEntries,
+                            includes,
+                            uniqueIncludes,
+                            &dagChecker,
+                            config,
+                            debugIncludes,
+                            lang);
+
+  cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
+
+  return includes;
+}
+
+//----------------------------------------------------------------------------
+static void processCompileOptionsInternal(cmGeneratorTarget const* tgt,
+      const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      UNORDERED_SET<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugOptions, const char *logName,
+      std::string const& language)
+{
+  cmMakefile *mf = tgt->Target->GetMakefile();
+
+  for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator
+      it = entries.begin(), end = entries.end(); it != end; ++it)
+    {
+    std::vector<std::string> entryOptions;
+    cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+                                              config,
+                                              false,
+                                              tgt->Target,
+                                              dagChecker,
+                                              language),
+                                    entryOptions);
+    std::string usedOptions;
+    for(std::vector<std::string>::iterator
+          li = entryOptions.begin(); li != entryOptions.end(); ++li)
+      {
+      std::string const& opt = *li;
+
+      if(uniqueOptions.insert(opt).second)
+        {
+        options.push_back(opt);
+        if (debugOptions)
+          {
+          usedOptions += " * " + opt + "\n";
+          }
+        }
+      }
+    if (!usedOptions.empty())
+      {
+      mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+                            std::string("Used compile ") + logName
+                            + std::string(" for target ")
+                            + tgt->GetName() + ":\n"
+                            + usedOptions, (*it)->ge->GetBacktrace());
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+static void processCompileOptions(cmGeneratorTarget const* tgt,
+      const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      UNORDERED_SET<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugOptions,
+      std::string const& language)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions, "options",
+                                language);
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::GetCompileOptions(std::vector<std::string> &result,
+                                 const std::string& config,
+                                 const std::string& language) const
+{
+  UNORDERED_SET<std::string> uniqueOptions;
+
+  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
+                                             "COMPILE_OPTIONS", 0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugOptions = !this->DebugCompileOptionsDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "COMPILE_OPTIONS")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsConfigured())
+    {
+    this->DebugCompileOptionsDone = true;
+    }
+
+  processCompileOptions(this,
+                            this->CompileOptionsEntries,
+                            result,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugOptions,
+                            language);
+
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+    linkInterfaceCompileOptionsEntries;
+
+  AddInterfaceEntries(
+    this, config, "INTERFACE_COMPILE_OPTIONS",
+    linkInterfaceCompileOptionsEntries);
+
+  processCompileOptions(this,
+                        linkInterfaceCompileOptionsEntries,
+                            result,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugOptions,
+                            language);
+
+  cmDeleteAll(linkInterfaceCompileOptionsEntries);
+}
+
+//----------------------------------------------------------------------------
+static void processCompileFeatures(cmGeneratorTarget const* tgt,
+      const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      UNORDERED_SET<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugOptions)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions, "features",
+                                std::string());
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string> &result,
+                                  const std::string& config) const
+{
+  UNORDERED_SET<std::string> uniqueFeatures;
+
+  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
+                                             "COMPILE_FEATURES",
+                                             0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugFeatures = !this->DebugCompileFeaturesDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "COMPILE_FEATURES")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsConfigured())
+    {
+    this->DebugCompileFeaturesDone = true;
+    }
+
+  processCompileFeatures(this,
+                            this->CompileFeaturesEntries,
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+    linkInterfaceCompileFeaturesEntries;
+  AddInterfaceEntries(
+    this, config, "INTERFACE_COMPILE_FEATURES",
+    linkInterfaceCompileFeaturesEntries);
+
+  processCompileFeatures(this,
+                         linkInterfaceCompileFeaturesEntries,
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  cmDeleteAll(linkInterfaceCompileFeaturesEntries);
+}
+
+//----------------------------------------------------------------------------
+static void processCompileDefinitions(cmGeneratorTarget const* tgt,
+      const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      UNORDERED_SET<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugOptions,
+      std::string const& language)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions,
+                                "definitions", language);
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::GetCompileDefinitions(std::vector<std::string> &list,
+                                            const std::string& config,
+                                            const std::string& language) const
+{
+  UNORDERED_SET<std::string> uniqueOptions;
+
+  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
+                                             "COMPILE_DEFINITIONS", 0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugDefines = !this->DebugCompileDefinitionsDone
+                          && std::find(debugProperties.begin(),
+                                debugProperties.end(),
+                                "COMPILE_DEFINITIONS")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsConfigured())
+    {
+    this->DebugCompileDefinitionsDone = true;
+    }
+
+  processCompileDefinitions(this,
+                            this->CompileDefinitionsEntries,
+                            list,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugDefines,
+                            language);
+
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+    linkInterfaceCompileDefinitionsEntries;
+  AddInterfaceEntries(
+    this, config, "INTERFACE_COMPILE_DEFINITIONS",
+    linkInterfaceCompileDefinitionsEntries);
+  if (!config.empty())
+    {
+    std::string configPropName = "COMPILE_DEFINITIONS_"
+                                        + cmSystemTools::UpperCase(config);
+    const char *configProp = this->Target->GetProperty(configPropName);
+    if (configProp)
+      {
+      switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043))
+        {
+        case cmPolicies::WARN:
+          {
+          std::ostringstream e;
+          e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043);
+          this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING,
+                                       e.str());
+          }
+        case cmPolicies::OLD:
+          {
+          cmGeneratorExpression ge;
+          cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                                                      ge.Parse(configProp);
+          linkInterfaceCompileDefinitionsEntries
+                .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
+          }
+          break;
+        case cmPolicies::NEW:
+        case cmPolicies::REQUIRED_ALWAYS:
+        case cmPolicies::REQUIRED_IF_USED:
+          break;
+        }
+      }
+    }
+
+  processCompileDefinitions(this,
+                            linkInterfaceCompileDefinitionsEntries,
+                            list,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugDefines,
+                            language);
+
+  cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
 }
 
 //----------------------------------------------------------------------------
@@ -3354,3 +3941,613 @@ cmGeneratorTarget::ReportPropertyOrigin(const std::string &p,
 
   this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport);
 }
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
+                               std::vector<cmLinkItem>& items) const
+{
+  for(std::vector<std::string>::const_iterator i = names.begin();
+      i != names.end(); ++i)
+    {
+    std::string name = this->Target->CheckCMP0004(*i);
+    if(name == this->GetName() || name.empty())
+      {
+      continue;
+      }
+    items.push_back(cmLinkItem(name, this->Target->FindTargetToLink(name)));
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
+                               std::string const& value,
+                               std::string const& config,
+                               cmTarget const* headTarget,
+                               bool usage_requirements_only,
+                               std::vector<cmLinkItem>& items,
+                               bool& hadHeadSensitiveCondition) const
+{
+  cmGeneratorExpression ge;
+  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0);
+  // The $<LINK_ONLY> expression may be in a link interface to specify private
+  // link dependencies that are otherwise excluded from usage requirements.
+  if(usage_requirements_only)
+    {
+    dagChecker.SetTransitivePropertiesOnly();
+    }
+  std::vector<std::string> libs;
+  cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+  cmSystemTools::ExpandListArgument(cge->Evaluate(
+                                      this->Makefile,
+                                      config,
+                                      false,
+                                      headTarget,
+                                      this->Target, &dagChecker), libs);
+  this->LookupLinkItems(libs, items);
+  hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
+}
+
+//----------------------------------------------------------------------------
+cmLinkInterface const*
+cmGeneratorTarget::GetLinkInterface(const std::string& config,
+                                    cmTarget const* head) const
+{
+  // Imported targets have their own link interface.
+  if(this->IsImported())
+    {
+    return this->GetImportLinkInterface(config, head, false);
+    }
+
+  // Link interfaces are not supported for executables that do not
+  // export symbols.
+  if(this->GetType() == cmTarget::EXECUTABLE &&
+     !this->Target->IsExecutableWithExports())
+    {
+    return 0;
+    }
+
+  // Lookup any existing link interface for this configuration.
+  cmHeadToLinkInterfaceMap& hm =
+      this->GetHeadToLinkInterfaceMap(config);
+
+  // If the link interface does not depend on the head target
+  // then return the one we computed first.
+  if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
+    {
+    return &hm.begin()->second;
+    }
+
+  cmOptionalLinkInterface& iface = hm[head];
+  if(!iface.LibrariesDone)
+    {
+    iface.LibrariesDone = true;
+    this->ComputeLinkInterfaceLibraries(
+      config, iface, head, false);
+    }
+  if(!iface.AllDone)
+    {
+    iface.AllDone = true;
+    if(iface.Exists)
+      {
+      this->ComputeLinkInterface(config, iface, head);
+      }
+    }
+
+  return iface.Exists? &iface : 0;
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ComputeLinkInterface(const std::string& config,
+                                    cmOptionalLinkInterface &iface,
+                                    cmTarget const* headTarget) const
+{
+  if(iface.ExplicitLibraries)
+    {
+    if(this->GetType() == cmTarget::SHARED_LIBRARY
+        || this->GetType() == cmTarget::STATIC_LIBRARY
+        || this->GetType() == cmTarget::INTERFACE_LIBRARY)
+      {
+      // Shared libraries may have runtime implementation dependencies
+      // on other shared libraries that are not in the interface.
+      UNORDERED_SET<std::string> emitted;
+      for(std::vector<cmLinkItem>::const_iterator
+          li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
+        {
+        emitted.insert(*li);
+        }
+      if (this->GetType() != cmTarget::INTERFACE_LIBRARY)
+        {
+        cmLinkImplementation const* impl =
+            this->GetLinkImplementation(config);
+        for(std::vector<cmLinkImplItem>::const_iterator
+              li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
+          {
+          if(emitted.insert(*li).second)
+            {
+            if(li->Target)
+              {
+              // This is a runtime dependency on another shared library.
+              if(li->Target->GetType() == cmTarget::SHARED_LIBRARY)
+                {
+                iface.SharedDeps.push_back(*li);
+                }
+              }
+            else
+              {
+              // TODO: Recognize shared library file names.  Perhaps this
+              // should be moved to cmComputeLinkInformation, but that creates
+              // a chicken-and-egg problem since this list is needed for its
+              // construction.
+              }
+            }
+          }
+        }
+      }
+    }
+  else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN
+        || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+    {
+    // The link implementation is the default link interface.
+    cmLinkImplementationLibraries const*
+      impl = this->Target->GetLinkImplementationLibrariesInternal(config,
+                                                                headTarget);
+    iface.ImplementationIsInterface = true;
+    iface.WrongConfigLibraries = impl->WrongConfigLibraries;
+    }
+
+  if(this->Target->LinkLanguagePropagatesToDependents())
+    {
+    // Targets using this archive need its language runtime libraries.
+    if(cmLinkImplementation const* impl =
+       this->GetLinkImplementation(config))
+      {
+      iface.Languages = impl->Languages;
+      }
+    }
+
+  if(this->GetType() == cmTarget::STATIC_LIBRARY)
+    {
+    // Construct the property name suffix for this configuration.
+    std::string suffix = "_";
+    if(!config.empty())
+      {
+      suffix += cmSystemTools::UpperCase(config);
+      }
+    else
+      {
+      suffix += "NOCONFIG";
+      }
+
+    // How many repetitions are needed if this library has cyclic
+    // dependencies?
+    std::string propName = "LINK_INTERFACE_MULTIPLICITY";
+    propName += suffix;
+    if(const char* config_reps = this->GetProperty(propName))
+      {
+      sscanf(config_reps, "%u", &iface.Multiplicity);
+      }
+    else if(const char* reps =
+            this->GetProperty("LINK_INTERFACE_MULTIPLICITY"))
+      {
+      sscanf(reps, "%u", &iface.Multiplicity);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+const cmLinkInterfaceLibraries *
+cmGeneratorTarget::GetLinkInterfaceLibraries(const std::string& config,
+                                    cmTarget const* head,
+                                    bool usage_requirements_only) const
+{
+  // Imported targets have their own link interface.
+  if(this->IsImported())
+    {
+    return this->GetImportLinkInterface(config, head,
+                                                usage_requirements_only);
+    }
+
+  // Link interfaces are not supported for executables that do not
+  // export symbols.
+  if(this->GetType() == cmTarget::EXECUTABLE &&
+     !this->Target->IsExecutableWithExports())
+    {
+    return 0;
+    }
+
+  // Lookup any existing link interface for this configuration.
+  std::string CONFIG = cmSystemTools::UpperCase(config);
+  cmHeadToLinkInterfaceMap& hm =
+    (usage_requirements_only ?
+     this->GetHeadToLinkInterfaceUsageRequirementsMap(config) :
+     this->GetHeadToLinkInterfaceMap(config));
+
+  // If the link interface does not depend on the head target
+  // then return the one we computed first.
+  if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
+    {
+    return &hm.begin()->second;
+    }
+
+  cmOptionalLinkInterface& iface = hm[head];
+  if(!iface.LibrariesDone)
+    {
+    iface.LibrariesDone = true;
+    this->ComputeLinkInterfaceLibraries(
+      config, iface, head, usage_requirements_only);
+    }
+
+  return iface.Exists? &iface : 0;
+}
+
+//----------------------------------------------------------------------------
+void
+cmGeneratorTarget::ComputeLinkInterfaceLibraries(
+  const std::string& config,
+  cmOptionalLinkInterface& iface,
+  cmTarget const* headTarget,
+  bool usage_requirements_only) const
+{
+  // Construct the property name suffix for this configuration.
+  std::string suffix = "_";
+  if(!config.empty())
+    {
+    suffix += cmSystemTools::UpperCase(config);
+    }
+  else
+    {
+    suffix += "NOCONFIG";
+    }
+
+  // An explicit list of interface libraries may be set for shared
+  // libraries and executables that export symbols.
+  const char* explicitLibraries = 0;
+  std::string linkIfaceProp;
+  if(this->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
+     this->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN)
+    {
+    // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
+    linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+    explicitLibraries = this->GetProperty(linkIfaceProp);
+    }
+  else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
+          this->Target->IsExecutableWithExports())
+    {
+    // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
+    // shared lib or executable.
+
+    // Lookup the per-configuration property.
+    linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+    linkIfaceProp += suffix;
+    explicitLibraries = this->GetProperty(linkIfaceProp);
+
+    // If not set, try the generic property.
+    if(!explicitLibraries)
+      {
+      linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+      explicitLibraries = this->GetProperty(linkIfaceProp);
+      }
+    }
+
+  if(explicitLibraries &&
+     this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
+     !this->PolicyWarnedCMP0022)
+    {
+    // Compare the explicitly set old link interface properties to the
+    // preferred new link interface property one and warn if different.
+    const char* newExplicitLibraries =
+      this->GetProperty("INTERFACE_LINK_LIBRARIES");
+    if (newExplicitLibraries
+        && strcmp(newExplicitLibraries, explicitLibraries) != 0)
+      {
+      std::ostringstream w;
+      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
+        "Target \"" << this->GetName() << "\" has an "
+        "INTERFACE_LINK_LIBRARIES property which differs from its " <<
+        linkIfaceProp << " properties."
+        "\n"
+        "INTERFACE_LINK_LIBRARIES:\n"
+        "  " << newExplicitLibraries << "\n" <<
+        linkIfaceProp << ":\n"
+        "  " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
+      this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+      this->PolicyWarnedCMP0022 = true;
+      }
+    }
+
+  // There is no implicit link interface for executables or modules
+  // so if none was explicitly set then there is no link interface.
+  if(!explicitLibraries &&
+     (this->GetType() == cmTarget::EXECUTABLE ||
+      (this->GetType() == cmTarget::MODULE_LIBRARY)))
+    {
+    return;
+    }
+  iface.Exists = true;
+  iface.ExplicitLibraries = explicitLibraries;
+
+  if(explicitLibraries)
+    {
+    // The interface libraries have been explicitly set.
+    this->ExpandLinkItems(linkIfaceProp, explicitLibraries,
+                                  config,
+                                headTarget, usage_requirements_only,
+                                iface.Libraries,
+                                iface.HadHeadSensitiveCondition);
+    }
+  else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN
+        || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+    // If CMP0022 is NEW then the plain tll signature sets the
+    // INTERFACE_LINK_LIBRARIES, so if we get here then the project
+    // cleared the property explicitly and we should not fall back
+    // to the link implementation.
+    {
+    // The link implementation is the default link interface.
+    cmLinkImplementationLibraries const* impl =
+      this->Target->GetLinkImplementationLibrariesInternal(config,
+                                                           headTarget);
+    iface.Libraries.insert(iface.Libraries.end(),
+                           impl->Libraries.begin(), impl->Libraries.end());
+    if(this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
+       !this->PolicyWarnedCMP0022 && !usage_requirements_only)
+      {
+      // Compare the link implementation fallback link interface to the
+      // preferred new link interface property and warn if different.
+      std::vector<cmLinkItem> ifaceLibs;
+      static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
+      if(const char* newExplicitLibraries = this->GetProperty(newProp))
+        {
+        bool hadHeadSensitiveConditionDummy = false;
+        this->ExpandLinkItems(newProp, newExplicitLibraries, config,
+                                    headTarget, usage_requirements_only,
+                                ifaceLibs, hadHeadSensitiveConditionDummy);
+        }
+      if (ifaceLibs != iface.Libraries)
+        {
+        std::string oldLibraries = cmJoin(impl->Libraries, ";");
+        std::string newLibraries = cmJoin(ifaceLibs, ";");
+        if(oldLibraries.empty())
+          { oldLibraries = "(empty)"; }
+        if(newLibraries.empty())
+          { newLibraries = "(empty)"; }
+
+        std::ostringstream w;
+        w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
+          "Target \"" << this->GetName() << "\" has an "
+          "INTERFACE_LINK_LIBRARIES property.  "
+          "This should be preferred as the source of the link interface "
+          "for this library but because CMP0022 is not set CMake is "
+          "ignoring the property and using the link implementation "
+          "as the link interface instead."
+          "\n"
+          "INTERFACE_LINK_LIBRARIES:\n"
+          "  " << newLibraries << "\n"
+          "Link implementation:\n"
+          "  " << oldLibraries << "\n";
+        this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+        this->PolicyWarnedCMP0022 = true;
+        }
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+const cmLinkInterface *
+cmGeneratorTarget::GetImportLinkInterface(const std::string& config,
+                                 cmTarget const* headTarget,
+                                 bool usage_requirements_only) const
+{
+  cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config);
+  if(!info)
+    {
+    return 0;
+    }
+
+  std::string CONFIG = cmSystemTools::UpperCase(config);
+  cmHeadToLinkInterfaceMap& hm =
+    (usage_requirements_only ?
+     this->GetHeadToLinkInterfaceUsageRequirementsMap(config) :
+     this->GetHeadToLinkInterfaceMap(config));
+
+  // If the link interface does not depend on the head target
+  // then return the one we computed first.
+  if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
+    {
+    return &hm.begin()->second;
+    }
+
+  cmOptionalLinkInterface& iface = hm[headTarget];
+  if(!iface.AllDone)
+    {
+    iface.AllDone = true;
+    iface.Multiplicity = info->Multiplicity;
+    cmSystemTools::ExpandListArgument(info->Languages, iface.Languages);
+    this->ExpandLinkItems(info->LibrariesProp, info->Libraries,
+                                  config,
+                          headTarget, usage_requirements_only,
+                          iface.Libraries,
+                          iface.HadHeadSensitiveCondition);
+    std::vector<std::string> deps;
+    cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
+    this->LookupLinkItems(deps, iface.SharedDeps);
+    }
+
+  return &iface;
+}
+
+cmHeadToLinkInterfaceMap&
+cmGeneratorTarget::GetHeadToLinkInterfaceMap(const std::string &config) const
+{
+  std::string CONFIG = cmSystemTools::UpperCase(config);
+  return this->LinkInterfaceMap[CONFIG];
+}
+
+cmHeadToLinkInterfaceMap&
+cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
+    const std::string &config) const
+{
+  std::string CONFIG = cmSystemTools::UpperCase(config);
+  return this->LinkInterfaceUsageRequirementsOnlyMap[CONFIG];
+}
+
+//----------------------------------------------------------------------------
+const cmLinkImplementation *
+cmGeneratorTarget::GetLinkImplementation(const std::string& config) const
+{
+  // There is no link implementation for imported targets.
+  if(this->Target->IsImported())
+    {
+    return 0;
+    }
+
+  cmOptionalLinkImplementation& impl = this->Target->GetLinkImplMap(config);
+  if(!impl.LibrariesDone)
+    {
+    impl.LibrariesDone = true;
+    this->Target->ComputeLinkImplementationLibraries(config, impl,
+                                                     this->Target);
+    }
+  if(!impl.LanguagesDone)
+    {
+    impl.LanguagesDone = true;
+    this->ComputeLinkImplementationLanguages(config, impl);
+    }
+  return &impl;
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorTarget::GetConfigCommonSourceFiles(
+    std::vector<cmSourceFile*>& files) const
+{
+  std::vector<std::string> configs;
+  this->Makefile->GetConfigurations(configs);
+  if (configs.empty())
+    {
+    configs.push_back("");
+    }
+
+  std::vector<std::string>::const_iterator it = configs.begin();
+  const std::string& firstConfig = *it;
+  this->Target->GetSourceFiles(files, firstConfig);
+
+  for ( ; it != configs.end(); ++it)
+    {
+    std::vector<cmSourceFile*> configFiles;
+    this->Target->GetSourceFiles(configFiles, *it);
+    if (configFiles != files)
+      {
+      std::string firstConfigFiles;
+      const char* sep = "";
+      for (std::vector<cmSourceFile*>::const_iterator fi = files.begin();
+           fi != files.end(); ++fi)
+        {
+        firstConfigFiles += sep;
+        firstConfigFiles += (*fi)->GetFullPath();
+        sep = "\n  ";
+        }
+
+      std::string thisConfigFiles;
+      sep = "";
+      for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin();
+           fi != configFiles.end(); ++fi)
+        {
+        thisConfigFiles += sep;
+        thisConfigFiles += (*fi)->GetFullPath();
+        sep = "\n  ";
+        }
+      std::ostringstream e;
+      e << "Target \"" << this->GetName()
+        << "\" has source files which vary by "
+        "configuration. This is not supported by the \""
+        << this->GlobalGenerator->GetName()
+        << "\" generator.\n"
+          "Config \"" << firstConfig << "\":\n"
+          "  " << firstConfigFiles << "\n"
+          "Config \"" << *it << "\":\n"
+          "  " << thisConfigFiles << "\n";
+      this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
+                            const std::string& config) const
+{
+  std::vector<cmSourceFile*> sourceFiles;
+  this->GetSourceFiles(sourceFiles, config);
+  for(std::vector<cmSourceFile*>::const_iterator
+        i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
+    {
+    const std::string& lang = (*i)->GetLanguage();
+    if(!lang.empty())
+      {
+      languages.insert(lang);
+      }
+    }
+
+  std::vector<cmGeneratorTarget*> objectLibraries;
+  std::vector<cmSourceFile const*> externalObjects;
+  if (!this->Makefile->IsConfigured())
+    {
+    std::vector<cmTarget*> objectTargets;
+    this->Target->GetObjectLibrariesCMP0026(objectTargets);
+    objectLibraries.reserve(objectTargets.size());
+    for (std::vector<cmTarget*>::const_iterator it = objectTargets.begin();
+         it != objectTargets.end(); ++it)
+      {
+      objectLibraries.push_back(this->GlobalGenerator
+                                ->GetGeneratorTarget(*it));
+      }
+    }
+  else
+    {
+    this->GetExternalObjects(externalObjects, config);
+    for(std::vector<cmSourceFile const*>::const_iterator
+          i = externalObjects.begin(); i != externalObjects.end(); ++i)
+      {
+      std::string objLib = (*i)->GetObjectLibrary();
+      if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
+        {
+        objectLibraries.push_back(this->GlobalGenerator
+                                  ->GetGeneratorTarget(tgt));
+        }
+      }
+    }
+  for(std::vector<cmGeneratorTarget*>::const_iterator
+      i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
+    {
+    (*i)->GetLanguages(languages, config);
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ComputeLinkImplementationLanguages(
+  const std::string& config,
+  cmOptionalLinkImplementation& impl) const
+{
+  // This target needs runtime libraries for its source languages.
+  std::set<std::string> languages;
+  // Get languages used in our source files.
+  this->GetLanguages(languages, config);
+  // Copy the set of langauges to the link implementation.
+  impl.Languages.insert(impl.Languages.begin(),
+                        languages.begin(), languages.end());
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
+{
+  if (this->Target->GetPropertyAsBool("SKIP_BUILD_RPATH"))
+    {
+    return false;
+    }
+  if(cmLinkImplementationLibraries const* impl =
+     this->Target->GetLinkImplementationLibraries(config))
+    {
+    return !impl->Libraries.empty();
+    }
+  return false;
+}

+ 80 - 1
Source/cmGeneratorTarget.h

@@ -12,7 +12,7 @@
 #ifndef cmGeneratorTarget_h
 #define cmGeneratorTarget_h
 
-#include "cmStandardIncludes.h"
+#include "cmLinkItem.h"
 
 class cmCustomCommand;
 class cmGlobalGenerator;
@@ -106,6 +106,21 @@ public:
   const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p,
                          const std::string& config) const;
 
+  cmLinkInterface const* GetLinkInterface(const std::string& config,
+                                        cmTarget const* headTarget) const;
+  void ComputeLinkInterface(const std::string& config,
+                            cmOptionalLinkInterface& iface,
+                            cmTarget const* head) const;
+
+  cmLinkInterfaceLibraries const*
+    GetLinkInterfaceLibraries(const std::string& config,
+                              cmTarget const* headTarget,
+                              bool usage_requirements_only) const;
+
+  void ComputeLinkInterfaceLibraries(const std::string& config,
+                                     cmOptionalLinkInterface &iface,
+                                     cmTarget const* head,
+                                     bool usage_requirements_only) const;
 
   /** Get the full path to the target according to the settings in its
       makefile and the configuration type.  */
@@ -183,6 +198,25 @@ public:
   LinkClosure const* GetLinkClosure(const std::string& config) const;
   void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
 
+  cmLinkImplementation const*
+    GetLinkImplementation(const std::string& config) const;
+
+  void ComputeLinkImplementationLanguages(const std::string& config,
+                                          cmOptionalLinkImplementation& impl
+                                          ) const;
+
+  // Compute the set of languages compiled by the target.  This is
+  // computed every time it is called because the languages can change
+  // when source file properties are changed and we do not have enough
+  // information to forward these property changes to the targets
+  // until we have per-target object file properties.
+  void GetLanguages(std::set<std::string>& languages,
+                    std::string const& config) const;
+
+  bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
+
+  bool HaveBuildTreeRPATH(const std::string& config) const;
+
   /** Full path with trailing slash to the top-level directory
       holding object files for this target.  Includes the build
       time config name placeholder if needed for the generator.  */
@@ -202,6 +236,17 @@ public:
   std::vector<std::string> GetIncludeDirectories(
       const std::string& config, const std::string& lang) const;
 
+  void GetCompileOptions(std::vector<std::string> &result,
+                         const std::string& config,
+                         const std::string& language) const;
+
+  void GetCompileFeatures(std::vector<std::string> &features,
+                          const std::string& config) const;
+
+  void GetCompileDefinitions(std::vector<std::string> &result,
+                             const std::string& config,
+                             const std::string& language) const;
+
   bool IsSystemIncludeDirectory(const std::string& dir,
                                 const std::string& config) const;
 
@@ -317,6 +362,8 @@ public:
                             const std::string &report,
                             const std::string &compatibilityType) const;
 
+  class TargetPropertyEntry;
+
 private:
   friend class cmTargetTraceDependencies;
   struct SourceEntry { std::vector<cmSourceFile*> Depends; };
@@ -375,9 +422,41 @@ private:
   };
   mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
 
+  typedef std::map<std::string, cmHeadToLinkInterfaceMap>
+                                                          LinkInterfaceMapType;
+  mutable LinkInterfaceMapType LinkInterfaceMap;
+  mutable LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap;
+
+  cmHeadToLinkInterfaceMap&
+  GetHeadToLinkInterfaceMap(std::string const& config) const;
+  cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap(
+      std::string const& config) const;
+
+  cmLinkInterface const*
+    GetImportLinkInterface(const std::string& config, cmTarget const* head,
+                           bool usage_requirements_only) const;
+
+  std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+  std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+  std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
+  std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+
+  void ExpandLinkItems(std::string const& prop, std::string const& value,
+                       std::string const& config, cmTarget const* headTarget,
+                       bool usage_requirements_only,
+                       std::vector<cmLinkItem>& items,
+                       bool& hadHeadSensitiveCondition) const;
+  void LookupLinkItems(std::vector<std::string> const& names,
+                       std::vector<cmLinkItem>& items) const;
+
   typedef std::pair<std::string, bool> OutputNameKey;
   typedef std::map<OutputNameKey, std::string> OutputNameMapType;
   mutable OutputNameMapType OutputNameMap;
+  mutable bool PolicyWarnedCMP0022;
+  mutable bool DebugIncludesDone;
+  mutable bool DebugCompileOptionsDone;
+  mutable bool DebugCompileFeaturesDone;
+  mutable bool DebugCompileDefinitionsDone;
 
 public:
   std::vector<cmTarget const*> const&

+ 5 - 4
Source/cmGhsMultiTargetGenerator.cxx

@@ -330,7 +330,8 @@ void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
   const std::string &config, const std::string &language)
 {
   std::vector<std::string> compileDefinitions;
-  this->Target->GetCompileDefinitions(compileDefinitions, config, language);
+  this->GeneratorTarget->GetCompileDefinitions(compileDefinitions,
+                                               config, language);
   for (std::vector<std::string>::const_iterator cdI =
          compileDefinitions.begin();
        cdI != compileDefinitions.end(); ++cdI)
@@ -343,7 +344,7 @@ void cmGhsMultiTargetGenerator::WriteIncludes(const std::string &config,
                                               const std::string &language)
 {
   std::vector<std::string> includes =
-    this->Target->GetIncludeDirectories(config, language);
+    this->GeneratorTarget->GetIncludeDirectories(config, language);
   for (std::vector<std::string>::const_iterator includes_i = includes.begin();
        includes_i != includes.end(); ++includes_i)
     {
@@ -558,7 +559,7 @@ bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const &config,
 {
   bool output;
   std::vector<std::string> options;
-  this->Target->GetCompileOptions(options, config, language);
+  this->GeneratorTarget->GetCompileOptions(options, config, language);
   output =
     options.end() == std::find(options.begin(), options.end(), "-kernel");
   return output;
@@ -587,7 +588,7 @@ bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
 {
   std::vector<std::string> options;
   bool output = false;
-  this->Target->GetCompileOptions(options, config, language);
+  this->GeneratorTarget->GetCompileOptions(options, config, language);
   for (std::vector<std::string>::const_iterator options_i = options.begin();
        options_i != options.end(); ++options_i)
     {

+ 0 - 1
Source/cmGlobalGenerator.cxx

@@ -1550,7 +1550,6 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes,
         ti != targets.end(); ++ti)
       {
       cmTarget* t = &ti->second;
-      t->Compute();
       cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg);
       this->GeneratorTargets[t] = gt;
       generatorTargets[t] = gt;

+ 2 - 1
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -1145,7 +1145,8 @@ bool cmGlobalUnixMakefileGenerator3
 ::NeedRequiresStep(cmTarget const& target)
 {
   std::set<std::string> languages;
-  target.GetLanguages(languages,
+  cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&target);
+  gtgt->GetLanguages(languages,
                 target.GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
   for(std::set<std::string>::const_iterator l = languages.begin();
       l != languages.end(); ++l)

+ 1 - 1
Source/cmGlobalVisualStudio8Generator.cxx

@@ -254,7 +254,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
     mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
                           no_working_directory, no_depends,
                           noCommandLines);
-  tgt->Compute();
+
   cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg);
   mf->AddGeneratorTarget(tgt, gt);
 

+ 5 - 3
Source/cmGlobalVisualStudioGenerator.cxx

@@ -90,7 +90,7 @@ bool cmGlobalVisualStudioGenerator::Compute()
         AddUtilityCommand("ALL_BUILD", true, no_working_dir,
                           no_depends, no_commands, false,
                           "Build all projects");
-      allBuild->Compute();
+
       cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]);
       allBuild->GetMakefile()->AddGeneratorTarget(allBuild, gt);
 
@@ -836,17 +836,19 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
 bool
 cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget const& target)
 {
+  cmGeneratorTarget* gt = this->GetGeneratorTarget(&target);
+
   // check to see if this is a fortran build
   std::set<std::string> languages;
   {
   // Issue diagnostic if the source files depend on the config.
   std::vector<cmSourceFile*> sources;
-  if (!target.GetConfigCommonSourceFiles(sources))
+  if (!gt->GetConfigCommonSourceFiles(sources))
     {
     return false;
     }
   }
-  target.GetLanguages(languages, "");
+  gt->GetLanguages(languages, "");
   if(languages.size() == 1)
     {
     if(*languages.begin() == "Fortran")

+ 14 - 11
Source/cmGlobalXCodeGenerator.cxx

@@ -463,7 +463,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
   cmTarget* allbuild = mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
                         no_working_directory,
                         "echo", "Build all projects");
-  allbuild->Compute();
+
   cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
   mf->AddGeneratorTarget(allbuild, allBuildGt);
 
@@ -498,7 +498,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
                           true, no_depends,
                           no_working_directory,
                           "make", "-f", file.c_str());
-    check->Compute();
+
     cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
     mf->AddGeneratorTarget(check, checkGt);
     }
@@ -1124,7 +1124,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
 
     // organize the sources
     std::vector<cmSourceFile*> classes;
-    if (!cmtarget.GetConfigCommonSourceFiles(classes))
+    if (!gtgt->GetConfigCommonSourceFiles(classes))
       {
       return false;
       }
@@ -1383,8 +1383,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
   if(llang.empty()) { return; }
 
   // If the language is compiled as a source trust Xcode to link with it.
-  cmTarget::LinkImplementation const* impl =
-    cmtarget.GetLinkImplementation("NOCONFIG");
+  cmLinkImplementation const* impl =
+    gtgt->GetLinkImplementation("NOCONFIG");
   for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
       li != impl->Languages.end(); ++li)
     {
@@ -1505,7 +1505,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
     }
 
   std::vector<cmSourceFile*> classes;
-  if (!cmtarget.GetConfigCommonSourceFiles(classes))
+  cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget);
+  if (!gtgt->GetConfigCommonSourceFiles(classes))
     {
     return;
     }
@@ -1805,7 +1806,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
 
   // Compute the compilation flags for each language.
   std::set<std::string> languages;
-  target.GetLanguages(languages, configName);
+  cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
+  gtgt->GetLanguages(languages, configName);
   std::map<std::string, std::string> cflags;
   for (std::set<std::string>::iterator li = languages.begin();
        li != languages.end(); ++li)
@@ -1827,7 +1829,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
       AddCompileOptions(flags, &target, lang, configName);
     }
 
-  cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
   std::string llang = gtgt->GetLinkerLanguage(configName);
   if(binary && llang.empty())
     {
@@ -1855,7 +1856,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     this->AppendDefines(ppDefs, exportMacro);
     }
   std::vector<std::string> targetDefines;
-  target.GetCompileDefinitions(targetDefines, configName, "C");
+  gtgt->GetCompileDefinitions(targetDefines, configName, "C");
   this->AppendDefines(ppDefs, targetDefines);
   buildSettings->AddAttribute
     ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
@@ -2557,7 +2558,8 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
   if(cmtarget.GetType() == cmTarget::UTILITY)
     {
     std::vector<cmSourceFile*> sources;
-    if (!cmtarget.GetConfigCommonSourceFiles(sources))
+    cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget);
+    if (!gtgt->GetConfigCommonSourceFiles(sources))
       {
       return 0;
       }
@@ -3085,7 +3087,8 @@ bool cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
         }
 
       std::vector<cmSourceFile*> classes;
-      if (!cmtarget.GetConfigCommonSourceFiles(classes))
+      cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget);
+      if (!gtgt->GetConfigCommonSourceFiles(classes))
         {
         return false;
         }

+ 62 - 0
Source/cmLinkItem.h

@@ -56,4 +56,66 @@ struct cmLinkImplementationLibraries
   std::vector<cmLinkItem> WrongConfigLibraries;
 };
 
+struct cmLinkInterfaceLibraries
+{
+  // Libraries listed in the interface.
+  std::vector<cmLinkItem> Libraries;
+};
+
+struct cmLinkInterface: public cmLinkInterfaceLibraries
+{
+  // Languages whose runtime libraries must be linked.
+  std::vector<std::string> Languages;
+
+  // Shared library dependencies needed for linking on some platforms.
+  std::vector<cmLinkItem> SharedDeps;
+
+  // Number of repetitions of a strongly connected component of two
+  // or more static libraries.
+  int Multiplicity;
+
+  // Libraries listed for other configurations.
+  // Needed only for OLD behavior of CMP0003.
+  std::vector<cmLinkItem> WrongConfigLibraries;
+
+  bool ImplementationIsInterface;
+
+  cmLinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
+};
+
+struct cmOptionalLinkInterface: public cmLinkInterface
+{
+  cmOptionalLinkInterface():
+    LibrariesDone(false), AllDone(false),
+    Exists(false), HadHeadSensitiveCondition(false),
+    ExplicitLibraries(0) {}
+  bool LibrariesDone;
+  bool AllDone;
+  bool Exists;
+  bool HadHeadSensitiveCondition;
+  const char* ExplicitLibraries;
+};
+
+struct cmHeadToLinkInterfaceMap:
+    public std::map<cmTarget const*, cmOptionalLinkInterface>
+{
+};
+
+struct cmLinkImplementation: public cmLinkImplementationLibraries
+{
+  // Languages whose runtime libraries must be linked.
+  std::vector<std::string> Languages;
+};
+
+// Cache link implementation computation from each configuration.
+struct cmOptionalLinkImplementation: public cmLinkImplementation
+{
+  cmOptionalLinkImplementation():
+    LibrariesDone(false), LanguagesDone(false),
+    HadHeadSensitiveCondition(false) {}
+  bool LibrariesDone;
+  bool LanguagesDone;
+  bool HadHeadSensitiveCondition;
+};
+
 #endif

+ 9 - 4
Source/cmLocalGenerator.cxx

@@ -1079,7 +1079,8 @@ void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
                                              const std::string& lang)
 {
   std::vector<std::string> targetDefines;
-  target->GetCompileDefinitions(targetDefines, config, lang);
+  cmGeneratorTarget* gtgt = this->GlobalGenerator->GetGeneratorTarget(target);
+  gtgt->GetCompileDefinitions(targetDefines, config, lang);
   this->AppendDefines(defines, targetDefines);
 }
 
@@ -1090,6 +1091,10 @@ void cmLocalGenerator::AddCompileOptions(
   )
 {
   std::string langFlagRegexVar = std::string("CMAKE_")+lang+"_FLAG_REGEX";
+
+  cmGeneratorTarget* gtgt =
+      this->GlobalGenerator->GetGeneratorTarget(target);
+
   if(const char* langFlagRegexStr =
      this->Makefile->GetDefinition(langFlagRegexVar))
     {
@@ -1100,7 +1105,7 @@ void cmLocalGenerator::AddCompileOptions(
       {
       cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
       }
-    target->GetCompileOptions(opts, config, lang);
+    gtgt->GetCompileOptions(opts, config, lang);
     for(std::vector<std::string>::const_iterator i = opts.begin();
         i != opts.end(); ++i)
       {
@@ -1121,7 +1126,7 @@ void cmLocalGenerator::AddCompileOptions(
       this->AppendFlags(flags, targetFlags);
       }
     std::vector<std::string> opts;
-    target->GetCompileOptions(opts, config, lang);
+    gtgt->GetCompileOptions(opts, config, lang);
     for(std::vector<std::string>::const_iterator i = opts.begin();
         i != opts.end(); ++i)
       {
@@ -1130,7 +1135,7 @@ void cmLocalGenerator::AddCompileOptions(
       }
     }
   std::vector<std::string> features;
-  target->GetCompileFeatures(features, config);
+  gtgt->GetCompileFeatures(features, config);
   for(std::vector<std::string>::const_iterator it = features.begin();
       it != features.end(); ++it)
     {

+ 3 - 1
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1257,7 +1257,9 @@ cmLocalUnixMakefileGenerator3
     {
     // Get the set of source languages in the target.
     std::set<std::string> languages;
-    target.GetLanguages(languages,
+    cmGeneratorTarget *gtgt =
+        this->GlobalGenerator->GetGeneratorTarget(&target);
+    gtgt->GetLanguages(languages,
                       this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
     fout << "\n"
          << "# Per-language clean rules from dependency scanning.\n"

+ 4 - 1
Source/cmLocalVisualStudio6Generator.cxx

@@ -305,9 +305,12 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
 
+  cmGeneratorTarget* gt =
+    this->GlobalGenerator->GetGeneratorTarget(&target);
+
   // get the classes from the source lists then add them to the groups
   std::vector<cmSourceFile*> classes;
-  if (!target.GetConfigCommonSourceFiles(classes))
+  if (!gt->GetConfigCommonSourceFiles(classes))
     {
     return;
     }

+ 5 - 4
Source/cmLocalVisualStudio7Generator.cxx

@@ -763,7 +763,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
   targetOptions.Parse(defineFlags.c_str());
   targetOptions.ParseFinish();
   std::vector<std::string> targetDefines;
-  target.GetCompileDefinitions(targetDefines, configName, "CXX");
+  gt->GetCompileDefinitions(targetDefines, configName, "CXX");
   targetOptions.AddDefines(targetDefines);
   targetOptions.SetVerboseMakefile(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -1469,10 +1469,13 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
 
+  cmGeneratorTarget* gt =
+    this->GlobalGenerator->GetGeneratorTarget(&target);
+
   // get the classes from the source lists then add them to the groups
   this->ModuleDefinitionFile = "";
   std::vector<cmSourceFile*> classes;
-  if (!target.GetConfigCommonSourceFiles(classes))
+  if (!gt->GetConfigCommonSourceFiles(classes))
     {
     return;
     }
@@ -1514,8 +1517,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
     {
     // VS >= 8 support per-config source locations so we
     // list object library content as external objects.
-    cmGeneratorTarget* gt =
-      this->GlobalGenerator->GetGeneratorTarget(&target);
     std::vector<std::string> objs;
     gt->UseObjectLibraries(objs, "");
     if(!objs.empty())

+ 1 - 1
Source/cmMakefileTargetGenerator.cxx

@@ -276,7 +276,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
 {
   // write language flags for target
   std::set<std::string> languages;
-  this->Target->GetLanguages(languages,
+  this->GeneratorTarget->GetLanguages(languages,
                       this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
   // put the compiler in the rules.make file so that if it changes
   // things rebuild

+ 11 - 5
Source/cmQtAutoGenerators.cxx

@@ -403,7 +403,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg,
         )
     {
     std::vector<cmSourceFile*> srcFiles;
-    target->GetConfigCommonSourceFiles(srcFiles);
+    cmGeneratorTarget* gtgt =
+        lg->GetGlobalGenerator()->GetGeneratorTarget(target);
+    gtgt->GetConfigCommonSourceFiles(srcFiles);
     for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
         fileIt != srcFiles.end();
         ++fileIt)
@@ -474,8 +476,6 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg,
                                 /*byproducts=*/rcc_output, depends,
                                 commandLines, false, autogenComment.c_str());
 
-    autogenTarget->Compute();
-
     cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
     makefile->AddGeneratorTarget(autogenTarget, gt);
 
@@ -663,7 +663,10 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target)
   const char* sepHeaders = "";
 
   std::vector<cmSourceFile*> srcFiles;
-  target->GetConfigCommonSourceFiles(srcFiles);
+  cmGeneratorTarget *gtgt = target->GetMakefile()
+                                  ->GetGlobalGenerator()
+                                  ->GetGeneratorTarget(target);
+  gtgt->GetConfigCommonSourceFiles(srcFiles);
 
   const char *skipMocSep = "";
   const char *skipUicSep = "";
@@ -1048,7 +1051,10 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
   cmMakefile *makefile = target->GetMakefile();
 
   std::vector<cmSourceFile*> srcFiles;
-  target->GetConfigCommonSourceFiles(srcFiles);
+  cmGeneratorTarget *gtgt = target->GetMakefile()
+                                  ->GetGlobalGenerator()
+                                  ->GetGeneratorTarget(target);
+  gtgt->GetConfigCommonSourceFiles(srcFiles);
 
   std::string qrcInputs;
   const char* qrcInputsSep = "";

文件差异内容过多而无法显示
+ 120 - 770
Source/cmTarget.cxx


+ 19 - 88
Source/cmTarget.h

@@ -132,15 +132,11 @@ public:
   void AddPostBuildCommand(cmCustomCommand const &cmd)
     {this->PostBuildCommands.push_back(cmd);}
 
-  void Compute();
-
   /**
    * Get the list of the source files used by this target
    */
   void GetSourceFiles(std::vector<cmSourceFile*> &files,
                       const std::string& config) const;
-  bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
-
   /**
    * Add sources to the target.
    */
@@ -233,54 +229,16 @@ public:
 
   void GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const;
 
-  /** The link interface specifies transitive library dependencies and
-      other information needed by targets that link to this target.  */
-  struct LinkInterfaceLibraries
-  {
-    // Libraries listed in the interface.
-    std::vector<cmLinkItem> Libraries;
-  };
-  struct LinkInterface: public LinkInterfaceLibraries
-  {
-    // Languages whose runtime libraries must be linked.
-    std::vector<std::string> Languages;
-
-    // Shared library dependencies needed for linking on some platforms.
-    std::vector<cmLinkItem> SharedDeps;
-
-    // Number of repetitions of a strongly connected component of two
-    // or more static libraries.
-    int Multiplicity;
-
-    // Libraries listed for other configurations.
-    // Needed only for OLD behavior of CMP0003.
-    std::vector<cmLinkItem> WrongConfigLibraries;
-
-    bool ImplementationIsInterface;
-
-    LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
-  };
-
-  /** Get the link interface for the given configuration.  Returns 0
-      if the target cannot be linked.  */
-  LinkInterface const* GetLinkInterface(const std::string& config,
-                                        cmTarget const* headTarget) const;
-  LinkInterfaceLibraries const*
-    GetLinkInterfaceLibraries(const std::string& config,
-                              cmTarget const* headTarget,
-                              bool usage_requirements_only) const;
-
-  struct LinkImplementation: public cmLinkImplementationLibraries
-  {
-    // Languages whose runtime libraries must be linked.
-    std::vector<std::string> Languages;
-  };
-  LinkImplementation const*
-    GetLinkImplementation(const std::string& config) const;
-
   cmLinkImplementationLibraries const*
     GetLinkImplementationLibraries(const std::string& config) const;
 
+  void ComputeLinkImplementationLibraries(const std::string& config,
+                                          cmOptionalLinkImplementation& impl,
+                                          cmTarget const* head) const;
+
+  cmOptionalLinkImplementation&
+  GetLinkImplMap(std::string const& config) const;
+
   cmTarget const* FindTargetToLink(std::string const& name) const;
 
   /** Strip off leading and trailing whitespace from an item named in
@@ -331,7 +289,6 @@ public:
   bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out,
                         const char* newExt = 0) const;
 
-  bool HaveBuildTreeRPATH(const std::string& config) const;
   bool HaveInstallTreeRPATH() const;
 
   // Get the properties
@@ -346,18 +303,6 @@ public:
       If no macro should be defined null is returned.  */
   const char* GetExportMacro() const;
 
-  void GetCompileDefinitions(std::vector<std::string> &result,
-                             const std::string& config,
-                             const std::string& language) const;
-
-  // Compute the set of languages compiled by the target.  This is
-  // computed every time it is called because the languages can change
-  // when source file properties are changed and we do not have enough
-  // information to forward these property changes to the targets
-  // until we have per-target object file properties.
-  void GetLanguages(std::set<std::string>& languages,
-                    std::string const& config) const;
-
   /** Return whether this target is an executable with symbol exports
       enabled.  */
   bool IsExecutableWithExports() const;
@@ -401,9 +346,6 @@ public:
   /** @return whether this target have a well defined output file name. */
   bool HaveWellDefinedOutputFiles() const;
 
-  std::vector<std::string> GetIncludeDirectories(
-                     const std::string& config,
-                     const std::string& language) const;
   void InsertInclude(std::string const& entry,
                      cmListFileBacktrace const& bt,
                      bool before = false);
@@ -415,12 +357,6 @@ public:
 
   void AppendBuildInterfaceIncludes();
 
-  void GetCompileOptions(std::vector<std::string> &result,
-                         const std::string& config,
-                         const std::string& language) const;
-  void GetCompileFeatures(std::vector<std::string> &features,
-                          const std::string& config) const;
-
   bool IsNullImpliedByLinkLibraries(const std::string &p) const;
 
   std::string GetDebugGeneratorExpressions(const std::string &value,
@@ -439,6 +375,18 @@ public:
     return this->MaxLanguageStandards;
   }
 
+  cmStringRange GetIncludeDirectoriesEntries() const;
+  cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
+
+  cmStringRange GetCompileOptionsEntries() const;
+  cmBacktraceRange GetCompileOptionsBacktraces() const;
+
+  cmStringRange GetCompileFeaturesEntries() const;
+  cmBacktraceRange GetCompileFeaturesBacktraces() const;
+
+  cmStringRange GetCompileDefinitionsEntries() const;
+  cmBacktraceRange GetCompileDefinitionsBacktraces() const;
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   const LinkLibraryVectorType &GetLinkLibrariesForVS6() const {
   return this->LinkLibrariesForVS6;}
@@ -553,11 +501,7 @@ private:
   bool IsApple;
   bool IsImportedTarget;
   bool BuildInterfaceIncludesAppended;
-  mutable bool DebugIncludesDone;
-  mutable bool DebugCompileOptionsDone;
-  mutable bool DebugCompileDefinitionsDone;
   mutable bool DebugSourcesDone;
-  mutable bool DebugCompileFeaturesDone;
   mutable bool LinkImplementationLanguageIsContextDependent;
 #if defined(_WIN32) && !defined(__CYGWIN__)
   bool LinkLibrariesForVS6Analyzed;
@@ -591,23 +535,10 @@ private:
   void ComputeImportInfo(std::string const& desired_config,
                          ImportInfo& info) const;
 
-
-  LinkInterface const*
-    GetImportLinkInterface(const std::string& config, cmTarget const* head,
-                           bool usage_requirements_only) const;
-
   cmLinkImplementationLibraries const*
     GetLinkImplementationLibrariesInternal(const std::string& config,
                                            cmTarget const* head) const;
 
-  void ExpandLinkItems(std::string const& prop, std::string const& value,
-                       std::string const& config, cmTarget const* headTarget,
-                       bool usage_requirements_only,
-                       std::vector<cmLinkItem>& items,
-                       bool& hadHeadSensitiveCondition) const;
-  void LookupLinkItems(std::vector<std::string> const& names,
-                       std::vector<cmLinkItem>& items) const;
-
   std::string ProcessSourceItemCMP0049(const std::string& s);
 
   void ClearLinkMaps();

+ 2 - 2
Source/cmVisualStudio10TargetGenerator.cxx

@@ -965,7 +965,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
   std::vector<cmSourceGroup> sourceGroups =
     this->Makefile->GetSourceGroups();
   std::vector<cmSourceFile*> classes;
-  if (!this->Target->GetConfigCommonSourceFiles(classes))
+  if (!this->GeneratorTarget->GetConfigCommonSourceFiles(classes))
     {
     return;
     }
@@ -1934,7 +1934,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   clOptions.Parse(flags.c_str());
   clOptions.Parse(defineFlags.c_str());
   std::vector<std::string> targetDefines;
-  this->Target->GetCompileDefinitions(targetDefines,
+  this->GeneratorTarget->GetCompileDefinitions(targetDefines,
                                       configName.c_str(), "CXX");
   clOptions.AddDefines(targetDefines);
   if(this->MSTools)

部分文件因为文件数量过多而无法显示