From b41ad3b399c591f8f35eaacf056ffd9016b9e0bc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 8 Jun 2011 08:46:31 -0400 Subject: [PATCH] Teach find_(library|package) about Linux multiarch (#12037) Implement support for multiarch as specified here: http://wiki.debian.org/Multiarch https://wiki.ubuntu.com/MultiarchSpec Detect the part of /lib/ from the implicit library search path from each compiler to set CMAKE__LIBRARY_ARCHITECTURE. Define CMAKE_LIBRARY_ARCHITECTURE using one of these values (they should all be the same). Teach the find_library and find_package commands to search /lib/ whenever they would search /lib. --- Modules/CMakeCCompiler.cmake.in | 5 +++++ Modules/CMakeCXXCompiler.cmake.in | 5 +++++ Modules/CMakeDetermineCompilerABI.cmake | 11 +++++++++++ Modules/CMakeFortranCompiler.cmake.in | 5 +++++ Modules/Platform/Linux.cmake | 3 +++ Source/cmDocumentVariables.cxx | 20 ++++++++++++++++++++ Source/cmFindBase.cxx | 12 ++++++++++++ Source/cmFindLibraryCommand.cxx | 4 ++++ Source/cmFindPackageCommand.cxx | 24 ++++++++++++++++++------ Source/cmFindPackageCommand.h | 1 + Source/cmFindPathCommand.cxx | 2 ++ Source/cmFindProgramCommand.cxx | 2 ++ 12 files changed, 88 insertions(+), 6 deletions(-) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 051df4cc7..04a5cec6d 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -28,6 +28,7 @@ SET(CMAKE_C_LINKER_PREFERENCE 10) # Save compiler ABI information. SET(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@") SET(CMAKE_C_COMPILER_ABI "@CMAKE_C_COMPILER_ABI@") +SET(CMAKE_C_LIBRARY_ARCHITECTURE "@CMAKE_C_LIBRARY_ARCHITECTURE@") IF(CMAKE_C_SIZEOF_DATA_PTR) SET(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") @@ -37,6 +38,10 @@ IF(CMAKE_C_COMPILER_ABI) SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") ENDIF(CMAKE_C_COMPILER_ABI) +IF(CMAKE_C_LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_C_LIBRARY_ARCHITECTURE@") +ENDIF() + SET(CMAKE_C_HAS_ISYSROOT "@CMAKE_C_HAS_ISYSROOT@") @CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index d7ae8d994..ea06526cc 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -29,6 +29,7 @@ SET(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) # Save compiler ABI information. SET(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@") SET(CMAKE_CXX_COMPILER_ABI "@CMAKE_CXX_COMPILER_ABI@") +SET(CMAKE_CXX_LIBRARY_ARCHITECTURE "@CMAKE_CXX_LIBRARY_ARCHITECTURE@") IF(CMAKE_CXX_SIZEOF_DATA_PTR) SET(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") @@ -38,6 +39,10 @@ IF(CMAKE_CXX_COMPILER_ABI) SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") ENDIF(CMAKE_CXX_COMPILER_ABI) +IF(CMAKE_CXX_LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_CXX_LIBRARY_ARCHITECTURE@") +ENDIF() + SET(CMAKE_CXX_HAS_ISYSROOT "@CMAKE_CXX_HAS_ISYSROOT@") @CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 7f918e6df..39d1f17b7 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -86,6 +86,17 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) SET(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE) SET(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE) + # Detect library architecture directory name. + IF(CMAKE_LIBRARY_ARCHITECTURE_REGEX) + FOREACH(dir ${implicit_dirs}) + IF("${dir}" MATCHES "/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$") + GET_FILENAME_COMPONENT(arch "${dir}" NAME) + SET(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${arch}" PARENT_SCOPE) + BREAK() + ENDIF() + ENDFOREACH() + ENDIF() + ELSE(CMAKE_DETERMINE_${lang}_ABI_COMPILED) MESSAGE(STATUS "Detecting ${lang} compiler ABI info - failed") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 146a6f2c2..53d95525f 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -34,6 +34,7 @@ ENDIF(UNIX) # Save compiler ABI information. SET(CMAKE_Fortran_SIZEOF_DATA_PTR "@CMAKE_Fortran_SIZEOF_DATA_PTR@") SET(CMAKE_Fortran_COMPILER_ABI "@CMAKE_Fortran_COMPILER_ABI@") +SET(CMAKE_Fortran_LIBRARY_ARCHITECTURE "@CMAKE_Fortran_LIBRARY_ARCHITECTURE@") IF(CMAKE_Fortran_SIZEOF_DATA_PTR AND NOT CMAKE_SIZEOF_VOID_P) SET(CMAKE_SIZEOF_VOID_P "${CMAKE_Fortran_SIZEOF_DATA_PTR}") @@ -43,5 +44,9 @@ IF(CMAKE_Fortran_COMPILER_ABI) SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_Fortran_COMPILER_ABI}") ENDIF(CMAKE_Fortran_COMPILER_ABI) +IF(CMAKE_Fortran_LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_Fortran_LIBRARY_ARCHITECTURE@") +ENDIF() + SET(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "@CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES@") SET(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@") diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index 6490dd1e5..57d1b3471 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -45,6 +45,9 @@ ELSE(DEFINED CMAKE_INSTALL_SO_NO_EXE) ENDIF(EXISTS "/etc/debian_version") ENDIF(DEFINED CMAKE_INSTALL_SO_NO_EXE) +# Match multiarch library directory names. +SET(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+-linux-gnu") + INCLUDE(Platform/UnixPaths) # Debian has lib64 paths only for compatibility so they should not be diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 994445d4e..ea25e60fd 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -822,6 +822,18 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "set to the output of uname -r. On other " "systems this is set to major-minor version numbers.",false, "Variables That Describe the System"); + cm->DefineProperty + ("CMAKE_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE, + "Target architecture library directory name, if detected.", + "This is the value of CMAKE__LIBRARY_ARCHITECTURE as " + "detected for one of the enabled languages.",false, + "Variables That Describe the System"); + cm->DefineProperty + ("CMAKE_LIBRARY_ARCHITECTURE_REGEX", cmProperty::VARIABLE, + "Regex matching possible target architecture library directory names.", + "This is used to detect CMAKE__LIBRARY_ARCHITECTURE from the " + "implicit linker search path by matching the name.",false, + "Variables That Describe the System"); cm->DefineProperty ("CMAKE_HOST_SYSTEM", cmProperty::VARIABLE, @@ -1359,6 +1371,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "language and reports the results in this variable.", false, "Variables for Languages"); + cm->DefineProperty + ("CMAKE__LIBRARY_ARCHITECTURE", cmProperty::VARIABLE, + "Target architecture library directory name detected for .", + "If the compiler passes to the linker an architecture-specific " + "system library search directory such as /lib/ this " + "variable contains the name if/as detected by CMake.",false, + "Variables for Languages"); + cm->DefineProperty ("CMAKE__LINKER_PREFERENCE_PROPAGATES", cmProperty::VARIABLE, "True if CMAKE__LINKER_PREFERENCE propagates across targets.", diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index d0fe99f24..ce9deb143 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -72,12 +72,14 @@ void cmFindBase::GenerateDocumentation() "1. Search paths specified in cmake-specific cache variables. " "These are intended to be used on the command line with a -DVAR=value. " "This can be skipped if NO_CMAKE_PATH is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " /XXX_SUBDIR for each in CMAKE_PREFIX_PATH\n" " CMAKE_XXX_PATH\n" " CMAKE_XXX_MAC_PATH\n" "2. Search paths specified in cmake-specific environment variables. " "These are intended to be set in the user's shell configuration. " "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " /XXX_SUBDIR for each in CMAKE_PREFIX_PATH\n" " CMAKE_XXX_PATH\n" " CMAKE_XXX_MAC_PATH\n" @@ -92,6 +94,7 @@ void cmFindBase::GenerateDocumentation() "5. Search cmake variables defined in the Platform files " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " "is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " /XXX_SUBDIR for each in CMAKE_SYSTEM_PREFIX_PATH\n" " CMAKE_SYSTEM_XXX_PATH\n" " CMAKE_SYSTEM_XXX_MAC_PATH\n" @@ -346,6 +349,15 @@ void cmFindBase::AddPrefixPaths(std::vector const& in_paths, { dir += "/"; } + if(subdir == "lib") + { + const char* arch = + this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); + if(arch && *arch) + { + this->AddPathInternal(dir+"lib/"+arch, pathType); + } + } std::string add = dir + subdir; if(add != "/") { diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index b3093764a..6355a85a7 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -44,6 +44,10 @@ void cmFindLibraryCommand::GenerateDocumentation() "SEARCH_XXX", "library"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "lib"); + cmSystemTools::ReplaceString( + this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", + " /lib/ if CMAKE_LIBRARY_ARCHITECTURE is set, and\n"); cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY"); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index b77273c3a..5f106bce0 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -243,9 +243,9 @@ void cmFindPackageCommand::GenerateDocumentation() " /(cmake|CMake)/ (W)\n" " /*/ (W)\n" " /*/(cmake|CMake)/ (W)\n" - " /(share|lib)/cmake/*/ (U)\n" - " /(share|lib)/*/ (U)\n" - " /(share|lib)/*/(cmake|CMake)/ (U)\n" + " /(lib/|lib|share)/cmake/*/ (U)\n" + " /(lib/|lib|share)/*/ (U)\n" + " /(lib/|lib|share)/*/(cmake|CMake)/ (U)\n" "On systems supporting OS X Frameworks and Application Bundles " "the following directories are searched for frameworks or bundles " "containing a configuration file:\n" @@ -257,6 +257,7 @@ void cmFindPackageCommand::GenerateDocumentation() " /.app/Contents/Resources/CMake/ (A)\n" "In all cases the is treated as case-insensitive and corresponds " "to any of the names specified ( or names given by NAMES). " + "Paths with lib/ are enabled if CMAKE_LIBRARY_ARCHITECTURE is set. " "If PATH_SUFFIXES is specified the suffixes are appended to each " "(W) or (U) directory entry one-by-one.\n" "This set of directories is intended to work in cooperation with " @@ -362,6 +363,13 @@ bool cmFindPackageCommand // Check for debug mode. this->DebugMode = this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE"); + // Lookup target architecture, if any. + if(const char* arch = + this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) + { + this->LibraryArchitecture = arch; + } + // Lookup whether lib64 paths should be used. if(this->Makefile->PlatformIs64Bit() && this->Makefile->GetCMakeInstance() @@ -2189,6 +2197,10 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) // Construct list of common install locations (lib and share). std::vector common; + if(!this->LibraryArchitecture.empty()) + { + common.push_back("lib/"+this->LibraryArchitecture); + } if(this->UseLib64Paths) { common.push_back("lib64"); @@ -2196,7 +2208,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) common.push_back("lib"); common.push_back("share"); - // PREFIX/(share|lib)/cmake/(Foo|foo|FOO).*/ + // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/ { cmFindPackageFileList lister(this); lister @@ -2210,7 +2222,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) } } - // PREFIX/(share|lib)/(Foo|foo|FOO).*/ + // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/ { cmFindPackageFileList lister(this); lister @@ -2223,7 +2235,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) } } - // PREFIX/(share|lib)/(Foo|foo|FOO).*/(cmake|CMake)/ + // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/ { cmFindPackageFileList lister(this); lister diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 4229d375d..2b2e1dace 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -141,6 +141,7 @@ private: bool DebugMode; bool UseLib64Paths; bool PolicyScope; + std::string LibraryArchitecture; std::vector Names; std::vector Configs; std::set IgnoredPaths; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 83b651b71..846d187cb 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -45,6 +45,8 @@ void cmFindPathCommand::GenerateDocumentation() "SEARCH_XXX", "file in a directory"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "include"); + cmSystemTools::ReplaceString(this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", ""); cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"); diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 71cfdcbbe..7c56ad7ce 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -41,6 +41,8 @@ void cmFindProgramCommand::GenerateDocumentation() "SEARCH_XXX", "program"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "[s]bin"); + cmSystemTools::ReplaceString(this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", ""); cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM");