Le 08.08.17 à 14:08, Raffi Enficiaud a écrit :
Hi CMake ML,

I am quite new to the topic of making toolchain files. However I need to
build a not so trivial application for iOS and I want to do it with
CMake, and if possible walk toward an official support of iOS in CMake.

I have looked a bit to the Android toolchains, and I have to say I found
those quite complicated as a first reading :)

The target application I am building uses Qt and Boost.

So far, I have managed to have an IOS toolchain file that is generating
a looking good XCode project, that I can compile properly (up until
signing).

[snip]

Hi there,

Following the thread, I would like to suggest a toolchain file for iOS, attached to this post.

I used this to compile a not too small project using Qt, Boost, LSL and some other fancy dependencies, and the project runs at least on the simulator (waiting for a real device).

The way it works:

- we need different build trees for the simulator and for a real device (not same arch nor base SDK). Changing this is way too difficult and the workaround of having different build trees, although not very "elegant", just work

- for the simulator
cmake -G Xcode \
  -DCMAKE_TOOLCHAIN_FILE=ios_toolchain.cmake \
  -DIOS_PLATFORM=SIMULATOR \
  ../some-path

- for a real device
cmake -G Xcode \
  -DCMAKE_TOOLCHAIN_FILE=ios_toolchain.cmake \
  -DIOS_PLATFORM=OS \
  ../some-path

- for the device, we need a real certificate for signing that can be set directly from within XCode or by setting `XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=YES` and the companion variables to the appropriate values


Next steps:
* I can set up a machine for running the tests as I am doing for the Matlab package. Those tests would be for the moment compilation tests. I would be happy to discuss on how to do real "runtime" tests. * I can proceed further with the documentation of course if people are happy with this toolchain file * I can add other SDKs like watchOS and such, but before proceeding further I would prefer to have a feature complete implementation for iOS device+simulator (I believe this is the most demanded). * I can check how to tweak CROSSCOMPILING_EMULATOR to run things on an emulator in case we are on the simulator. I believe add_test should be disabled when compiling for a real device * I would like to know if there is any direction in indicating the bundles structures, as those are different for iOS and macOS. Right now I am using a switch like this

if(IOS)
  set(OSX_BUNDLE_RELATIVE_PATH ".")
else()
  set(OSX_BUNDLE_RELATIVE_PATH "../..")
endif()

add_custom_command(
TARGET myproj
POST_BUILD
COMMAND ${CMAKE_COMMAND} -DAPPFOLDER=$<TARGET_FILE_DIR:myproj>/${OSX_BUNDLE_RELATIVE_PATH} "-DSOMEPARAMS=${BOOST_LIB_PATH}"
-P ${CMAKE_SOURCE_DIR}/cmake/osx_bundle.cmake
)

to get the path to the root folder of the bundle. I do not know if there is anything like this in CMake already (the BundleUtilities I believe has relative paths written in hard).

Thanks!
Raffi
# cmake -G Xcode \
#  -DCMAKE_TOOLCHAIN_FILE=./ios_toolchain.cmake \
#  -DCMAKE_PREFIX_PATH=~/Qt5.9.1/5.9.1/ios/ \
#  -DBOOST_ROOT=~/Code/SoftwareWorkshop/sw_thirdparties/osx/boost_1_63_0
#  -DBoost_COMPILER=-xgcc42 ../source

# * `IOS`: indicates that the build is being performed for iOS (generic device 
or simulator)
# * `IOS_PLATFORM`: indicates the platform to compile for. This can be the 
genuine operating system (`OS`) or the simulator (`SIMULATOR`)
# * `IOS_ARCH`: the architecture to compile. The default is dependant on the 
`IOS_PLATFORM`:
#    * `armv7;arm64` for the `IOS`
#    * `i386;x86_64` for the `SIMULATOR`
#
# Other variables
#
# * `CMAKE_IOS_SDK_ROOT`: indicates the name of an SDK to choose, defaults to 
the "most recent" SDK
#
# By default code signing is `OFF`, but should be activated per target in order 
to have the compilation
# possible for iOS device (Xcode defaults to some ad-hox signing otherwise). 
This can be done
# through the target properties `XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED`

# TODO
# - documentation
# - detects automatically sdks and target systems from XCode, and lists the 
sysroots
# - this is for IOS only, not watchOS or anything else
# - indicate the bundle structure for this target system (different than from 
macOS)
# - indicate how to run tests maybe through `CROSSCOMPILING_EMULATOR`
# - fix the tests
# - find other libraries that clang/clang++ ?


# some relevant doc/resources
# 
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-SW6

# for running simulator
# 
https://stackoverflow.com/questions/26031601/xcode-6-launch-simulator-from-command-line
# can be consumed with
# https://cmake.org/cmake/help/v3.8/prop_tgt/CROSSCOMPILING_EMULATOR.html

# Raffi: automated code signing
# public.kitware.com/pipermail/cmake/2016.../064602.html
# set_target_properties(app PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY  
"PROPER IDENTIFIER")

# listing all signing identities
# security find-identity -v -p codesigning

# signing a binary
# codesign -s my-signing-identity -f ./md5

# signing code manually
# 
https://developer.apple.com/library/content/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html

# examining a .a
# lipo -info boost_1_63_0_ios/lib/libboost_filesystem.a


set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_VERSION 1)
set(UNIX True)
set(APPLE True)
set(IOS True)

#
if(NOT DEFINED IOS_PLATFORM)
  set(IOS_PLATFORM "OS")
endif()

