Merge topic 'fat-ios'

a9b41195d2 Handle multi-arch sysroots on Apple platforms
372c89ea38 Refactor -arch and -isysroot code usage
7a44e16d7f Refactor SDK name to path into a function
777d364913 Use xcrun instead of xcodebuild for resolving SDK path

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4125
This commit is contained in:
Brad King 2019-12-17 16:07:02 +00:00 committed by Kitware Robot
commit 671ed5b123
3 changed files with 134 additions and 30 deletions

View File

@ -122,7 +122,97 @@ endforeach()
set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_DEFAULT}" CACHE ${_CMAKE_OSX_SYSROOT_TYPE}
"The product will be built against the headers and libraries located inside the indicated SDK.")
# Transform the cached value to something we can use.
# Resolves the SDK name into a path
function(_apple_resolve_sdk_path sdk_name ret)
execute_process(
COMMAND xcrun -sdk ${sdk_name} --show-sdk-path
OUTPUT_VARIABLE _stdout
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _stderr
RESULT_VARIABLE _failed
)
set(${ret} "${_stdout}" PARENT_SCOPE)
endfunction()
# Handle multi-arch sysroots. Do this before CMAKE_OSX_SYSROOT is
# transformed into a path, so that we know the sysroot name.
function(_apple_resolve_multi_arch_sysroots)
if(CMAKE_APPLE_ARCH_SYSROOTS)
return() # Already cached
endif()
list(LENGTH CMAKE_OSX_ARCHITECTURES _num_archs)
if(NOT (_num_archs GREATER 1))
return() # Only apply to multi-arch
endif()
if(CMAKE_OSX_SYSROOT STREQUAL "macosx")
# macOS doesn't have a simulator sdk / sysroot, so there is no need to handle per-sdk arches.
return()
endif()
if(IS_DIRECTORY "${CMAKE_OSX_SYSROOT}")
if(NOT CMAKE_OSX_SYSROOT STREQUAL _CMAKE_OSX_SYSROOT_DEFAULT)
message(WARNING "Can not resolve multi-arch sysroots with CMAKE_OSX_SYSROOT set to path (${CMAKE_OSX_SYSROOT})")
endif()
return()
endif()
string(REPLACE "os" "simulator" _simulator_sdk ${CMAKE_OSX_SYSROOT})
set(_sdks "${CMAKE_OSX_SYSROOT};${_simulator_sdk}")
foreach(sdk ${_sdks})
_apple_resolve_sdk_path(${sdk} _sdk_path)
if(NOT IS_DIRECTORY "${_sdk_path}")
message(WARNING "Failed to resolve SDK path for '${sdk}'")
continue()
endif()
execute_process(
COMMAND plutil -extract SupportedTargets.${sdk}.Archs json ${_sdk_path}/SDKSettings.plist -o -
OUTPUT_VARIABLE _sdk_archs_json
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _stderr
RESULT_VARIABLE _failed
)
if(_failed)
# Failure to extract supported architectures for an SDK means that the installed SDK is old
# and does not provide such information (SDKs that come with Xcode >= 10.x started providing
# the information). In such a case, return early, and handle multi-arch builds the old way
# (no per-sdk arches).
return()
endif()
# Poor man's JSON decoding
string(REGEX REPLACE "[]\\[\"]" "" _sdk_archs ${_sdk_archs_json})
string(REPLACE "," ";" _sdk_archs ${_sdk_archs})
set(_sdk_archs_${sdk} ${_sdk_archs})
set(_sdk_path_${sdk} ${_sdk_path})
endforeach()
foreach(arch ${CMAKE_OSX_ARCHITECTURES})
set(_arch_sysroot "")
foreach(sdk ${_sdks})
list(FIND _sdk_archs_${sdk} ${arch} arch_index)
if(NOT arch_index EQUAL -1)
set(_arch_sysroot ${_sdk_path_${sdk}})
break()
endif()
endforeach()
if(_arch_sysroot)
list(APPEND _arch_sysroots ${_arch_sysroot})
else()
message(WARNING "No SDK found for architecture '${arch}'")
list(APPEND _arch_sysroots "") # Placeholder
endif()
endforeach()
set(CMAKE_APPLE_ARCH_SYSROOTS "${_arch_sysroots}" CACHE INTERNAL
"Architecture dependent sysroots, one per CMAKE_OSX_ARCHITECTURES")
endfunction()
_apple_resolve_multi_arch_sysroots()
# Transform CMAKE_OSX_SYSROOT to absolute path
set(_CMAKE_OSX_SYSROOT_PATH "")
if(CMAKE_OSX_SYSROOT)
if("x${CMAKE_OSX_SYSROOT}" MATCHES "/")
@ -134,16 +224,9 @@ if(CMAKE_OSX_SYSROOT)
endif()
set(_CMAKE_OSX_SYSROOT_PATH "${CMAKE_OSX_SYSROOT}")
else()
# Transform the sdk name into a path.
execute_process(
COMMAND xcodebuild -sdk ${CMAKE_OSX_SYSROOT} -version Path
OUTPUT_VARIABLE _stdout
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _stderr
RESULT_VARIABLE _failed
)
if(NOT _failed AND IS_DIRECTORY "${_stdout}")
set(_CMAKE_OSX_SYSROOT_PATH "${_stdout}")
_apple_resolve_sdk_path(${CMAKE_OSX_SYSROOT} _sdk_path)
if(IS_DIRECTORY "${_sdk_path}")
set(_CMAKE_OSX_SYSROOT_PATH "${_sdk_path}")
# For non-Xcode generators use the path.
if(NOT "${CMAKE_GENERATOR}" MATCHES "Xcode")
set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_PATH}")

