Просмотр исходного кода

OS X: Make sure RPATHs are unique to avoid possible corruption.

When using link_directories() and including CMAKE_CFG_INTDIR,
one can end up with duplicate RPATHs in the binary which
install_name_tool cannot fix without corrupting the binary.
Also, the cmake_install.cmake file has been fixed to correctly
handle these generator specific variables.
Clinton Stimpson 12 лет назад
Родитель
Сommit
028a5285d8

+ 7 - 0
Source/cmGlobalGenerator.cxx

@@ -3032,3 +3032,10 @@ void cmGlobalGenerator::ProcessEvaluationFiles()
       }
       }
     }
     }
 }
 }
+
+//----------------------------------------------------------------------------
+std::string cmGlobalGenerator::ExpandCFGIntDir(const std::string& str,
+                            const std::string& /*config*/) const
+{
+  return str;
+}

+ 4 - 0
Source/cmGlobalGenerator.h

@@ -193,6 +193,10 @@ public:
   ///! What is the configurations directory variable called?
   ///! What is the configurations directory variable called?
   virtual const char* GetCMakeCFGIntDir() const { return "."; }
   virtual const char* GetCMakeCFGIntDir() const { return "."; }
 
 
+  ///! expand CFGIntDir for a configuration
+  virtual std::string ExpandCFGIntDir(const std::string& str,
+                                      const std::string& config) const;
+
   /** Get whether the generator should use a script for link commands.  */
   /** Get whether the generator should use a script for link commands.  */
   bool GetUseLinkScript() const { return this->UseLinkScript; }
   bool GetUseLinkScript() const { return this->UseLinkScript; }
 
 

+ 17 - 0
Source/cmGlobalVisualStudioGenerator.cxx

@@ -902,3 +902,20 @@ cmGlobalVisualStudioGenerator::OrderedTargetDependSet
     this->insert(*ti);
     this->insert(*ti);
     }
     }
 }
 }
+
+std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir(
+  const std::string& str,
+  const std::string& config) const
+{
+  std::string replace = GetCMakeCFGIntDir();
+
+  std::string tmp = str;
+  for(std::string::size_type i = tmp.find(replace);
+      i != std::string::npos;
+      i = tmp.find(replace, i))
+    {
+    tmp.replace(i, replace.size(), config);
+    i += config.size();
+    }
+  return tmp;
+}

+ 4 - 0
Source/cmGlobalVisualStudioGenerator.h

@@ -84,6 +84,10 @@ public:
 
 
   virtual void FindMakeProgram(cmMakefile*);
   virtual void FindMakeProgram(cmMakefile*);
 
 
+
+  virtual std::string ExpandCFGIntDir(const std::string& str,
+                                      const std::string& config) const;
+
 protected:
 protected:
   // Does this VS version link targets to each other if there are
   // Does this VS version link targets to each other if there are
   // dependencies in the SLN file?  This was done for VS versions
   // dependencies in the SLN file?  This was done for VS versions

+ 37 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -2272,14 +2272,24 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     std::string search_paths;
     std::string search_paths;
     std::vector<std::string> runtimeDirs;
     std::vector<std::string> runtimeDirs;
     pcli->GetRPath(runtimeDirs, false);
     pcli->GetRPath(runtimeDirs, false);
+    // runpath dirs needs to be unique to prevent corruption
+    std::set<std::string> unique_dirs;
+
     for(std::vector<std::string>::const_iterator i = runtimeDirs.begin();
     for(std::vector<std::string>::const_iterator i = runtimeDirs.begin();
         i != runtimeDirs.end(); ++i)
         i != runtimeDirs.end(); ++i)
       {
       {
-      if(!search_paths.empty())
+      std::string runpath = *i;
+      runpath = this->ExpandCFGIntDir(runpath, configName);
+
+      if(unique_dirs.find(runpath) == unique_dirs.end())
         {
         {
-        search_paths += " ";
+        unique_dirs.insert(runpath);
+        if(!search_paths.empty())
+          {
+          search_paths += " ";
+          }
+        search_paths += this->XCodeEscapePath(runpath.c_str());
         }
         }
-      search_paths += this->XCodeEscapePath((*i).c_str());
       }
       }
     if(!search_paths.empty())
     if(!search_paths.empty())
       {
       {
@@ -3675,6 +3685,30 @@ const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
     "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
     "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
 }
 }
 
 
+std::string cmGlobalXCodeGenerator::ExpandCFGIntDir(const std::string& str,
+                                        const std::string& config) const
+{
+  std::string replace1 = "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+  std::string replace2 = "$(CONFIGURATION)";
+
+  std::string tmp = str;
+  for(std::string::size_type i = tmp.find(replace1);
+      i != std::string::npos;
+      i = tmp.find(replace1, i))
+    {
+    tmp.replace(i, replace1.size(), config);
+    i += config.size();
+    }
+  for(std::string::size_type i = tmp.find(replace2);
+      i != std::string::npos;
+      i = tmp.find(replace2, i))
+    {
+    tmp.replace(i, replace2.size(), config);
+    i += config.size();
+    }
+  return tmp;
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
 {
 {

+ 3 - 0
Source/cmGlobalXCodeGenerator.h

@@ -79,6 +79,9 @@ public:
 
 
   ///! What is the configurations directory variable called?
   ///! What is the configurations directory variable called?
   virtual const char* GetCMakeCFGIntDir() const;
   virtual const char* GetCMakeCFGIntDir() const;
+  ///! expand CFGIntDir
+  virtual std::string ExpandCFGIntDir(const std::string& str,
+                                      const std::string& config) const;
 
 
   void SetCurrentLocalGenerator(cmLocalGenerator*);
   void SetCurrentLocalGenerator(cmLocalGenerator*);
 
 

+ 22 - 8
Source/cmInstallTargetGenerator.cxx

@@ -669,22 +669,36 @@ cmInstallTargetGenerator
     cli->GetRPath(oldRuntimeDirs, false);
     cli->GetRPath(oldRuntimeDirs, false);
     cli->GetRPath(newRuntimeDirs, true);
     cli->GetRPath(newRuntimeDirs, true);
 
 
-    // Note: These are separate commands to avoid install_name_tool
-    // corruption on 10.6.
+    // Note: These paths are kept unique to avoid install_name_tool corruption.
+    std::set<std::string> runpaths;
     for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin();
     for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin();
         i != oldRuntimeDirs.end(); ++i)
         i != oldRuntimeDirs.end(); ++i)
       {
       {
-      os << indent << "execute_process(COMMAND " << installNameTool << "\n";
-      os << indent << "  -delete_rpath \"" << *i << "\"\n";
-      os << indent << "  \"" << toDestDirPath << "\")\n";
+      std::string runpath = this->Target->GetMakefile()->GetLocalGenerator()->
+        GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+
+      if(runpaths.find(runpath) == runpaths.end())
+        {
+        runpaths.insert(runpath);
+        os << indent << "execute_process(COMMAND " << installNameTool << "\n";
+        os << indent << "  -delete_rpath \"" << runpath << "\"\n";
+        os << indent << "  \"" << toDestDirPath << "\")\n";
+        }
       }
       }
 
 
+    runpaths.clear();
     for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
     for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
         i != newRuntimeDirs.end(); ++i)
         i != newRuntimeDirs.end(); ++i)
       {
       {
-      os << indent << "execute_process(COMMAND " << installNameTool << "\n";
-      os << indent << "  -add_rpath \"" << *i << "\"\n";
-      os << indent << "  \"" << toDestDirPath << "\")\n";
+      std::string runpath = this->Target->GetMakefile()->GetLocalGenerator()->
+        GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+
+      if(runpaths.find(runpath) == runpaths.end())
+        {
+        os << indent << "execute_process(COMMAND " << installNameTool << "\n";
+        os << indent << "  -add_rpath \"" << runpath << "\"\n";
+        os << indent << "  \"" << toDestDirPath << "\")\n";
+        }
       }
       }
     }
     }
   else
   else