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 <arch> part of <prefix>/lib/<arch> from the implicit library
search path from each compiler to set CMAKE_<lang>_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 <prefix>/lib/<arch> whenever they would search <prefix>/lib.
This commit is contained in:
Brad King 2011-06-08 08:46:31 -04:00
parent 0f939ee164
commit b41ad3b399
12 changed files with 88 additions and 6 deletions

View File

@ -28,6 +28,7 @@ SET(CMAKE_C_LINKER_PREFERENCE 10)
# Save compiler ABI information. # Save compiler ABI information.
SET(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@") SET(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@")
SET(CMAKE_C_COMPILER_ABI "@CMAKE_C_COMPILER_ABI@") SET(CMAKE_C_COMPILER_ABI "@CMAKE_C_COMPILER_ABI@")
SET(CMAKE_C_LIBRARY_ARCHITECTURE "@CMAKE_C_LIBRARY_ARCHITECTURE@")
IF(CMAKE_C_SIZEOF_DATA_PTR) IF(CMAKE_C_SIZEOF_DATA_PTR)
SET(CMAKE_SIZEOF_VOID_P "${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}") SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
ENDIF(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@") SET(CMAKE_C_HAS_ISYSROOT "@CMAKE_C_HAS_ISYSROOT@")
@CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ @CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG_CODE@

View File

@ -29,6 +29,7 @@ SET(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
# Save compiler ABI information. # Save compiler ABI information.
SET(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@") SET(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@")
SET(CMAKE_CXX_COMPILER_ABI "@CMAKE_CXX_COMPILER_ABI@") SET(CMAKE_CXX_COMPILER_ABI "@CMAKE_CXX_COMPILER_ABI@")
SET(CMAKE_CXX_LIBRARY_ARCHITECTURE "@CMAKE_CXX_LIBRARY_ARCHITECTURE@")
IF(CMAKE_CXX_SIZEOF_DATA_PTR) IF(CMAKE_CXX_SIZEOF_DATA_PTR)
SET(CMAKE_SIZEOF_VOID_P "${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}") SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
ENDIF(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@") SET(CMAKE_CXX_HAS_ISYSROOT "@CMAKE_CXX_HAS_ISYSROOT@")
@CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ @CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@

View File

@ -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_LIBRARIES "${implicit_libs}" PARENT_SCOPE)
SET(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" 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) ELSE(CMAKE_DETERMINE_${lang}_ABI_COMPILED)
MESSAGE(STATUS "Detecting ${lang} compiler ABI info - failed") MESSAGE(STATUS "Detecting ${lang} compiler ABI info - failed")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log

View File

@ -34,6 +34,7 @@ ENDIF(UNIX)
# Save compiler ABI information. # Save compiler ABI information.
SET(CMAKE_Fortran_SIZEOF_DATA_PTR "@CMAKE_Fortran_SIZEOF_DATA_PTR@") SET(CMAKE_Fortran_SIZEOF_DATA_PTR "@CMAKE_Fortran_SIZEOF_DATA_PTR@")
SET(CMAKE_Fortran_COMPILER_ABI "@CMAKE_Fortran_COMPILER_ABI@") 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) IF(CMAKE_Fortran_SIZEOF_DATA_PTR AND NOT CMAKE_SIZEOF_VOID_P)
SET(CMAKE_SIZEOF_VOID_P "${CMAKE_Fortran_SIZEOF_DATA_PTR}") 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}") SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_Fortran_COMPILER_ABI}")
ENDIF(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_LIBRARIES "@CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES@")
SET(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@") SET(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@")

View File

@ -45,6 +45,9 @@ ELSE(DEFINED CMAKE_INSTALL_SO_NO_EXE)
ENDIF(EXISTS "/etc/debian_version") ENDIF(EXISTS "/etc/debian_version")
ENDIF(DEFINED CMAKE_INSTALL_SO_NO_EXE) 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) INCLUDE(Platform/UnixPaths)
# Debian has lib64 paths only for compatibility so they should not be # Debian has lib64 paths only for compatibility so they should not be

View File

@ -822,6 +822,18 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"set to the output of uname -r. On other " "set to the output of uname -r. On other "
"systems this is set to major-minor version numbers.",false, "systems this is set to major-minor version numbers.",false,
"Variables That Describe the System"); "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_<lang>_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_<lang>_LIBRARY_ARCHITECTURE from the "
"implicit linker search path by matching the <arch> name.",false,
"Variables That Describe the System");
cm->DefineProperty cm->DefineProperty
("CMAKE_HOST_SYSTEM", cmProperty::VARIABLE, ("CMAKE_HOST_SYSTEM", cmProperty::VARIABLE,
@ -1359,6 +1371,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"language and reports the results in this variable.", false, "language and reports the results in this variable.", false,
"Variables for Languages"); "Variables for Languages");
cm->DefineProperty
("CMAKE_<LANG>_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE,
"Target architecture library directory name detected for <lang>.",
"If the <lang> compiler passes to the linker an architecture-specific "
"system library search directory such as <prefix>/lib/<arch> this "
"variable contains the <arch> name if/as detected by CMake.",false,
"Variables for Languages");
cm->DefineProperty cm->DefineProperty
("CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES", cmProperty::VARIABLE, ("CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES", cmProperty::VARIABLE,
"True if CMAKE_<LANG>_LINKER_PREFERENCE propagates across targets.", "True if CMAKE_<LANG>_LINKER_PREFERENCE propagates across targets.",

View File

@ -72,12 +72,14 @@ void cmFindBase::GenerateDocumentation()
"1. Search paths specified in cmake-specific cache variables. " "1. Search paths specified in cmake-specific cache variables. "
"These are intended to be used on the command line with a -DVAR=value. " "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" "This can be skipped if NO_CMAKE_PATH is passed.\n"
"XXX_EXTRA_PREFIX_ENTRY"
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
" CMAKE_XXX_PATH\n" " CMAKE_XXX_PATH\n"
" CMAKE_XXX_MAC_PATH\n" " CMAKE_XXX_MAC_PATH\n"
"2. Search paths specified in cmake-specific environment variables. " "2. Search paths specified in cmake-specific environment variables. "
"These are intended to be set in the user's shell configuration. " "These are intended to be set in the user's shell configuration. "
"This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n" "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n"
"XXX_EXTRA_PREFIX_ENTRY"
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
" CMAKE_XXX_PATH\n" " CMAKE_XXX_PATH\n"
" CMAKE_XXX_MAC_PATH\n" " CMAKE_XXX_MAC_PATH\n"
@ -92,6 +94,7 @@ void cmFindBase::GenerateDocumentation()
"5. Search cmake variables defined in the Platform files " "5. Search cmake variables defined in the Platform files "
"for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
"is passed.\n" "is passed.\n"
"XXX_EXTRA_PREFIX_ENTRY"
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n"
" CMAKE_SYSTEM_XXX_PATH\n" " CMAKE_SYSTEM_XXX_PATH\n"
" CMAKE_SYSTEM_XXX_MAC_PATH\n" " CMAKE_SYSTEM_XXX_MAC_PATH\n"
@ -346,6 +349,15 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
{ {
dir += "/"; 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; std::string add = dir + subdir;
if(add != "/") if(add != "/")
{ {

View File

@ -44,6 +44,10 @@ void cmFindLibraryCommand::GenerateDocumentation()
"SEARCH_XXX", "library"); "SEARCH_XXX", "library");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SUBDIR", "lib"); "XXX_SUBDIR", "lib");
cmSystemTools::ReplaceString(
this->GenericDocumentation,
"XXX_EXTRA_PREFIX_ENTRY",
" <prefix>/lib/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_XXX",
"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY"); "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY");

View File

@ -243,9 +243,9 @@ void cmFindPackageCommand::GenerateDocumentation()
" <prefix>/(cmake|CMake)/ (W)\n" " <prefix>/(cmake|CMake)/ (W)\n"
" <prefix>/<name>*/ (W)\n" " <prefix>/<name>*/ (W)\n"
" <prefix>/<name>*/(cmake|CMake)/ (W)\n" " <prefix>/<name>*/(cmake|CMake)/ (W)\n"
" <prefix>/(share|lib)/cmake/<name>*/ (U)\n" " <prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)\n"
" <prefix>/(share|lib)/<name>*/ (U)\n" " <prefix>/(lib/<arch>|lib|share)/<name>*/ (U)\n"
" <prefix>/(share|lib)/<name>*/(cmake|CMake)/ (U)\n" " <prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)\n"
"On systems supporting OS X Frameworks and Application Bundles " "On systems supporting OS X Frameworks and Application Bundles "
"the following directories are searched for frameworks or bundles " "the following directories are searched for frameworks or bundles "
"containing a configuration file:\n" "containing a configuration file:\n"
@ -257,6 +257,7 @@ void cmFindPackageCommand::GenerateDocumentation()
" <prefix>/<name>.app/Contents/Resources/CMake/ (A)\n" " <prefix>/<name>.app/Contents/Resources/CMake/ (A)\n"
"In all cases the <name> is treated as case-insensitive and corresponds " "In all cases the <name> is treated as case-insensitive and corresponds "
"to any of the names specified (<package> or names given by NAMES). " "to any of the names specified (<package> or names given by NAMES). "
"Paths with lib/<arch> are enabled if CMAKE_LIBRARY_ARCHITECTURE is set. "
"If PATH_SUFFIXES is specified the suffixes are appended to each " "If PATH_SUFFIXES is specified the suffixes are appended to each "
"(W) or (U) directory entry one-by-one.\n" "(W) or (U) directory entry one-by-one.\n"
"This set of directories is intended to work in cooperation with " "This set of directories is intended to work in cooperation with "
@ -362,6 +363,13 @@ bool cmFindPackageCommand
// Check for debug mode. // Check for debug mode.
this->DebugMode = this->Makefile->IsOn("CMAKE_FIND_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. // Lookup whether lib64 paths should be used.
if(this->Makefile->PlatformIs64Bit() && if(this->Makefile->PlatformIs64Bit() &&
this->Makefile->GetCMakeInstance() this->Makefile->GetCMakeInstance()
@ -2189,6 +2197,10 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
// Construct list of common install locations (lib and share). // Construct list of common install locations (lib and share).
std::vector<std::string> common; std::vector<std::string> common;
if(!this->LibraryArchitecture.empty())
{
common.push_back("lib/"+this->LibraryArchitecture);
}
if(this->UseLib64Paths) if(this->UseLib64Paths)
{ {
common.push_back("lib64"); common.push_back("lib64");
@ -2196,7 +2208,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
common.push_back("lib"); common.push_back("lib");
common.push_back("share"); common.push_back("share");
// PREFIX/(share|lib)/cmake/(Foo|foo|FOO).*/ // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
{ {
cmFindPackageFileList lister(this); cmFindPackageFileList lister(this);
lister 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); cmFindPackageFileList lister(this);
lister 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); cmFindPackageFileList lister(this);
lister lister

View File

@ -141,6 +141,7 @@ private:
bool DebugMode; bool DebugMode;
bool UseLib64Paths; bool UseLib64Paths;
bool PolicyScope; bool PolicyScope;
std::string LibraryArchitecture;
std::vector<std::string> Names; std::vector<std::string> Names;
std::vector<std::string> Configs; std::vector<std::string> Configs;
std::set<std::string> IgnoredPaths; std::set<std::string> IgnoredPaths;

View File

@ -45,6 +45,8 @@ void cmFindPathCommand::GenerateDocumentation()
"SEARCH_XXX", "file in a directory"); "SEARCH_XXX", "file in a directory");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SUBDIR", "include"); "XXX_SUBDIR", "include");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_EXTRA_PREFIX_ENTRY", "");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_XXX",
"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"); "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");

View File

@ -41,6 +41,8 @@ void cmFindProgramCommand::GenerateDocumentation()
"SEARCH_XXX", "program"); "SEARCH_XXX", "program");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SUBDIR", "[s]bin"); "XXX_SUBDIR", "[s]bin");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_EXTRA_PREFIX_ENTRY", "");
cmSystemTools::ReplaceString(this->GenericDocumentation, cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_XXX",
"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM"); "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM");