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.
This commit is contained in:
parent
2dd67c7ea0
commit
cc676c3a08
|
@ -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@
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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@")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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$");
|
||||
|
|
|
@ -1624,6 +1624,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
|||
"reports the results in this variable.", false,
|
||||
"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>.",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}"
|
||||
|
|
Loading…
Reference in New Issue