Browse Source

ENH: Refactor target output dir computation

This creates cmTarget::GetOutputInfo to compute, cache, and lookup
target output directory information on a per-configuration basis.  It
avoids re-computing the information every time it is needed.
Brad King 16 years ago
parent
commit
275c21d351
2 changed files with 65 additions and 69 deletions
  1. 54 63
      Source/cmTarget.cxx
  2. 11 6
      Source/cmTarget.h

+ 54 - 63
Source/cmTarget.cxx

@@ -1936,6 +1936,48 @@ void cmTarget::MarkAsImported()
   this->IsImportedTarget = true;
 }
 
+//----------------------------------------------------------------------------
+cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
+{
+  // There is no output information for imported targets.
+  if(this->IsImported())
+    {
+    return 0;
+    }
+
+  // Only libraries and executables have well-defined output files.
+  if(this->GetType() != cmTarget::STATIC_LIBRARY &&
+     this->GetType() != cmTarget::SHARED_LIBRARY &&
+     this->GetType() != cmTarget::MODULE_LIBRARY &&
+     this->GetType() != cmTarget::EXECUTABLE)
+    {
+    std::string msg = "cmTarget::GetOutputInfo called for ";
+    msg += this->GetName();
+    msg += " which has type ";
+    msg += cmTarget::TargetTypeNames[this->GetType()];
+    this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg);
+    return 0;
+    }
+
+  // Lookup/compute/cache the output information for this configuration.
+  std::string config_upper;
+  if(config && *config)
+    {
+    config_upper = cmSystemTools::UpperCase(config);
+    }
+  OutputInfoMapType::const_iterator i =
+    this->OutputInfoMap.find(config_upper);
+  if(i == this->OutputInfoMap.end())
+    {
+    OutputInfo info;
+    this->ComputeOutputDir(config, false, info.OutDir);
+    this->ComputeOutputDir(config, true, info.ImpDir);
+    OutputInfoMapType::value_type entry(config_upper, info);
+    i = this->OutputInfoMap.insert(entry).first;
+    }
+  return &i->second;
+}
+
 //----------------------------------------------------------------------------
 std::string cmTarget::GetDirectory(const char* config, bool implib)
 {
@@ -1946,22 +1988,12 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
       cmSystemTools::GetFilenamePath(
       this->ImportedGetFullPath(config, implib));
     }
-  else
+  else if(OutputInfo const* info = this->GetOutputInfo(config))
     {
     // Return the directory in which the target will be built.
-    if(config && *config)
-      {
-      // Add the configuration's subdirectory.
-      std::string dir = this->GetOutputDir(implib);
-      this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
-        AppendDirectoryForConfig("/", config, "", dir);
-      return dir;
-      }
-    else
-      {
-      return this->GetOutputDir(implib);
-      }
+    return implib? info->ImpDir : info->OutDir;
     }
+  return "";
 }
 
 //----------------------------------------------------------------------------
@@ -3153,56 +3185,9 @@ const char* cmTarget::GetOutputTargetType(bool implib)
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetOutputDir(bool implib)
+void cmTarget::ComputeOutputDir(const char* config,
+                                bool implib, std::string& out)
 {
-  // The implib option is only allowed for shared libraries, module
-  // libraries, and executables.
-  if(this->GetType() != cmTarget::SHARED_LIBRARY &&
-     this->GetType() != cmTarget::MODULE_LIBRARY &&
-     this->GetType() != cmTarget::EXECUTABLE)
-    {
-    implib = false;
-    }
-
-  // Sanity check.  Only generators on platforms supporting import
-  // libraries should be asking for the import library output
-  // directory.
-  if(implib &&
-     !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
-    {
-    std::string msg =  "GetOutputDir, imlib set but there is no "
-      "CMAKE_IMPORT_LIBRARY_SUFFIX for target: ";
-    msg += this->GetName();
-    this->GetMakefile()->
-      IssueMessage(cmake::INTERNAL_ERROR,
-                   msg.c_str());
-    }
-  if(implib && !this->DLLPlatform)
-    {
-    std::string msg =  "implib set for platform that does not "
-      " support DLL's for target: ";
-    msg += this->GetName();
-    this->GetMakefile()->
-      IssueMessage(cmake::INTERNAL_ERROR,
-                   msg.c_str());
-    }
-
-  return this->ComputeBaseOutputDir(implib);
-}
-
-//----------------------------------------------------------------------------
-std::string const& cmTarget::ComputeBaseOutputDir(bool implib)
-{
-  // Select whether we are constructing the directory for the main
-  // target or the import library.
-  std::string& out = implib? this->BaseOutputDirImplib : this->BaseOutputDir;
-
-  // Return immediately if the directory has already been computed.
-  if(!out.empty())
-    {
-    return out;
-    }
-
   // Look for a target property defining the target output directory
   // based on the target type.
   const char* propertyName = 0;
@@ -3242,7 +3227,13 @@ std::string const& cmTarget::ComputeBaseOutputDir(bool implib)
   // relative to the current output directory for this makefile.
   out = (cmSystemTools::CollapseFullPath
          (out.c_str(), this->Makefile->GetStartOutputDirectory()));
-  return out;
+
+  // The generator may add the configuration's subdirectory.
+  if(config && *config)
+    {
+    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
+      AppendDirectoryForConfig("/", config, "", out);
+    }
 }
 
 //----------------------------------------------------------------------------

+ 11 - 6
Source/cmTarget.h

@@ -462,10 +462,6 @@ private:
   // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
   const char* GetOutputTargetType(bool implib);
 
-  // Get the full path to the target output directory.
-  std::string GetOutputDir(bool implib);
-  std::string const& ComputeBaseOutputDir(bool implib);
-
   // Get the target base name.
   std::string GetOutputName(const char* config, bool implib);
 
@@ -500,8 +496,6 @@ private:
   bool HaveInstallRule;
   std::string InstallPath;
   std::string RuntimeInstallPath;
-  std::string BaseOutputDir;
-  std::string BaseOutputDirImplib;
   std::string Location;
   std::string ExportMacro;
   std::set<cmStdString> Utilities;
@@ -511,6 +505,17 @@ private:
   bool DLLPlatform;
   bool IsImportedTarget;
 
+  // Cache target output paths for each configuration.
+  struct OutputInfo
+  {
+    std::string OutDir;
+    std::string ImpDir;
+  };
+  typedef std::map<cmStdString, OutputInfo> OutputInfoMapType;
+  OutputInfoMapType OutputInfoMap;
+  OutputInfo const* GetOutputInfo(const char* config);
+  void ComputeOutputDir(const char* config, bool implib, std::string& out);
+
   // Cache import information from properties for each configuration.
   struct ImportInfo
   {