summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2012-12-05 13:46:04 -0500
committerBrad King <brad.king@kitware.com>2012-12-11 15:15:52 -0500
commitcc676c3a08019b17433931a9287d9cd8b0ccf2f2 (patch)
tree8dd39816b0c86d71ae2a3dadd384c740bd1da730
parent2dd67c7ea095957d557d2934a67baacdf8a82d7b (diff)
downloadcmake-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.in1
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in1
-rw-r--r--Modules/CMakeDetermineCompilerABI.cmake4
-rw-r--r--Modules/CMakeFortranCompiler.cmake.in1
-rw-r--r--Modules/CMakeParseImplicitLinkInfo.cmake40
-rw-r--r--Modules/Platform/Darwin.cmake18
-rw-r--r--Source/cmComputeLinkInformation.cxx29
-rw-r--r--Source/cmDocumentVariables.cxx9
-rw-r--r--Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in11
-rw-r--r--Tests/SystemInformation/SystemInformation.in2
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}"