View File

@ -51,6 +51,8 @@ static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET =
"CMAKE_OSX_DEPLOYMENT_TARGET";
static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT";
static std::string const kCMAKE_APPLE_ARCH_SYSROOTS =
"CMAKE_APPLE_ARCH_SYSROOTS";
static std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
"CMAKE_POSITION_INDEPENDENT_CODE";
static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
@ -723,6 +725,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_OSX_ARCHITECTURES);
vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET);
vars.insert(kCMAKE_OSX_SYSROOT);
vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS);
vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE);
vars.insert(kCMAKE_SYSROOT);
vars.insert(kCMAKE_SYSROOT_COMPILE);

View File

@ -1777,23 +1777,10 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
const std::string& lang,
const std::string& config)
{
// Only add macOS specific flags on Darwin platforms (macOS and iOS):
// Only add Apple specific flags on Apple platforms
if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) {
std::vector<std::string> archs;
target->GetAppleArchs(config, archs);
const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
if (sysroot && sysroot[0] == '/' && !sysroot[1]) {
sysroot = nullptr;
}
std::string sysrootFlagVar =
std::string("CMAKE_") + lang + "_SYSROOT_FLAG";
const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
const char* deploymentTarget =
this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
std::string deploymentTargetFlagVar =
std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG";
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (!archs.empty() && !lang.empty() &&
(lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) {
for (std::string const& arch : archs) {
@ -1802,13 +1789,44 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
}
}
if (sysrootFlag && *sysrootFlag && sysroot && *sysroot) {
const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
if (sysroot && sysroot[0] == '/' && !sysroot[1]) {
sysroot = nullptr;
}
std::string sysrootFlagVar =
std::string("CMAKE_") + lang + "_SYSROOT_FLAG";
const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
if (sysrootFlag && *sysrootFlag) {
std::vector<std::string> arch_sysroots;
if (const char* arch_sysroots_str =
this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) {
cmExpandList(std::string(arch_sysroots_str), arch_sysroots, true);
}
if (!arch_sysroots.empty()) {
assert(arch_sysroots.size() == archs.size());
for (size_t i = 0; i < archs.size(); ++i) {
if (arch_sysroots[i].empty()) {
continue;
}
flags += " -Xarch_" + archs[i] + " ";
// Combine sysroot flag and path to work with -Xarch
std::string arch_sysroot = sysrootFlag + arch_sysroots[i];
flags += this->ConvertToOutputFormat(arch_sysroot, SHELL);
}
} else if (sysroot && *sysroot) {
flags += " ";
flags += sysrootFlag;
flags += " ";
flags += this->ConvertToOutputFormat(sysroot, SHELL);
}
}
const char* deploymentTarget =
this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
std::string deploymentTargetFlagVar =
std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG";
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget &&
*deploymentTarget) {
flags += " ";