# left as an example on how to list things from command line utilities
# to be integrated
if(FALSE)
  execute_process(
    COMMAND xcodebuild -sdk -version
    RESULT_VARIABLE
      XCODE_SYSROOT_LISTING_RES
    OUTPUT_VARIABLE
      XCODE_SYSROOT_LISTING
    ERROR_VARIABLE
      XCODE_SYSROOT_LISTING_ERROR
  )

  if(NOT "${XCODE_SYSROOT_LISTING_RES}" STREQUAL "0")
    message(FATAL_ERROR "Cannot list SDKs from xcodebuild. Please make sure 
XCode is properly installed")
  endif()

  string(REGEX MATCHALL "Path:[ ]*([a-zA-Z0-9/\\. ]+)"
         VAR_MATCH "${XCODE_SYSROOT_LISTING}"
        )
  list(REMOVE_DUPLICATES VAR_MATCH)
  message("${VAR_MATCH}")
endif()


# for each SDK, showing the version:
# xcrun --sdk iphoneos --show-sdk-version

#
# Detect the current XCode
#
if(NOT DEFINED XCODE_ROOT_PATH)
  execute_process(
    COMMAND xcode-select -print-path
    RESULT_VARIABLE
      XCODE_COMPILER_PRINT_PATH_RES
    OUTPUT_VARIABLE
      XCODE_COMPILER_PRINT_PATH
    ERROR_VARIABLE
      XCODE_COMPILER_PRINT_PATH_ERROR
  )
  # Raffi : check errors
  set(_suffix_app ".app")
  string(FIND "${XCODE_COMPILER_PRINT_PATH}" "${_suffix_app}/" VAR_LOCATION_APP)
  string(SUBSTRING "${XCODE_COMPILER_PRINT_PATH}" 0 "${VAR_LOCATION_APP}" 
XCODE_ROOT_PATH)
  set(XCODE_ROOT_PATH "${XCODE_ROOT_PATH}${_suffix_app}" CACHE STRING "XCode 
ROOT folder" FORCE)
endif()

#
# Check the platform selection and setup for developer root
if(IOS_PLATFORM STREQUAL "OS")
  set(IOS_PLATFORM_LOCATION "iPhoneOS.platform")
  set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") # This causes the installers 
to properly locate the output libraries
elseif(IOS_PLATFORM STREQUAL "SIMULATOR")
  set(IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
  set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
else()
  message(FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose 
OS or SIMULATOR")
endif()

# Indicate cross compilation: we suppose that we never perform compilation 
direclty
# on a device
set(CMAKE_CROSSCOMPILING TRUE)

#
# looking for the compilers
# Check how to do it consistently with XCODE_ROOT_PATH
if(NOT DEFINED XCODE_COMPILER_CLANG)
  execute_process(
    COMMAND xcodebuild -find-executable clang
    RESULT_VARIABLE
      XCODE_COMPILER_CLANG_RES
    OUTPUT_VARIABLE
      XCODE_COMPILER_CLANG
    ERROR_VARIABLE
      XCODE_COMPILER_CLANG_ERROR
  )
  if(NOT "${XCODE_COMPILER_CLANG_RES}" STREQUAL "0")
    message(FATAL_ERROR "IOSToolchain: 'clang' compiler cannot be found")
  endif()
  set(XCODE_COMPILER_CLANG "${XCODE_COMPILER_CLANG}" CACHE STRING "XCode clang 
compiler" FORCE)
endif()

if(NOT DEFINED XCODE_COMPILER_CLANGPP)
  execute_process(
    COMMAND xcodebuild -find-executable clang++
    RESULT_VARIABLE
      XCODE_COMPILER_CLANGPP_RES
    OUTPUT_VARIABLE
      XCODE_COMPILER_CLANGPP
    ERROR_VARIABLE
      XCODE_COMPILER_CLANGPP_ERROR
  )
  if(NOT "${XCODE_COMPILER_CLANGPP_RES}" STREQUAL "0")
    message(FATAL_ERROR "IOSToolchain: 'clang++' compiler cannot be found")
  endif()
  set(XCODE_COMPILER_CLANGPP "${XCODE_COMPILER_CLANGPP}" CACHE STRING "XCode 
clang++ compiler" FORCE)
endif()

set(CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment 
target for iOS" FORCE)
set(CMAKE_IOS_DEVELOPER_ROOT 
"${XCODE_ROOT_PATH}/Contents/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")

# Find and use the most recent iOS sdk unless specified manually with 
CMAKE_IOS_SDK_ROOT
if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
  file(GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
  if(_CMAKE_IOS_SDKS)
    list(SORT _CMAKE_IOS_SDKS)
    list(REVERSE _CMAKE_IOS_SDKS)
    list(GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
  else()
    message(FATAL_ERROR "No iOS SDK's found in default search path 
${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS 
SDK.")
  endif()
  message(STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
endif()

set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the 
selected iOS SDK")
# this variable is used all over the places in CMake, we override it with the
# iOS SDK root found
set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS 
support")

#
# set the architecture for iOS
#
if(NOT DEFINED IOS_ARCH)
  if (IOS_PLATFORM STREQUAL "OS")
    set(CMAKE_SYSTEM_PROCESSOR arm)
    set(IOS_ARCH armv7 arm64)
  elseif(IOS_PLATFORM STREQUAL "SIMULATOR")
    set(CMAKE_SYSTEM_PROCESSOR x86_64)
    set(IOS_ARCH i386 x86_64)
  endif()
endif()
set(CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for 
iOS")

# Set the find root to the iOS developer roots and to user defined paths
set(CMAKE_FIND_ROOT_PATH
  ${CMAKE_IOS_DEVELOPER_ROOT}
  ${CMAKE_IOS_SDK_ROOT}
  ${CMAKE_PREFIX_PATH}
  CACHE string  "iOS find search path root"
)

# set up the default search directories for frameworks
set (CMAKE_SYSTEM_FRAMEWORK_PATH
  ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
  ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
  ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
)

# visibility flags
set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden")

# from https://public.kitware.com/Bug/view.php?id=15329
set(CMAKE_MACOSX_BUNDLE YES)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")


if(CMAKE_OSX_SYSROOT)
  if(NOT IS_DIRECTORY "${CMAKE_OSX_SYSROOT}")
    message(FATAL_ERROR
      "iOS: The system root directory needed for the selected iOS version and 
architecture does not exist:\n"
      "  ${CMAKE_OSX_SYSROOT}\n"
      )
  endif()
else()
  message(FATAL_ERROR
    "iOS: No CMAKE_OSX_SYSROOT was selected."
    )
endif()

set(CMAKE_BUILD_TYPE_INIT Debug)
-- 

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:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to