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.
This commit is contained in:
Clinton Stimpson 2014-02-01 21:18:04 -07:00
parent 6385c71516
commit 028a5285d8
7 changed files with 94 additions and 11 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{ {
std::string runpath = *i;
runpath = this->ExpandCFGIntDir(runpath, configName);
if(unique_dirs.find(runpath) == unique_dirs.end())
{
unique_dirs.insert(runpath);
if(!search_paths.empty()) if(!search_paths.empty())
{ {
search_paths += " "; search_paths += " ";
} }
search_paths += this->XCodeEscapePath((*i).c_str()); search_paths += this->XCodeEscapePath(runpath.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)
{ {

View File

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

View File

@ -669,24 +669,38 @@ 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 // Note: These paths are kept unique to avoid install_name_tool corruption.
// corruption on 10.6. 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)
{ {
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 << "execute_process(COMMAND " << installNameTool << "\n";
os << indent << " -delete_rpath \"" << *i << "\"\n"; os << indent << " -delete_rpath \"" << runpath << "\"\n";
os << indent << " \"" << toDestDirPath << "\")\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)
{ {
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 << "execute_process(COMMAND " << installNameTool << "\n";
os << indent << " -add_rpath \"" << *i << "\"\n"; os << indent << " -add_rpath \"" << runpath << "\"\n";
os << indent << " \"" << toDestDirPath << "\")\n"; os << indent << " \"" << toDestDirPath << "\")\n";
} }
} }
}
else else
{ {
// Construct the original rpath string to be replaced. // Construct the original rpath string to be replaced.