diff options
author | Brad King <brad.king@kitware.com> | 2012-12-05 13:46:04 -0500 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2012-12-11 15:15:52 -0500 |
commit | cc676c3a08019b17433931a9287d9cd8b0ccf2f2 (patch) | |
tree | 8dd39816b0c86d71ae2a3dadd384c740bd1da730 | |
parent | 2dd67c7ea095957d557d2934a67baacdf8a82d7b (diff) | |
download | cmake-cc676c3a08019b17433931a9287d9cd8b0ccf2f2.tar.gz |
OS X: Detect implicit linker framework search paths
Previously we hard-coded a list of implicit framework directories but
did not account for CMAKE_OSX_SYSROOT or for changes to the list across
OS X versions. Instead we should automatically detect the framework
directories for the active toolchain.
The parent commit added the "-Wl,-v" option to ask "ld" to print its
implicit directories. It displays a block such as:
Framework search paths:
/...
Parse this block to extract the list of framework directories.
Detection may fail on toolchains that do not list their framework
directories, such as older OS X linkers. Always treat the paths
<sdk>/Library/Frameworks
<sdk>/System/Library/Frameworks
<sdk>/Network/Library/Frameworks # Older OS X only
/System/Library/Frameworks
as implicit. Note that /System/Library/Frameworks should always be
considered implicit so that frameworks CMake finds there will not
override the SDK copies.
-rw-r--r-- | Modules/CMakeCCompiler.cmake.in | 1 | ||||
-rw-r--r-- | Modules/CMakeCXXCompiler.cmake.in | 1 | ||||
-rw-r--r-- | Modules/CMakeDetermineCompilerABI.cmake | 4 | ||||
-rw-r--r-- | Modules/CMakeFortranCompiler.cmake.in | 1 | ||||
-rw-r--r-- | Modules/CMakeParseImplicitLinkInfo.cmake | 40 | ||||
-rw-r--r-- | Modules/Platform/Darwin.cmake | 18 | ||||
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 29 | ||||
-rw-r--r-- | Source/cmDocumentVariables.cxx | 9 | ||||
-rw-r--r-- | Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in | 11 | ||||
-rw-r--r-- | Tests/SystemInformation/SystemInformation.in | 2 |
10 files changed, 94 insertions, 22 deletions
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index d74dcdceec..c41adc956b 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -50,6 +50,7 @@ endif() set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 8c5d84e6cb..9287b81945 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -51,6 +51,7 @@ endif() set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index cb94aa6559..25d6bbea77 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -72,8 +72,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # Parse implicit linker information for this language, if available. set(implicit_dirs "") set(implicit_libs "") + set(implicit_fwks "") if(CMAKE_${lang}_VERBOSE_FLAG) - CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log + CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Parsed ${lang} implicit link information from above output:\n${log}\n\n") @@ -111,6 +112,7 @@ 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) + set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE) # Detect library architecture directory name. if(CMAKE_LIBRARY_ARCHITECTURE_REGEX) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 55f8277735..d193881d96 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -52,3 +52,4 @@ endif() 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_FRAMEWORK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 54e8127489..234fb7fa15 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -16,9 +16,10 @@ # This is used internally by CMake and should not be included by user # code. -function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) +function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj_regex) set(implicit_libs_tmp "") set(implicit_dirs_tmp) + set(implicit_fwks_tmp) set(log "") # Parse implicit linker arguments. @@ -113,6 +114,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) set(log "${log} Library search paths: [${implicit_dirs_match}]\n") list(APPEND implicit_dirs_tmp ${implicit_dirs_match}) endif() + if("${output_lines}" MATCHES ";Framework search paths:((;\t[^;]+)+)") + string(REPLACE ";\t" ";" implicit_fwks_match "${CMAKE_MATCH_1}") + set(log "${log} Framework search paths: [${implicit_fwks_match}]\n") + list(APPEND implicit_fwks_tmp ${implicit_fwks_match}) + endif() # Cleanup list of libraries and flags. # We remove items that are not language-specific. @@ -125,27 +131,33 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() - # Cleanup list of library directories. - set(implicit_dirs "") - foreach(d IN LISTS implicit_dirs_tmp) - get_filename_component(dir "${d}" ABSOLUTE) - string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) - if(NOT pos LESS 0) - set(msg ", skipping non-system directory") - else() - set(msg "") - list(APPEND implicit_dirs "${dir}") - endif() - set(log "${log} collapse library dir [${d}] ==> [${dir}]${msg}\n") + # Cleanup list of library and framework directories. + set(desc_dirs "library") + set(desc_fwks "framework") + foreach(t dirs fwks) + set(implicit_${t} "") + foreach(d IN LISTS implicit_${t}_tmp) + get_filename_component(dir "${d}" ABSOLUTE) + string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) + if(NOT pos LESS 0) + set(msg ", skipping non-system directory") + else() + set(msg "") + list(APPEND implicit_${t} "${dir}") + endif() + set(log "${log} collapse ${desc_${t}} dir [${d}] ==> [${dir}]${msg}\n") + endforeach() + list(REMOVE_DUPLICATES implicit_${t}) endforeach() - list(REMOVE_DUPLICATES implicit_dirs) # Log results. set(log "${log} implicit libs: [${implicit_libs}]\n") set(log "${log} implicit dirs: [${implicit_dirs}]\n") + set(log "${log} implicit fwks: [${implicit_fwks}]\n") # Return results. set(${lib_var} "${implicit_libs}" PARENT_SCOPE) set(${dir_var} "${implicit_dirs}" PARENT_SCOPE) + set(${fwk_var} "${implicit_fwks}" PARENT_SCOPE) set(${log_var} "${log}" PARENT_SCOPE) endfunction() diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index ed0b8af3f4..2e6b71e369 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -256,6 +256,24 @@ set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK if(NOT DEFINED CMAKE_FIND_FRAMEWORK) set(CMAKE_FIND_FRAMEWORK FIRST) endif() + +# Older OS X linkers do not report their framework search path +# with -v but "man ld" documents the following locations. +set(CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Library/Frameworks + ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks + ) +if(_CMAKE_OSX_SYSROOT_PATH) + # Treat some paths as implicit so we do not override the SDK versions. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + /System/Library/Frameworks) +endif() +if("${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5") + # Older OS X tools had more implicit paths. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks) +endif() + # set up the default search directories for frameworks set(CMAKE_SYSTEM_FRAMEWORK_PATH ~/Library/Frameworks diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d8ffb5e838..19de903476 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1376,10 +1376,31 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item) //---------------------------------------------------------------------------- void cmComputeLinkInformation::ComputeFrameworkInfo() { - // Avoid adding system framework paths. See "man ld" on OS X. - this->FrameworkPathsEmmitted.insert("/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/Network/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/System/Library/Frameworks"); + // Avoid adding implicit framework paths. + std::vector<std::string> implicitDirVec; + + // Get platform-wide implicit directories. + if(const char* implicitLinks = this->Makefile->GetDefinition + ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) + { + cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec); + } + + // Get language-specific implicit directories. + std::string implicitDirVar = "CMAKE_"; + implicitDirVar += this->LinkLanguage; + implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"; + if(const char* implicitDirs = + this->Makefile->GetDefinition(implicitDirVar.c_str())) + { + cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec); + } + + for(std::vector<std::string>::const_iterator i = implicitDirVec.begin(); + i != implicitDirVec.end(); ++i) + { + this->FrameworkPathsEmmitted.insert(*i); + } // Regular expression to extract a framework path and name. this->SplitFramework.compile("(.*)/(.*)\\.framework$"); diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 55d70f8623..0a4170b711 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1625,6 +1625,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Variables for Languages"); cm->DefineProperty + ("CMAKE_<LANG>_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE, + "Implicit linker framework search path detected for language <LANG>.", + "These paths are implicit linker framework search directories for " + "the compiler's language. " + "CMake automatically detects these directories for each language and " + "reports the results in this variable.", false, + "Variables for Languages"); + + cm->DefineProperty ("CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES", cmProperty::VARIABLE, "Implicit link libraries and flags detected for language <LANG>.", "Compilers typically pass language runtime library names and " diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 02963042c1..31488c0ff4 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -120,6 +120,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_gcc_Wlv_libs "") set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gcc_Wlv) # gcc -arch i686 dummy.c -v @@ -146,6 +147,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_g++_Wlv_libs "stdc++") set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_g++_Wlv) # g++ -arch i686 dummy.cxx -v @@ -169,6 +171,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran") set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") +set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gfortran_Wlv) # gfortran dummy.f -v @@ -195,6 +198,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_ppc_gcc_Wlv_libs "") set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_gcc_Wlv) # gcc -arch ppc dummy.c -v @@ -221,6 +225,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_ppc_g++_Wlv_libs "stdc++") set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_g++_Wlv) # g++ -arch ppc dummy.cxx -v @@ -499,10 +504,10 @@ list(APPEND platforms msys_g77) # Test parsing for all above examples. foreach(p IN LISTS platforms) - cmake_parse_implicit_link_info("${${p}_text}" libs dirs log "${${p}_obj_regex}") + cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") - foreach(v libs dirs) - if(NOT "${${v}}" STREQUAL "${${p}_${v}}") + foreach(v libs dirs fwks) + if(DEFINED "${p}_${v}" AND NOT "${${v}}" STREQUAL "${${p}_${v}}") message(FATAL_ERROR "cmake_parse_implicit_link_info failed\n" "Expected '${p}' implicit ${v}\n" diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in index ecbc05408a..df3bf49d56 100644 --- a/Tests/SystemInformation/SystemInformation.in +++ b/Tests/SystemInformation/SystemInformation.in @@ -96,7 +96,9 @@ CMAKE_CXX_LINK_EXECUTABLE == "${CMAKE_CXX_LINK_EXECUTABLE}" // implicit link info CMAKE_C_IMPLICIT_LINK_LIBRARIES == "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}" CMAKE_C_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" CMAKE_CXX_IMPLICIT_LINK_LIBRARIES == "${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES}" CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" XCODE_VERSION == "${XCODE_VERSION}" |