CMAKE_OSX_SYSROOT icw iOS fat binaries (iPhone + iPhoneSimulator)

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

CMAKE_OSX_SYSROOT icw iOS fat binaries (iPhone + iPhoneSimulator)

Erik van Nooijen

 With CMake it is possible to build for fat binaries for iOS without XCode. Fat binaries meaning containing all the architectures for iPhone and iPhoneSimulator.

However, when building frameworks, CMake builds it with the MacOSX layout, including 'Version' directory and symlinks etc. This is wrong when building for iOS.

The reason is that CMake determines bundle layout based on CMAKE_OSX_SYSROOT, but this cannot be set correctly in this situation, as it allows only one directory to be set, and we'd need two (iPhone and iPhoneSimulator). In short:

* not setting CMAKE_OSX_SYSROOT results in MacOSX framework/bundle layouts

* setting CMAKE_OSX_SYSROOT to a single sysroot gives error for the other architecture(s)

  ld: dynamic main executables must link with libSystem.dylib for architecture i386

* setting CMAKE_OSX_SYSROOT to multiple sysroots gives error for incorrect paths

  Ignoring CMAKE_OSX_SYSROOT value:

  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.1.sdk;/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.1.sdk

  because the directory does not exist.

 

Please find below an example CMakeLists.txt to test/verify this. The behaviour can be switched on and off with the MAKE_FAT variable.

 

What is the correct way to get fat binaries in the correct iOS layout in such a case?

 

cmake_minimum_required(VERSION 3.13)

project(iOSFatBinaries)

set(MAKE_FAT TRUE)

 

execute_process(COMMAND xcodebuild -version -sdk iphoneos        Path COMMAND perl -ne "chomp;print;exit;" OUTPUT_VARIABLE SDK_IPHONE_ROOT)

execute_process(COMMAND xcodebuild -version -sdk iphonesimulator Path COMMAND perl -ne "chomp;print;exit;" OUTPUT_VARIABLE SDK_IPHONE_SIMULATOR_ROOT)

 

# CMAKE_OSX_ARCHITECTURES

if(MAKE_FAT)

  set(CMAKE_OSX_ARCHITECTURES "armv7;armv7s;arm64;i386;x86_64" CACHE INTERNAL "Set supported OSX architectures")

else()

  set(CMAKE_OSX_ARCHITECTURES "armv7;armv7s;arm64" CACHE INTERNAL "Set supported OSX architectures")

endif()

 

# CMAKE_C_FLAGS and CMAKE_CXX_FLAGS

if(MAKE_FAT)

  set(SYSROOT_FLAGS "                 -arch armv7  -Xarch_armv7  \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch armv7s -Xarch_armv7s \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch arm64  -Xarch_arm64  \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch i386   -Xarch_i386   \"-isysroot${SDK_IPHONE_SIMULATOR_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch x86_64 -Xarch_x86_64 \"-isysroot${SDK_IPHONE_SIMULATOR_ROOT}\"")

  set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   ${SYSROOT_FLAGS}" CACHE INTERNAL "CMake C Compiler Flags")

  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYSROOT_FLAGS}" CACHE INTERNAL "CMake CXX Compiler Flags")

else()

  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -arch armv7 -arch armv7s -arch arm64")

  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch armv7 -arch armv7s -arch arm64")

endif()

 

# CMAKE_CXX_FLAGS

if(MAKE_FAT)

  set(CMAKE_OSX_SYSROOT "" CACHE INTERNAL "sysroot" FORCE)

else()

  set(CMAKE_OSX_SYSROOT ${SDK_IPHONE_ROOT} CACHE INTERNAL "sysroot" FORCE)

endif()

 

add_library(${PROJECT_NAME} SHARED

  lib.h

  lib.cpp

)

 

# Framework properties

set_target_properties(${PROJECT_NAME} PROPERTIES

  FRAMEWORK TRUE

  FORCE_IOS_BUNDLE_LAYOUT TRUE

  MACOSX_FRAMEWORK_IDENTIFIER ${PROJECT_NAME}

  MACOSX_FRAMEWORK_BUNDLE_VERSION 1.0

  MACOSX_FRAMEWORK_SHORT_VERSION_STRING 1.0

  MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in

  PUBLIC_HEADER lib.h

)


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: CMAKE_OSX_SYSROOT icw iOS fat binaries (iPhone + iPhoneSimulator)

Craig Scott-3
The IOS_INSTALL_COMBINED target property allows you to create fat binaries, but only at install time. To use this feature, set your CMAKE_OSX_SYSROOT to iphoneos and the simulator slice will be built and added to the fat binary for you automatically during the install step. If you require fat binaries at build time, that could be much more challenging.


On Mon, Nov 19, 2018 at 10:19 PM Erik van Nooijen <[hidden email]> wrote:

 With CMake it is possible to build for fat binaries for iOS without XCode. Fat binaries meaning containing all the architectures for iPhone and iPhoneSimulator.

However, when building frameworks, CMake builds it with the MacOSX layout, including 'Version' directory and symlinks etc. This is wrong when building for iOS.

The reason is that CMake determines bundle layout based on CMAKE_OSX_SYSROOT, but this cannot be set correctly in this situation, as it allows only one directory to be set, and we'd need two (iPhone and iPhoneSimulator). In short:

* not setting CMAKE_OSX_SYSROOT results in MacOSX framework/bundle layouts

* setting CMAKE_OSX_SYSROOT to a single sysroot gives error for the other architecture(s)

  ld: dynamic main executables must link with libSystem.dylib for architecture i386

* setting CMAKE_OSX_SYSROOT to multiple sysroots gives error for incorrect paths

  Ignoring CMAKE_OSX_SYSROOT value:

  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.1.sdk;/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.1.sdk

  because the directory does not exist.

 

Please find below an example CMakeLists.txt to test/verify this. The behaviour can be switched on and off with the MAKE_FAT variable.

 

What is the correct way to get fat binaries in the correct iOS layout in such a case?

 

cmake_minimum_required(VERSION 3.13)

project(iOSFatBinaries)

set(MAKE_FAT TRUE)

 

execute_process(COMMAND xcodebuild -version -sdk iphoneos        Path COMMAND perl -ne "chomp;print;exit;" OUTPUT_VARIABLE SDK_IPHONE_ROOT)

execute_process(COMMAND xcodebuild -version -sdk iphonesimulator Path COMMAND perl -ne "chomp;print;exit;" OUTPUT_VARIABLE SDK_IPHONE_SIMULATOR_ROOT)

 

# CMAKE_OSX_ARCHITECTURES

if(MAKE_FAT)

  set(CMAKE_OSX_ARCHITECTURES "armv7;armv7s;arm64;i386;x86_64" CACHE INTERNAL "Set supported OSX architectures")

else()

  set(CMAKE_OSX_ARCHITECTURES "armv7;armv7s;arm64" CACHE INTERNAL "Set supported OSX architectures")

endif()

 

# CMAKE_C_FLAGS and CMAKE_CXX_FLAGS

if(MAKE_FAT)

  set(SYSROOT_FLAGS "                 -arch armv7  -Xarch_armv7  \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch armv7s -Xarch_armv7s \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch arm64  -Xarch_arm64  \"-isysroot${SDK_IPHONE_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch i386   -Xarch_i386   \"-isysroot${SDK_IPHONE_SIMULATOR_ROOT}\"")

  set(SYSROOT_FLAGS "${SYSROOT_FLAGS} -arch x86_64 -Xarch_x86_64 \"-isysroot${SDK_IPHONE_SIMULATOR_ROOT}\"")

  set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   ${SYSROOT_FLAGS}" CACHE INTERNAL "CMake C Compiler Flags")

  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYSROOT_FLAGS}" CACHE INTERNAL "CMake CXX Compiler Flags")

else()

  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -arch armv7 -arch armv7s -arch arm64")

  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch armv7 -arch armv7s -arch arm64")

endif()

 

# CMAKE_CXX_FLAGS

if(MAKE_FAT)

  set(CMAKE_OSX_SYSROOT "" CACHE INTERNAL "sysroot" FORCE)

else()

  set(CMAKE_OSX_SYSROOT ${SDK_IPHONE_ROOT} CACHE INTERNAL "sysroot" FORCE)

endif()

 

add_library(${PROJECT_NAME} SHARED

  lib.h

  lib.cpp

)

 

# Framework properties

set_target_properties(${PROJECT_NAME} PROPERTIES

  FRAMEWORK TRUE

  FORCE_IOS_BUNDLE_LAYOUT TRUE

  MACOSX_FRAMEWORK_IDENTIFIER ${PROJECT_NAME}

  MACOSX_FRAMEWORK_BUNDLE_VERSION 1.0

  MACOSX_FRAMEWORK_SHORT_VERSION_STRING 1.0

  MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in

  PUBLIC_HEADER lib.h

)




--
Craig Scott
Melbourne, Australia


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake