Xcode: Add support for combined install on iOS
This patch solves the problem of installing both: Device and Simulator libraries on iOS. Before only one of them was installed. If the IOS_INSTALL_COMBINED property is set on a target, a special install hook will be activated which builds the corresponding target and combines both at the install location. The original patch was contributed by Ruslan Baratov, and polished by Gregor Jasny.
This commit is contained in:
parent
34f5ef564a
commit
565d080a9a
|
@ -191,6 +191,7 @@ Properties on Targets
|
|||
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG
|
||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
|
||||
/prop_tgt/IOS_INSTALL_COMBINED
|
||||
/prop_tgt/JOB_POOL_COMPILE
|
||||
/prop_tgt/JOB_POOL_LINK
|
||||
/prop_tgt/LABELS
|
||||
|
|
|
@ -257,6 +257,7 @@ Variables that Control the Build
|
|||
/variable/CMAKE_INSTALL_NAME_DIR
|
||||
/variable/CMAKE_INSTALL_RPATH
|
||||
/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH
|
||||
/variable/CMAKE_IOS_INSTALL_COMBINED
|
||||
/variable/CMAKE_LANG_COMPILER_LAUNCHER
|
||||
/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE
|
||||
/variable/CMAKE_LANG_VISIBILITY_PRESET
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
IOS_INSTALL_COMBINED
|
||||
--------------------
|
||||
|
||||
Build a combined (device and simulator) target when installing.
|
||||
|
||||
When this property is set to set to false (which is the default) then it will
|
||||
either be built with the device SDK or the simulator SDK depending on the SDK
|
||||
set. But if this property is set to true then the target will at install time
|
||||
also be built for the corresponding SDK and combined into one library.
|
||||
|
||||
This feature requires at least Xcode version 6.
|
|
@ -0,0 +1,7 @@
|
|||
ios-universal
|
||||
-------------
|
||||
|
||||
* When building for embedded Apple platforms like iOS CMake learned to build and
|
||||
install combined targets which contain both a device and a simulator build.
|
||||
This behavior can be enabled by setting the :prop_tgt:`IOS_INSTALL_COMBINED`
|
||||
target property.
|
|
@ -0,0 +1,8 @@
|
|||
CMAKE_IOS_INSTALL_COMBINED
|
||||
--------------------------
|
||||
|
||||
Default value for :prop_tgt:`IOS_INSTALL_COMBINED` of targets.
|
||||
|
||||
This variable is used to initialize the :prop_tgt:`IOS_INSTALL_COMBINED`
|
||||
property on all the targets. See that target property for additional
|
||||
information.
|
|
@ -0,0 +1,297 @@
|
|||
|
||||
#=============================================================================
|
||||
# Copyright 2014-2015 Ruslan Baratov, Gregor Jasny
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
# Function to print messages of this module
|
||||
function(_ios_install_combined_message)
|
||||
message("[iOS combined] " ${ARGN})
|
||||
endfunction()
|
||||
|
||||
# Get build settings for the current target/config/SDK by running
|
||||
# `xcodebuild -sdk ... -showBuildSettings` and parsing it's output
|
||||
function(_ios_install_combined_get_build_setting sdk variable resultvar)
|
||||
if("${sdk}" STREQUAL "")
|
||||
message(FATAL_ERROR "`sdk` is empty")
|
||||
endif()
|
||||
|
||||
if("${variable}" STREQUAL "")
|
||||
message(FATAL_ERROR "`variable` is empty")
|
||||
endif()
|
||||
|
||||
if("${resultvar}" STREQUAL "")
|
||||
message(FATAL_ERROR "`resultvar` is empty")
|
||||
endif()
|
||||
|
||||
set(
|
||||
cmd
|
||||
xcodebuild -showBuildSettings
|
||||
-sdk "${sdk}"
|
||||
-target "${CURRENT_TARGET}"
|
||||
-config "${CURRENT_CONFIG}"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${cmd}
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
)
|
||||
|
||||
if(NOT result EQUAL 0)
|
||||
message(FATAL_ERROR "Command failed (${result}): ${cmd}")
|
||||
endif()
|
||||
|
||||
if(NOT output MATCHES " ${variable} = ([^\n]*)")
|
||||
message(FATAL_ERROR "${variable} not found.")
|
||||
endif()
|
||||
|
||||
set("${resultvar}" "${CMAKE_MATCH_1}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Get architectures of given SDK (iphonesimulator/iphoneos)
|
||||
function(_ios_install_combined_get_valid_archs sdk resultvar)
|
||||
cmake_policy(SET CMP0007 NEW)
|
||||
|
||||
if("${resultvar}" STREQUAL "")
|
||||
message(FATAL_ERROR "`resultvar` is empty")
|
||||
endif()
|
||||
|
||||
_ios_install_combined_get_build_setting("${sdk}" "VALID_ARCHS" valid_archs)
|
||||
|
||||
separate_arguments(valid_archs)
|
||||
list(REMOVE_ITEM valid_archs "") # remove empty elements
|
||||
list(REMOVE_DUPLICATES valid_archs)
|
||||
|
||||
set("${resultvar}" "${valid_archs}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Final target can contain more architectures that specified by SDK. This
|
||||
# function will run 'lipo -info' and parse output. Result will be returned
|
||||
# as a CMake list.
|
||||
function(_ios_install_combined_get_real_archs filename resultvar)
|
||||
set(cmd "${_lipo_path}" -info "${filename}")
|
||||
execute_process(
|
||||
COMMAND ${cmd}
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
ERROR_VARIABLE output
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT result EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR "Command failed (${result}): ${cmd}\n\nOutput:\n${output}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT output MATCHES "(Architectures in the fat file: [^\n]+ are|Non-fat file: [^\n]+ is architecture): ([^\n]*)")
|
||||
message(FATAL_ERROR "Could not detect architecture from: ${output}")
|
||||
endif()
|
||||
|
||||
separate_arguments(CMAKE_MATCH_2)
|
||||
set(${resultvar} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Run build command for the given SDK
|
||||
function(_ios_install_combined_build sdk)
|
||||
if("${sdk}" STREQUAL "")
|
||||
message(FATAL_ERROR "`sdk` is empty")
|
||||
endif()
|
||||
|
||||
_ios_install_combined_message("Build `${CURRENT_TARGET}` for `${sdk}`")
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}"
|
||||
--build
|
||||
.
|
||||
--target "${CURRENT_TARGET}"
|
||||
--config ${CURRENT_CONFIG}
|
||||
--
|
||||
-sdk "${sdk}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
|
||||
if(NOT result EQUAL 0)
|
||||
message(FATAL_ERROR "Build failed")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Remove given architecture from file. This step needed only in rare cases
|
||||
# when target was built in "unusual" way. Emit warning message.
|
||||
function(_ios_install_combined_remove_arch lib arch)
|
||||
_ios_install_combined_message(
|
||||
"Warning! Unexpected architecture `${arch}` detected and will be removed "
|
||||
"from file `${lib}`")
|
||||
set(cmd "${_lipo_path}" -remove ${arch} -output ${lib} ${lib})
|
||||
execute_process(
|
||||
COMMAND ${cmd}
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
ERROR_VARIABLE output
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT result EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR "Command failed (${result}): ${cmd}\n\nOutput:\n${output}"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Check that 'lib' contains only 'archs' architectures (remove others).
|
||||
function(_ios_install_combined_keep_archs lib archs)
|
||||
_ios_install_combined_get_real_archs("${lib}" real_archs)
|
||||
set(archs_to_remove ${real_archs})
|
||||
list(REMOVE_ITEM archs_to_remove ${archs})
|
||||
foreach(x ${archs_to_remove})
|
||||
_ios_install_combined_remove_arch("${lib}" "${x}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(_ios_install_combined_detect_sdks this_sdk_var corr_sdk_var)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
|
||||
set(this_sdk "$ENV{PLATFORM_NAME}")
|
||||
if("${this_sdk}" STREQUAL "")
|
||||
message(FATAL_ERROR "Environment variable PLATFORM_NAME is empty")
|
||||
endif()
|
||||
|
||||
set(all_platforms "$ENV{SUPPORTED_PLATFORMS}")
|
||||
if("${all_platforms}" STREQUAL "")
|
||||
message(FATAL_ERROR "Environment variable SUPPORTED_PLATFORMS is empty")
|
||||
endif()
|
||||
|
||||
separate_arguments(all_platforms)
|
||||
if(NOT this_sdk IN_LIST all_platforms)
|
||||
message(FATAL_ERROR "`${this_sdk}` not found in `${all_platforms}`")
|
||||
endif()
|
||||
|
||||
list(REMOVE_ITEM all_platforms "" "${this_sdk}")
|
||||
list(LENGTH all_platforms all_platforms_length)
|
||||
if(NOT all_platforms_length EQUAL 1)
|
||||
message(FATAL_ERROR "Expected one element: ${all_platforms}")
|
||||
endif()
|
||||
|
||||
set(${this_sdk_var} "${this_sdk}" PARENT_SCOPE)
|
||||
set(${corr_sdk_var} "${all_platforms}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Create combined binary for the given target.
|
||||
#
|
||||
# Preconditions:
|
||||
# * Target already installed at ${destination}
|
||||
# for the ${PLATFORM_NAME} platform
|
||||
#
|
||||
# This function will:
|
||||
# * Run build for the lacking platform, i.e. opposite to the ${PLATFORM_NAME}
|
||||
# * Fuse both libraries by running lipo
|
||||
function(ios_install_combined target destination)
|
||||
if("${target}" STREQUAL "")
|
||||
message(FATAL_ERROR "`target` is empty")
|
||||
endif()
|
||||
|
||||
if("${destination}" STREQUAL "")
|
||||
message(FATAL_ERROR "`destination` is empty")
|
||||
endif()
|
||||
|
||||
if(NOT IS_ABSOLUTE "${destination}")
|
||||
message(FATAL_ERROR "`destination` is not absolute: ${destination}")
|
||||
endif()
|
||||
|
||||
if(IS_DIRECTORY "${destination}" OR IS_SYMLINK "${destination}")
|
||||
message(FATAL_ERROR "`destination` is no regular file: ${destination}")
|
||||
endif()
|
||||
|
||||
if("${CMAKE_BINARY_DIR}" STREQUAL "")
|
||||
message(FATAL_ERROR "`CMAKE_BINARY_DIR` is empty")
|
||||
endif()
|
||||
|
||||
if(NOT IS_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
message(FATAL_ERROR "Is not a directory: ${CMAKE_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
if("${CMAKE_INSTALL_CONFIG_NAME}" STREQUAL "")
|
||||
message(FATAL_ERROR "CMAKE_INSTALL_CONFIG_NAME is empty")
|
||||
endif()
|
||||
|
||||
set(cmd xcrun -f lipo)
|
||||
execute_process(
|
||||
COMMAND ${cmd}
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
ERROR_VARIABLE output
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT result EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR "Command failed (${result}): ${cmd}\n\nOutput:\n${output}"
|
||||
)
|
||||
endif()
|
||||
set(_lipo_path ${output})
|
||||
|
||||
set(CURRENT_CONFIG "${CMAKE_INSTALL_CONFIG_NAME}")
|
||||
set(CURRENT_TARGET "${target}")
|
||||
|
||||
_ios_install_combined_message("Target: ${CURRENT_TARGET}")
|
||||
_ios_install_combined_message("Config: ${CURRENT_CONFIG}")
|
||||
_ios_install_combined_message("Destination: ${destination}")
|
||||
|
||||
# Get SDKs
|
||||
_ios_install_combined_detect_sdks(this_sdk corr_sdk)
|
||||
|
||||
# Get architectures of the target
|
||||
_ios_install_combined_get_valid_archs("${corr_sdk}" corr_valid_archs)
|
||||
_ios_install_combined_get_valid_archs("${this_sdk}" this_valid_archs)
|
||||
|
||||
# Return if there are no valid architectures for the SDK.
|
||||
# (note that library already installed)
|
||||
if("${corr_valid_archs}" STREQUAL "")
|
||||
_ios_install_combined_message(
|
||||
"No architectures detected for `${corr_sdk}` (skip)"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Trigger build of corresponding target
|
||||
_ios_install_combined_build("${corr_sdk}")
|
||||
|
||||
# Get location of the library in build directory
|
||||
_ios_install_combined_get_build_setting(
|
||||
"${corr_sdk}" "CONFIGURATION_BUILD_DIR" corr_build_dir)
|
||||
_ios_install_combined_get_build_setting(
|
||||
"${corr_sdk}" "EXECUTABLE_PATH" corr_executable_path)
|
||||
set(corr "${corr_build_dir}/${corr_executable_path}")
|
||||
|
||||
_ios_install_combined_keep_archs("${corr}" "${corr_valid_archs}")
|
||||
_ios_install_combined_keep_archs("${destination}" "${this_valid_archs}")
|
||||
|
||||
_ios_install_combined_message("Current: ${destination}")
|
||||
_ios_install_combined_message("Corresponding: ${corr}")
|
||||
|
||||
set(cmd "${_lipo_path}" -create ${corr} ${destination} -output ${destination})
|
||||
|
||||
execute_process(
|
||||
COMMAND ${cmd}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
|
||||
if(NOT result EQUAL 0)
|
||||
message(FATAL_ERROR "Command failed: ${cmd}")
|
||||
endif()
|
||||
|
||||
_ios_install_combined_message("Install done: ${destination}")
|
||||
endfunction()
|
|
@ -531,6 +531,7 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
|
|||
{
|
||||
this->AddInstallNamePatchRule(os, indent, config, file);
|
||||
this->AddChrpathPatchRule(os, indent, config, file);
|
||||
this->AddUniversalInstallRule(os, indent, file);
|
||||
this->AddRanlibRule(os, indent, file);
|
||||
this->AddStripRule(os, indent, file);
|
||||
}
|
||||
|
@ -867,3 +868,46 @@ cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
|
|||
os << indent << "execute_process(COMMAND \""
|
||||
<< ranlib << "\" \"" << toDestDirPath << "\")\n";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmInstallTargetGenerator
|
||||
::AddUniversalInstallRule(std::ostream& os,
|
||||
Indent const& indent,
|
||||
const std::string& toDestDirPath)
|
||||
{
|
||||
cmMakefile const* mf = this->Target->Target->GetMakefile();
|
||||
|
||||
if(!mf->PlatformIsAppleIos() || !mf->IsOn("XCODE"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char* xcodeVersion = mf->GetDefinition("XCODE_VERSION");
|
||||
if(!xcodeVersion || cmSystemTools::VersionCompareGreater("6", xcodeVersion))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(this->Target->GetType())
|
||||
{
|
||||
case cmState::EXECUTABLE:
|
||||
case cmState::STATIC_LIBRARY:
|
||||
case cmState::SHARED_LIBRARY:
|
||||
case cmState::MODULE_LIBRARY:
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this->Target->Target->GetPropertyAsBool("IOS_INSTALL_COMBINED"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
os << indent << "include(CMakeIOSInstallCombined)\n";
|
||||
os << indent << "ios_install_combined("
|
||||
<< "\"" << this->Target->Target->GetName() << "\" "
|
||||
<< "\"" << toDestDirPath << "\")\n";
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ protected:
|
|||
const std::string& toDestDirPath);
|
||||
void AddRanlibRule(std::ostream& os, Indent const& indent,
|
||||
const std::string& toDestDirPath);
|
||||
void AddUniversalInstallRule(std::ostream& os, Indent const& indent,
|
||||
const std::string& toDestDirPath);
|
||||
|
||||
std::string TargetName;
|
||||
cmGeneratorTarget* Target;
|
||||
|
|
|
@ -132,6 +132,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("GNUtoMS", 0);
|
||||
this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
|
||||
this->SetPropertyDefault("IOS_INSTALL_COMBINED", 0);
|
||||
this->SetPropertyDefault("AUTOMOC", 0);
|
||||
this->SetPropertyDefault("AUTOUIC", 0);
|
||||
this->SetPropertyDefault("AUTORCC", 0);
|
||||
|
|
|
@ -94,3 +94,39 @@ if(NOT XCODE_VERSION VERSION_LESS 7)
|
|||
run_cmake(XcodeTbdStub)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
endif()
|
||||
|
||||
if(NOT XCODE_VERSION VERSION_LESS 6)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeIOSInstallCombined-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OPTIONS
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/_install"
|
||||
"-DCMAKE_IOS_INSTALL_COMBINED=YES")
|
||||
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(XcodeIOSInstallCombined)
|
||||
run_cmake_command(XcodeIOSInstallCombined-build ${CMAKE_COMMAND} --build .)
|
||||
run_cmake_command(XcodeIOSInstallCombined-install ${CMAKE_COMMAND} --build . --target install)
|
||||
|
||||
unset(RunCMake_TEST_BINARY_DIR)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeIOSInstallCombinedPrune-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OPTIONS
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/_install"
|
||||
"-DCMAKE_IOS_INSTALL_COMBINED=YES")
|
||||
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(XcodeIOSInstallCombinedPrune)
|
||||
run_cmake_command(XcodeIOSInstallCombinedPrune-build ${CMAKE_COMMAND} --build .)
|
||||
run_cmake_command(XcodeIOSInstallCombinedPrune-install ${CMAKE_COMMAND} --build . --target install)
|
||||
|
||||
unset(RunCMake_TEST_BINARY_DIR)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
function(verify_architectures file)
|
||||
execute_process(
|
||||
COMMAND xcrun otool -vf ${RunCMake_TEST_BINARY_DIR}/_install/${file}
|
||||
OUTPUT_VARIABLE otool_out
|
||||
ERROR_VARIABLE otool_err
|
||||
RESULT_VARIABLE otool_result)
|
||||
if(NOT otool_result EQUAL "0")
|
||||
message(SEND_ERROR "Could not retrieve fat headers: ${otool_err}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(REGEX MATCHALL "architecture [^ \n\t]+" architectures ${otool_out})
|
||||
string(REPLACE "architecture " "" actual "${architectures}")
|
||||
list(SORT actual)
|
||||
|
||||
set(expected arm64 armv7 i386 x86_64)
|
||||
|
||||
if(NOT actual STREQUAL expected)
|
||||
message(SEND_ERROR
|
||||
"The actual library contains the architectures:\n ${actual} \n"
|
||||
"which do not match expected ones:\n ${expected} \n"
|
||||
"otool output:\n${otool_out}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
verify_architectures(bin/foo_app.app/foo_app)
|
||||
verify_architectures(lib/libfoo_static.a)
|
||||
verify_architectures(lib/libfoo_shared.dylib)
|
||||
verify_architectures(lib/foo_bundle.bundle/foo_bundle)
|
||||
verify_architectures(lib/foo_framework.framework/foo_framework)
|
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.3)
|
||||
|
||||
project(IOSInstallCombined CXX)
|
||||
|
||||
set(CMAKE_OSX_SYSROOT iphoneos)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
|
||||
|
||||
set(CMAKE_OSX_ARCHITECTURES "armv7;arm64;i386;x86_64")
|
||||
|
||||
add_executable(foo_app MACOSX_BUNDLE main.cpp)
|
||||
install(TARGETS foo_app BUNDLE DESTINATION bin)
|
||||
|
||||
add_library(foo_static STATIC foo.cpp)
|
||||
install(TARGETS foo_static ARCHIVE DESTINATION lib)
|
||||
|
||||
add_library(foo_shared SHARED foo.cpp)
|
||||
install(TARGETS foo_shared LIBRARY DESTINATION lib)
|
||||
|
||||
add_library(foo_bundle MODULE foo.cpp)
|
||||
set_target_properties(foo_bundle PROPERTIES BUNDLE TRUE)
|
||||
install(TARGETS foo_bundle LIBRARY DESTINATION lib)
|
||||
|
||||
add_library(foo_framework SHARED foo.cpp)
|
||||
set_target_properties(foo_framework PROPERTIES FRAMEWORK TRUE)
|
||||
install(TARGETS foo_framework FRAMEWORK DESTINATION lib)
|
|
@ -0,0 +1,26 @@
|
|||
function(verify_architectures file)
|
||||
execute_process(
|
||||
COMMAND xcrun otool -vf ${RunCMake_TEST_BINARY_DIR}/_install/${file}
|
||||
OUTPUT_VARIABLE otool_out
|
||||
ERROR_VARIABLE otool_err
|
||||
RESULT_VARIABLE otool_result)
|
||||
if(NOT otool_result EQUAL "0")
|
||||
message(SEND_ERROR "Could not retrieve fat headers: ${otool_err}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(REGEX MATCHALL "architecture [^ \n\t]+" architectures ${otool_out})
|
||||
string(REPLACE "architecture " "" actual "${architectures}")
|
||||
list(SORT actual)
|
||||
|
||||
set(expected armv7 x86_64)
|
||||
|
||||
if(NOT actual STREQUAL expected)
|
||||
message(SEND_ERROR
|
||||
"The actual library contains the architectures:\n ${actual} \n"
|
||||
"which do not match expected ones:\n ${expected} \n"
|
||||
"otool output:\n${otool_out}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
verify_architectures(lib/libfoo.dylib)
|
|
@ -0,0 +1,2 @@
|
|||
.*Unexpected architecture `i386` detected.*
|
||||
.*Unexpected architecture `arm64` detected.*
|
|
@ -0,0 +1,36 @@
|
|||
cmake_minimum_required(VERSION 3.3)
|
||||
|
||||
project(XcodeIOSInstallCombinedPrune CXX)
|
||||
|
||||
set(CMAKE_OSX_SYSROOT iphoneos)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf")
|
||||
|
||||
add_library(foo SHARED foo.cpp)
|
||||
install(TARGETS foo DESTINATION lib)
|
||||
|
||||
add_library(baz SHARED foo.cpp)
|
||||
set_target_properties(
|
||||
foo baz
|
||||
PROPERTIES
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] armv7
|
||||
XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] armv7
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] x86_64
|
||||
XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] x86_64
|
||||
)
|
||||
|
||||
add_library(boo SHARED foo.cpp)
|
||||
set_target_properties(
|
||||
boo
|
||||
PROPERTIES
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] arm64
|
||||
XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] arm64
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] i386
|
||||
XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] i386
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET foo
|
||||
POST_BUILD
|
||||
COMMAND lipo -create $<TARGET_FILE:baz> $<TARGET_FILE:boo> -output $<TARGET_FILE:foo>
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
int main(int argc, const char * argv[]) {
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue