From 171b0993d9596bd3d8e7363515346c6313e7d3a2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 14 Feb 2013 09:51:24 -0500 Subject: Avoid duplicate RPATH entries Teach cmComputeLinkInformation::GetRPath to avoid adding the same directory to the output runtime path more than once. --- Source/cmComputeLinkInformation.cxx | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index cd3ef59..a40df51 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1752,6 +1752,22 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath) } //---------------------------------------------------------------------------- +static void cmCLI_ExpandListUnique(const char* str, + std::vector& out, + std::set& emitted) +{ + std::vector tmp; + cmSystemTools::ExpandListArgument(str, tmp); + for(std::vector::iterator i = tmp.begin(); i != tmp.end(); ++i) + { + if(emitted.insert(*i).second) + { + out.push_back(*i); + } + } +} + +//---------------------------------------------------------------------------- void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, bool for_install) { @@ -1776,10 +1792,11 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); // Construct the RPATH. + std::set emitted; if(use_install_rpath) { const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); - cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs); + cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); } if(use_build_rpath || use_link_rpath) { @@ -1791,7 +1808,10 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, // support or if using the link path as an rpath. if(use_build_rpath) { - runtimeDirs.push_back(*ri); + if(emitted.insert(*ri).second) + { + runtimeDirs.push_back(*ri); + } } else if(use_link_rpath) { @@ -1803,7 +1823,10 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) && !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir)) { - runtimeDirs.push_back(*ri); + if(emitted.insert(*ri).second) + { + runtimeDirs.push_back(*ri); + } } } } @@ -1811,7 +1834,7 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, // Add runtime paths required by the platform to always be // present. This is done even when skipping rpath support. - cmSystemTools::ExpandListArgument(this->RuntimeAlways.c_str(), runtimeDirs); + cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted); } //---------------------------------------------------------------------------- -- cgit v0.12 From baa33acbdaa3bf88fe1fc591562574ab43b056fe Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 14 Feb 2013 09:58:29 -0500 Subject: AIX-GNU: Put implicit link directories in runtime libpath (#13909) The GNU compiler front-ends on AIX invoke the linker with flags of the form "-L/path/to/gnu/runtime/lib" to tell ld where to find the language runtime libraries. They depend on the default libpath behavior documented in "man ld" to add the -L paths also to the runtime libpath so the dynamic loader can find the language runtime libraries. This differs from platforms whose linkers have distinct -rpath flags that non-system compilers can use to tell the dynamic loader where to find their language runtime libraries. Since commit 96fd5909 (Implement linking with paths to library files, 2008-01-22) CMake always passes "-Wl,-blibpath:" followed by any project-defined RPATH plus "/usr/lib:/lib" in order to explicitly set the runtime libpath and avoid getting all the project -L paths in the runtime libpath. The explicit libpath prevents the GNU compiler runtime library -L paths from being placed in the libpath and then the dynamic loader fails to find the language runtime libraries. CMake already detects the implicit link directories for each language since commit 07ea19ad (Implicit link info for C, CXX, and Fortran, 2009-07-23). Add the implicit link directories to the explicit runtime libpath for GNU compilers on AIX to fix this use case. --- Modules/Platform/AIX-GNU.cmake | 1 + Source/cmComputeLinkInformation.cxx | 22 ++++++++++++++++++++++ Source/cmDocumentVariables.cxx | 3 +++ 3 files changed, 26 insertions(+) diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake index 81ba365..a73a7a2 100644 --- a/Modules/Platform/AIX-GNU.cmake +++ b/Modules/Platform/AIX-GNU.cmake @@ -23,4 +23,5 @@ macro(__aix_compiler_gnu lang) set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,-G,-brtl,-bnoipath") set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-brtl,-bnoipath,-bexpall") # +s, flag for exe link to use shared lib + set(CMAKE_${lang}_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH 1) endmacro() diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index a40df51..ee8bd90 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1832,6 +1832,28 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, } } + // Add runtime paths required by the languages to always be + // present. This is done even when skipping rpath support. + { + cmTarget::LinkClosure const* lc = + this->Target->GetLinkClosure(this->Config); + for(std::vector::const_iterator li = lc->Languages.begin(); + li != lc->Languages.end(); ++li) + { + std::string useVar = "CMAKE_" + *li + + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH"; + if(this->Makefile->IsOn(useVar.c_str())) + { + std::string dirVar = "CMAKE_" + *li + + "_IMPLICIT_LINK_DIRECTORIES"; + if(const char* dirs = this->Makefile->GetDefinition(dirVar.c_str())) + { + cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted); + } + } + } + } + // Add runtime paths required by the platform to always be // present. This is done even when skipping rpath support. cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted); diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 8db0e8f..23590b8 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1803,6 +1803,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH", cmProperty::VARIABLE,0,0); + cm->DefineProperty( + "CMAKE__USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH", + cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE__FLAGS", cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_SHARED_MODULE__FLAGS", -- cgit v0.12