Linux to iOS C++ Cross Compile

In this article I will describe the build process of C++ SDL iOS app on Linux, resign ipa file without a paid subscription to Apple Developer Program and installation on a clean device (iPad) via macOS without Jailbreak.

First, install the build toolchain in Linux:
https://github.com/tpoechtrager/cctools-port

Toolchain needs to be downloaded from the repository, follow instructions on the site of Godot Engine to complete the installation:
https://docs.godotengine.org/ru/latest/development/compiling/cross-compiling_for_ios_on_linux.html

At this point you need to download Xcode dmg and copy ios sdk to build cctools-port. This stage is easier to pass on MacOS, simply copy of Xcode installed sdk necessary files. After successful build, the terminal will show a path to crosscompiler bin directory.

You can then proceed to the build of SDL applications for iOS. Open cmake and add the necessary changes for C ++ build code:


SET(CMAKE_SYSTEM_NAME Darwin)
SET(CMAKE_C_COMPILER arm-apple-darwin11-clang)
SET(CMAKE_CXX_COMPILER arm-apple-darwin11-clang++)
SET(CMAKE_LINKER arm-apple-darwin11-ld)

Now you can build using cmake and make, but do not forget to register to the $PATH of crosscompiler bin directory:



PATH=$PATH:~/Sources/cctools-port/usage_examples/ios_toolchain/target/bin

For correct linking with frameworks and SDL add them to cmake, Space Jaguar games depending for example:



target_link_libraries(
${FSEGT_PROJECT_NAME}
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libclang_rt.ios.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2_mixer.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2_image.a
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreServices.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/ImageIO.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/Metal.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/AVFoundation.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/GameController.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreMotion.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreGraphics.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/AudioToolbox.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreAudio.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/QuartzCore.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/OpenGLES.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/UIKit.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/Foundation.framework"
)

In my case, SDL library, SDL_Image, SDL_mixer compiled in Xcode on macOS advance for static linking; Frameworks copied from Xcode. Also added libclang_rt.ios.a library, which includes specific runtime iOS calls, e.g. isOSVersionAtLeast. Enabled macros for working with OpenGL ES, disables unsupported features in the mobile platforms, similar to Android.

After the resolving build problems, you must get a binary compiled for the arm. Next, I will describe binary installation and run on the device without Jailbreak.

On macOS make Xcode installation, register on Apple’s website, without having to pay for the development of the program. Add account in Xcode -> Preferences -> Accounts, create an empty application and build for a real device. During assembly, device will be added to a free developer account. After building and running, you need to make an archive of the build, for this select Generic iOS Device and Product -> Archive. By the end of the archive build, copy files called embedded.mobileprovision, PkgInfo. From the build log on the device, find the line codesign with the correct key signature, the path to the file with the extension of entitlements app.xcent, copy it.

Copy the .app from the archive, replace binary in the archive created by cross-compiler in Linux (eg SpaceJaguar.app/SpaceJaguar), further adding to the .app necessary resources to check the safety and PkgInfo embedded.mobileprovision in the .app file from the archive, copy again if needed. Resign .app using codesign command – codesign requires the input argument of the key for the sign, the path to the entitlements file (can be renamed with the extension .plist)

After resign create Payload folder, move to the folder with the .app extension, create a zip file with the Payload directory, rename the file with the extension .ipa. After that, in Xcode, open the list of devices and Drag’n’Drop ipa in the list of device applications; Installation via Apple Configurator 2 for this process does not work. If resign made correctly, a new application is installed with correct binary on iOS device (e.g. iPad) with 7 day certificate for testing period that is sufficient.

References

https://github.com/tpoechtrager/cctools-port
https://docs.godotengine.org/ru/latest/development/compiling/cross-compiling_for_ios_on_linux.html
https://jonnyzzz.com/blog/2018/06/13/link-error-3/
https://stackoverflow.com/questions/6896029/re-sign-ipa-iphone
https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html