Cross-compiling for iOS on Linux:
Your Godot version: 4.4.1
Issue description:
The documentation for Cross-compiling for iOS on Linux seems outdated. Many of the components (pbzx, xar, etc.) are wrong but they can still be obtained.
Some steps like the one below doesn't work because something is missing.
cp -r xcode/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk/usr/include/c++
Or, there is no a clear example of the path (in this case for the chain):
scons platform=ios arch=arm64 target=template_release IOS_SDK_PATH="$IOS_SDK_PATH" IOS_TOOLCHAIN_PATH="$IOS_TOOLCHAIN_PATH" ios_triple="arm-apple-darwin11-"
Where IOS_TOOLCHAIN_PATH could be, in my case:
- This:
$HOME/iostoolchain/usr/bin - or this:
$HOME/iostoolchain/usr - or this:
$HOME/iostoolchain
Finally, it takes days for whoever is trying this the first time. I can't even make it work yet.
I think that creating an installation bash file is required for sanity sake.
URL to the documentation page (if already existing):
(Cross-compiling for iOS on Linux)[https://docs.godotengine.org/en/stable/contributing/development/compiling/cross-compiling_for_ios_on_linux.html#cross-compiling-for-ios-on-linux]
install_ios_cross_compile.sh
First draft of the script:
#!/usr/bin/env bash
# filepath: install_ios_cross_compile.sh
set -e
# Default values from your environment
XCODE_PATH="${XCODE_PATH:-$HOME/xcode}"
IOS_SDK_VERSION="${IOS_SDK_VERSION:-16.4}"
IOS_SDK_PATH="${IOS_SDK_PATH:-$HOME/iPhoneSDK/iPhoneOS$IOS_SDK_VERSION.sdk}"
IOS_TOOLCHAIN_PATH="${IOS_TOOLCHAIN_PATH:-$HOME/iostoolchain/usr/bin}"
NONINTERACTIVE=0
# Parse arguments
for arg in "$@"; do
case $arg in
-y|--yes)
NONINTERACTIVE=1
shift
;;
esac
done
ask() {
if [ "$NONINTERACTIVE" -eq 1 ]; then
return 0
fi
read -p "$1 [Y/n] " yn
case $yn in
[Nn]*) return 1 ;;
*) return 0 ;;
esac
}
install_package() {
PKG="$1"
if ! dpkg -s "$PKG" >/dev/null 2>&1; then
if ask "Install $PKG?"; then
sudo apt-get update
sudo apt-get install -y "$PKG"
else
echo "Please install $PKG manually and re-run the script."
exit 1
fi
fi
}
echo "Checking required programs..."
install_package clang
install_package git
install_package automake
install_package autogen
install_package libtool
install_package xz-utils
install_package cpio
install_package fuse
install_package libfuse2
# xar
if ! command -v xar >/dev/null 2>&1; then
echo "xar not found."
echo "You can build it from https://mackyle.github.io/xar/ or use your package manager."
if ask "Try to install xar from apt?"; then
sudo apt-get install -y xar
else
echo "Please install xar manually and re-run the script."
exit 1
fi
fi
# pbzx
if ! command -v pbzx >/dev/null 2>&1; then
echo "pbzx not found."
echo "You can get pbzx from https://github.com/NiklasRosenstein/pbzx"
if ask "Clone and install pbzx to ~/pbzx?"; then
git clone https://github.com/NiklasRosenstein/pbzx.git ~/pbzx
sudo install ~/pbzx/pbzx /usr/local/bin/
else
echo "Please install pbzx manually and re-run the script."
exit 1
fi
fi
# Check for Xcode .xip
if [ ! -d "$XCODE_PATH" ]; then
echo "Xcode not found at $XCODE_PATH."
echo "Please download the Xcode .xip from https://developer.apple.com/download/all/?q=Xcode"
echo "and extract it to $XCODE_PATH."
exit 1
fi
# Prepare SDK
if [ -d "$IOS_SDK_PATH" ]; then
echo "iOS SDK already exists at $IOS_SDK_PATH."
if ask "Skip SDK extraction?"; then
:
else
rm -rf "$IOS_SDK_PATH"
fi
fi
if [ ! -d "$IOS_SDK_PATH" ]; then
if ask "Extract iOS SDK version $IOS_SDK_VERSION from Xcode?"; then
mkdir -p "$IOS_SDK_PATH"
cp -r "$XCODE_PATH/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/"* "$IOS_SDK_PATH/"
cp -r "$XCODE_PATH/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/"* "$IOS_SDK_PATH/usr/include/c++/"
fi
fi
# Pack SDK
SDK_ARCHIVE="$HOME/iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz"
if [ -f "$SDK_ARCHIVE" ]; then
echo "SDK archive $SDK_ARCHIVE already exists."
if ask "Skip SDK archiving?"; then
:
else
rm -f "$SDK_ARCHIVE"
fi
fi
if [ ! -f "$SDK_ARCHIVE" ]; then
if ask "Pack the SDK into $SDK_ARCHIVE?"; then
cd "$(dirname "$IOS_SDK_PATH")"
tar -cf - "$(basename "$IOS_SDK_PATH")" | xz -9 -c - > "$SDK_ARCHIVE"
fi
fi
# Build cctools
if [ -d "$HOME/cctools-port" ]; then
echo "cctools-port already cloned."
if ask "Skip cctools-port clone?"; then
:
else
rm -rf "$HOME/cctools-port"
fi
fi
if [ ! -d "$HOME/cctools-port" ]; then
git clone https://github.com/tpoechtrager/cctools-port.git "$HOME/cctools-port"
fi
if [ -d "$HOME/cctools-port/usage_examples/ios_toolchain/target/bin" ]; then
echo "cctools already built."
if ask "Skip cctools build?"; then
:
else
rm -rf "$HOME/cctools-port/usage_examples/ios_toolchain/target"
fi
fi
if [ ! -d "$HOME/cctools-port/usage_examples/ios_toolchain/target/bin" ]; then
cd "$HOME/cctools-port/usage_examples/ios_toolchain"
./build.sh "$SDK_ARCHIVE" arm64
fi
# Copy toolchain
if [ -d "$IOS_TOOLCHAIN_PATH" ]; then
echo "Toolchain already exists at $IOS_TOOLCHAIN_PATH."
if ask "Skip copying toolchain?"; then
:
else
rm -rf "$IOS_TOOLCHAIN_PATH"
fi
fi
if [ ! -d "$IOS_TOOLCHAIN_PATH" ]; then
mkdir -p "$(dirname "$IOS_TOOLCHAIN_PATH")"
cp -r "$HOME/cctools-port/usage_examples/ios_toolchain/target/bin" "$(dirname "$IOS_TOOLCHAIN_PATH")/"
fi
echo "Setup complete!"
echo "You can now build Godot for iOS using:"
echo " scons platform=ios arch=arm64 target=template_release IOS_SDK_PATH=\"$IOS_SDK_PATH\" IOS_TOOLCHAIN_PATH=\"$IOS_TOOLCHAIN_PATH\" ios_triple=\"arm-apple-darwin11-\""
# End of script
I'm going to split this file in different one for sanity sake:
Lets start with a script that will detect all the components required:
check_ios_cross_compile_requirements.sh
#!/usr/bin/env bash
# filepath: check_ios_cross_compile_requirements.sh
set -e
REQUIRED_CMDS=(
clang
git
xar
pbzx
automake
autogen
libtool
xz
cpio
fusermount
)
MISSING=0
check_required_cmds() {
echo "Checking required commands and tools for iOS cross-compiling..."
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "❌ $cmd: NOT FOUND"
MISSING=1
else
echo "✅ $cmd: found at $(command -v $cmd)"
fi
done
}
check_xcode_sdk_dir() {
if [ -z "$XCODE_PATH" ]; then
XCODE_PATH="$HOME/xcode"
fi
if [ ! -d "$XCODE_PATH" ]; then
echo "❌ Xcode SDK directory not found at $XCODE_PATH"
MISSING=1
else
echo "✅ Xcode SDK directory found at $XCODE_PATH"
fi
}
check_ios_sdk_version() {
if [ -z "$IOS_SDK_VERSION" ]; then
echo "❌ IOS_SDK_VERSION environment variable is not set"
MISSING=1
else
echo "✅ IOS_SDK_VERSION is set to $IOS_SDK_VERSION"
fi
}
check_pbzx() {
if ! command -v pbzx >/dev/null 2>&1; then
if [ -f "$HOME/pbzx/pbzx" ]; then
echo "✅ pbzx found at $HOME/pbzx/pbzx (not in PATH)"
else
echo "❌ pbzx: NOT FOUND"
MISSING=1
fi
fi
}
# Run all checks
check_required_cmds
check_xcode_sdk_dir
check_ios_sdk_version
check_pbzx
if [ "$MISSING" -eq 1 ]; then
echo ""
echo "Some required components are missing. Please install them before proceeding."
exit 1
else
echo ""
echo "All required components are installed and accessible."
fi
Output Example
$ ./check_ios_cross_compile_requirements.sh
Checking required commands and tools for iOS cross-compiling...
✅ clang: found at /usr/bin/clang
✅ git: found at /usr/bin/git
✅ xar: found at /usr/local/bin/xar
✅ pbzx: found at /home/myhome/pbzx/pbzx
✅ automake: found at /usr/bin/automake
❌ autogen: NOT FOUND
❌ libtool: NOT FOUND
✅ xz: found at /usr/bin/xz
✅ cpio: found at /usr/bin/cpio
✅ fusermount: found at /usr/bin/fusermount
✅ Xcode SDK directory found at /home/myhome/xcode
✅ IOS_SDK_VERSION is set to 16.4
Some required components are missing. Please install them before proceeding.
Updated the code to try to install the components:
#!/usr/bin/env bash
# filepath: check_ios_cross_compile_requirements.sh
set -e
REQUIRED_CMDS=(
clang
git
xar
pbzx
automake
autogen
libtool
xz
cpio
fusermount
)
MISSING=0
MISSING_CMDS=()
check_required_cmds() {
echo "Checking required commands and tools for iOS cross-compiling..."
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "❌ $cmd: NOT FOUND"
MISSING=1
MISSING_CMDS+=("$cmd")
else
echo "✅ $cmd: found at $(command -v $cmd)"
fi
done
}
check_xcode_sdk_dir() {
if [ -z "$XCODE_PATH" ]; then
XCODE_PATH="$HOME/xcode"
fi
if [ ! -d "$XCODE_PATH" ]; then
echo "❌ Xcode SDK directory not found at $XCODE_PATH"
MISSING=1
else
echo "✅ Xcode SDK directory found at $XCODE_PATH"
fi
}
check_ios_sdk_version() {
if [ -z "$IOS_SDK_VERSION" ]; then
echo "❌ IOS_SDK_VERSION environment variable is not set"
MISSING=1
else
echo "✅ IOS_SDK_VERSION is set to $IOS_SDK_VERSION"
fi
}
check_pbzx() {
if ! command -v pbzx >/dev/null 2>&1; then
if [ -f "$HOME/pbzx/pbzx" ]; then
echo "✅ pbzx found at $HOME/pbzx/pbzx (not in PATH)"
else
echo "❌ pbzx: NOT FOUND"
MISSING=1
if [[ ! " ${MISSING_CMDS[@]} " =~ " pbzx " ]]; then
MISSING_CMDS+=("pbzx")
fi
fi
fi
}
install_xar_from_source() {
echo "Installing xar from source..."
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz
tar -zxvf xar-1.5.2.tar.gz
cd xar-1.5.2
sudo apt install -y gcc
sudo apt-get install -y libxml2-dev zlib1g-dev autoconf libbz2-dev
./autogen.sh --noconfigure
./configure --with-bzip2
make
sudo make install
cd ..
echo "xar installation from source complete."
}
install_pbzx_from_source() {
echo "Installing pbzx from source..."
git clone https://github.com/NiklasRosenstein/pbzx.git
cd pbzx
sudo apt-get install -y clang liblzma-dev
clang -llzma -lxar -I /usr/local/include pbzx.c -o pbzx
echo "pbzx installation from source complete. The binary is at $(pwd)/pbzx"
cd ..
}
handle_missing_components() {
echo ""
echo "Some required components are missing:"
for cmd in "${MISSING_CMDS[@]}"; do
echo " - $cmd"
done
echo ""
read -p "Do you want to attempt to install the missing components now? [y/N]: " yn
case "$yn" in
[Yy]* )
echo "Attempting to install missing components..."
sudo apt-get update
PKGS=()
for cmd in "${MISSING_CMDS[@]}"; do
case "$cmd" in
clang) PKGS+=("clang") ;;
git) PKGS+=("git") ;;
xar) install_xar_from_source ;;
pbzx) install_pbzx_from_source ;;
automake) PKGS+=("automake") ;;
autogen) PKGS+=("autogen") ;;
libtool) PKGS+=("libtool") ;;
xz) PKGS+=("xz-utils") ;;
cpio) PKGS+=("cpio") ;;
fusermount) PKGS+=("fuse") ;;
*) PKGS+=("$cmd") ;;
esac
done
if [ "${#PKGS[@]}" -gt 0 ]; then
sudo apt-get install -y "${PKGS[@]}"
fi
;;
* )
echo "Exiting without installing missing components."
exit 1
;;
esac
exit 1
}
# Run all checks
check_required_cmds
check_xcode_sdk_dir
check_ios_sdk_version
check_pbzx
if [ "$MISSING" -eq 1 ]; then
handle_missing_components
else
echo ""
echo "All required components are installed and accessible."
fi
Updated the code to try to install the components. Made it to be the stable version 1.0.0. Let me know if I'm missing something:
#!/usr/bin/env bash
# filepath: check_ios_cross_compile_requirements.sh
# version: 1.0.0
# description: This script checks for the required tools and environment variables for iOS cross-compiling.
set -e
REQUIRED_CMDS=(
clang
git
xar
pbzx
automake
autogen
libtool
xz
cpio
fusermount
)
MISSING=0
MISSING_CMDS=()
check_required_cmds() {
echo "Checking required commands and tools for iOS cross-compiling..."
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "❌ $cmd: NOT FOUND"
MISSING=1
MISSING_CMDS+=("$cmd")
else
echo "✅ $cmd: found at $(command -v $cmd)"
fi
done
}
check_xcode_sdk_dir() {
if [ -z "$XCODE_PATH" ]; then
XCODE_PATH="$HOME/xcode"
fi
if [ ! -d "$XCODE_PATH" ]; then
echo "❌ Xcode SDK directory not found at $XCODE_PATH"
MISSING=1
else
echo "✅ Xcode SDK directory found at $XCODE_PATH"
fi
}
check_ios_sdk_version() {
if [ -z "$IOS_SDK_VERSION" ]; then
echo "❌ IOS_SDK_VERSION environment variable is not set"
MISSING=1
else
echo "✅ IOS_SDK_VERSION is set to $IOS_SDK_VERSION"
fi
}
check_pbzx() {
if ! command -v pbzx >/dev/null 2>&1; then
if [ -f "$HOME/pbzx/pbzx" ]; then
echo "✅ pbzx found at $HOME/pbzx/pbzx (not in PATH)"
else
echo "❌ pbzx: NOT FOUND"
MISSING=1
if [[ ! " ${MISSING_CMDS[@]} " =~ " pbzx " ]]; then
MISSING_CMDS+=("pbzx")
fi
fi
fi
}
install_xar_from_source() {
echo "Installing xar from source..."
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz
tar -zxvf xar-1.5.2.tar.gz
cd xar-1.5.2
sudo apt install -y gcc
sudo apt-get install -y libxml2-dev zlib1g-dev autoconf libbz2-dev
./autogen.sh --noconfigure
./configure --with-bzip2
make
sudo make install
cd ..
echo "xar installation from source complete."
}
install_pbzx_from_source() {
echo "Installing pbzx from source..."
git clone https://github.com/NiklasRosenstein/pbzx.git
cd pbzx
sudo apt-get install -y clang liblzma-dev
clang -llzma -lxar -I /usr/local/include pbzx.c -o pbzx
echo "pbzx installation from source complete. The binary is at $(pwd)/pbzx"
cd ..
}
handle_missing_components() {
echo ""
echo "Some required components are missing:"
for cmd in "${MISSING_CMDS[@]}"; do
echo " - $cmd"
done
echo ""
read -p "Do you want to attempt to install the missing components now? [y/N]: " yn
case "$yn" in
[Yy]* )
echo "Attempting to install missing components..."
sudo apt-get update
PKGS=()
for cmd in "${MISSING_CMDS[@]}"; do
case "$cmd" in
clang) PKGS+=("clang") ;;
git) PKGS+=("git") ;;
xar) install_xar_from_source ;;
pbzx) install_pbzx_from_source ;;
automake) PKGS+=("automake") ;;
autogen) PKGS+=("autogen") ;;
libtool) PKGS+=("libtool-bin") ;; # Use libtool-bin for the actual binary
xz) PKGS+=("xz-utils") ;;
cpio) PKGS+=("cpio") ;;
fusermount) PKGS+=("fuse") ;;
*) PKGS+=("$cmd") ;;
esac
done
if [ "${#PKGS[@]}" -gt 0 ]; then
sudo apt-get install -y "${PKGS[@]}"
fi
;;
* )
echo "Exiting without installing missing components."
exit 1
;;
esac
exit 1
}
# Run all checks
check_required_cmds
check_xcode_sdk_dir
check_ios_sdk_version
check_pbzx
if [ "$MISSING" -eq 1 ]; then
handle_missing_components
else
echo ""
echo "All required components are installed and accessible."
fi
Here is the output on my machine:
$ ./check_ios_cross_compile_requirements.sh
Checking required commands and tools for iOS cross-compiling...
✅ clang: found at /usr/bin/clang
✅ git: found at /usr/bin/git
✅ xar: found at /usr/local/bin/xar
✅ pbzx: found at /home/myhome/pbzx/pbzx
✅ automake: found at /usr/bin/automake
✅ autogen: found at /usr/bin/autogen
✅ libtool: found at /usr/bin/libtool
✅ xz: found at /usr/bin/xz
✅ cpio: found at /usr/bin/cpio
✅ fusermount: found at /usr/bin/fusermount
✅ Xcode SDK directory found at /home/myhome/xcode
✅ IOS_SDK_VERSION is set to 16.4
All required components are installed and accessible.
Next, the configuration file that will try to do the steps of the documentation
configuration.sh
#!/usr/bin/env bash
# version: 0.0.1
# description: Automate SDK extraction, toolchain build, and environment setup for Godot iOS cross-compiling.
set -e
AUTO_INSTALL=0
usage() {
echo "Usage: $0 [--auto]"
echo " --auto Automatically run all steps without prompting."
exit 1
}
if [[ "$1" == "--auto" ]]; then
AUTO_INSTALL=1
elif [[ -n "$1" ]]; then
usage
fi
prompt_step() {
local msg="$1"
if [[ "$AUTO_INSTALL" -eq 1 ]]; then
return 0
fi
read -p "$msg [y/N]: " yn
case "$yn" in
[Yy]*) return 0 ;;
*) return 1 ;;
esac
}
extract_xcode_xip() {
if prompt_step "Extract Xcode .xip and unpack Xcode.app?"; then
# Search for .xip files in current dir and $HOME
mapfile -t XIP_FILES < <(find . "$HOME" -maxdepth 2 -type f -name "*.xip" 2>/dev/null)
if [[ ${#XIP_FILES[@]} -eq 0 ]]; then
echo "No .xip files found. Please provide the path manually."
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
else
echo "Found the following .xip files:"
select XIP_CHOICE in "${XIP_FILES[@]}" "Enter path manually"; do
if [[ "$REPLY" -gt 0 && "$REPLY" -le "${#XIP_FILES[@]}" ]]; then
XCODE_XIP="${XIP_FILES[$((REPLY-1))]}"
break
elif [[ "$REPLY" -eq $((${#XIP_FILES[@]}+1)) ]]; then
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
break
else
echo "Invalid selection."
fi
done
fi
mkdir -p xcode
xar -xf "$XCODE_XIP" -C xcode
cd xcode
pbzx -n Content | cpio -i
cd ..
echo "Xcode .xip extraction complete."
fi
}
extract_ios_sdk() {
if prompt_step "Extract and prepare iOS SDK from Xcode.app?"; then
read -e -p "Enter iOS SDK version (e.g., 17.0): " IOS_SDK_VERSION
export IOS_SDK_VERSION
mkdir -p iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r xcode/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk/usr/include/c++
fusermount -u xcode || true
echo "iOS SDK extracted to iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk"
fi
}
pack_ios_sdk() {
if prompt_step "Pack the iOS SDK for cctools-port?"; then
cd iPhoneSDK
tar -cf - * | xz -9 -c - > iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz
cd ..
echo "Packed SDK: iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz"
fi
}
build_cctools_port() {
if prompt_step "Build cctools-port toolchain?"; then
git clone https://github.com/tpoechtrager/cctools-port.git || true
cd cctools-port/usage_examples/ios_toolchain
sudo apt-get install -y automake autogen libtool-bin
./build.sh ../../../../iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz arm64
cd ../../..
echo "cctools-port toolchain build complete."
fi
}
copy_toolchain_binaries() {
if prompt_step "Copy toolchain binaries to \$HOME/iostoolchain/usr/bin?"; then
mkdir -p "$HOME/iostoolchain/usr"
cp -r cctools-port/usage_examples/ios_toolchain/target/bin "$HOME/iostoolchain/usr/"
echo "Toolchain binaries copied to $HOME/iostoolchain/usr/bin"
fi
}
set_env_and_show_scons() {
if prompt_step "Show environment setup and SCons build command?"; then
echo "You must keep the built toolchain and iPhoneOS SDK directory."
echo "Set the following environment variable before building:"
echo
echo ' export OSXCROSS_IOS="anything"'
echo
echo "Example SCons build command:"
echo
echo " scons platform=ios arch=arm64 target=template_release \\"
echo " IOS_SDK_PATH=\"$(pwd)/iPhoneSDK\" \\"
echo " IOS_TOOLCHAIN_PATH=\"\$HOME/iostoolchain\" \\"
echo " ios_triple=\"arm-apple-darwin11-\""
echo
fi
}
main() {
extract_xcode_xip
extract_ios_sdk
pack_ios_sdk
build_cctools_port
copy_toolchain_binaries
set_env_and_show_scons
echo "iOS cross-compiling environment setup steps complete."
}
main
Updated the configure.sh:
#!/usr/bin/env bash
# version: 0.0.5
# description: Automate SDK extraction, toolchain build, and environment setup for Godot iOS cross-compiling.
set -e
AUTO_INSTALL=0
usage() {
echo "Usage: $0 [--auto]"
echo " --auto Automatically run all steps without prompting."
exit 1
}
if [[ "$1" == "--auto" ]]; then
AUTO_INSTALL=1
elif [[ -n "$1" ]]; then
usage
fi
prompt_step() {
local msg="$1"
if [[ "$AUTO_INSTALL" -eq 1 ]]; then
return 0
fi
read -p "$msg [y/N]: " yn
case "$yn" in
[Yy]*) return 0 ;;
*) return 1 ;;
esac
}
extract_xcode_xip() {
if prompt_step "Extract Xcode .xip and unpack Xcode.app into \$HOME/xcode?"; then
# Search for .xip files in current dir and $HOME
mapfile -t XIP_FILES < <(find . "$HOME" -maxdepth 2 -type f -name "*.xip" 2>/dev/null)
if [[ ${#XIP_FILES[@]} -eq 0 ]]; then
echo "No .xip files found. Please provide the path manually."
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
else
echo "Found the following .xip files:"
select XIP_CHOICE in "${XIP_FILES[@]}" "Enter path manually"; do
if [[ "$REPLY" -gt 0 && "$REPLY" -le "${#XIP_FILES[@]}" ]]; then
XCODE_XIP="${XIP_FILES[$((REPLY-1))]}"
break
elif [[ "$REPLY" -eq $((${#XIP_FILES[@]}+1)) ]]; then
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
break
else
echo "Invalid selection."
fi
done
fi
XCODE_DIR="$HOME/xcode"
if [[ -d "$XCODE_DIR" ]]; then
if prompt_step "Directory $XCODE_DIR already exists. Overwrite?"; then
rm -rf "$XCODE_DIR"
else
echo "Skipping extraction."
return
fi
fi
mkdir -p "$XCODE_DIR"
pushd "$XCODE_DIR"
echo "Extracting Xcode .xip archive (this may take several minutes)..."
xar -xf "$XCODE_XIP"
echo "Unpacking pbzx stream (this may take several minutes)..."
pbzx -n Content | cpio -i
popd
echo "Xcode .xip extraction complete in $XCODE_DIR."
fi
}
extract_ios_sdk() {
if prompt_step "Extract and prepare iOS SDK from Xcode.app?"; then
# Try to find iOS SDK directories inside $HOME/xcode/Xcode.app
mapfile -t SDK_DIRS < <(find "$HOME/xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/" -maxdepth 1 -type d -name "iPhoneOS*.sdk" 2>/dev/null)
if [[ ${#SDK_DIRS[@]} -eq 0 ]]; then
echo "No iOS SDK directories found. Please provide the path manually."
read -e -p "Enter path to iPhoneOS.sdk directory: " SDK_PATH
else
echo "Found the following iOS SDK directories:"
select SDK_CHOICE in "${SDK_DIRS[@]}" "Enter path manually"; do
if [[ "$REPLY" -gt 0 && "$REPLY" -le "${#SDK_DIRS[@]}" ]]; then
SDK_PATH="${SDK_DIRS[$((REPLY-1))]}"
break
elif [[ "$REPLY" -eq $((${#SDK_DIRS[@]}+1)) ]]; then
read -e -p "Enter path to iPhoneOS.sdk directory: " SDK_PATH
break
else
echo "Invalid selection."
fi
done
fi
read -e -p "Enter iOS SDK version (e.g., 17.0): " IOS_SDK_VERSION
export IOS_SDK_VERSION
mkdir -p iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r "$SDK_PATH"/* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r "$HOME/xcode/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/"* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk/usr/include/c++
fusermount -u "$HOME/xcode" || true
echo "iOS SDK extracted to iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk"
fi
}
pack_ios_sdk() {
if prompt_step "Pack the iOS SDK for cctools-port?"; then
cd iPhoneSDK
echo "Packing iOS SDK (this may take a while)..."
tar -cf - * | xz -9 -c - > iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz
cd ..
echo "Packed SDK: iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz"
fi
}
build_cctools_port() {
if prompt_step "Build cctools-port toolchain?"; then
git clone https://github.com/tpoechtrager/cctools-port.git || true
cd cctools-port/usage_examples/ios_toolchain
sudo apt-get install -y automake autogen libtool-bin
./build.sh ../../../../iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz arm64
cd ../../..
echo "cctools-port toolchain build complete."
fi
}
copy_toolchain_binaries() {
if prompt_step "Copy toolchain binaries to \$HOME/iostoolchain/usr/bin?"; then
mkdir -p "$HOME/iostoolchain/usr"
cp -r cctools-port/usage_examples/ios_toolchain/target/bin "$HOME/iostoolchain/usr/"
echo "Toolchain binaries copied to $HOME/iostoolchain/usr/bin"
fi
}
set_env_and_show_scons() {
if prompt_step "Show environment setup and SCons build command?"; then
echo "You must keep the built toolchain and iPhoneOS SDK directory."
echo "Set the following environment variable before building:"
echo
echo ' export OSXCROSS_IOS="anything"'
echo
echo "Example SCons build command:"
echo
echo " scons platform=ios arch=arm64 target=template_release \\"
echo " IOS_SDK_PATH=\"$(pwd)/iPhoneSDK\" \\"
echo " IOS_TOOLCHAIN_PATH=\"\$HOME/iostoolchain\" \\"
echo " ios_triple=\"arm-apple-darwin11-\""
echo
fi
}
main() {
extract_xcode_xip
extract_ios_sdk
pack_ios_sdk
build_cctools_port
copy_toolchain_binaries
set_env_and_show_scons
echo "iOS cross-compiling environment setup steps complete."
}
main
I'm not sure it works yet. I have to create some project in godot and see if I can make it work.
The question I have is how do I deploy to my iphone. Does the command scons take care of that?
Updated configure.sh to create the file build_ios_godot.sh, so the user can do one step less:
#!/usr/bin/env bash
# version: 0.0.6
# description: Automate SDK extraction, toolchain build, and environment setup for Godot iOS cross-compiling.
set -e
AUTO_INSTALL=0
usage() {
echo "Usage: $0 [--auto]"
echo " --auto Automatically run all steps without prompting."
exit 1
}
if [[ "$1" == "--auto" ]]; then
AUTO_INSTALL=1
elif [[ -n "$1" ]]; then
usage
fi
prompt_step() {
local msg="$1"
if [[ "$AUTO_INSTALL" -eq 1 ]]; then
return 0
fi
read -p "$msg [y/N]: " yn
case "$yn" in
[Yy]*) return 0 ;;
*) return 1 ;;
esac
}
extract_xcode_xip() {
if prompt_step "Extract Xcode .xip and unpack Xcode.app into \$HOME/xcode?"; then
# Search for .xip files in current dir and $HOME
mapfile -t XIP_FILES < <(find . "$HOME" -maxdepth 2 -type f -name "*.xip" 2>/dev/null)
if [[ ${#XIP_FILES[@]} -eq 0 ]]; then
echo "No .xip files found. Please provide the path manually."
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
else
echo "Found the following .xip files:"
select XIP_CHOICE in "${XIP_FILES[@]}" "Enter path manually"; do
if [[ "$REPLY" -gt 0 && "$REPLY" -le "${#XIP_FILES[@]}" ]]; then
XCODE_XIP="${XIP_FILES[$((REPLY-1))]}"
break
elif [[ "$REPLY" -eq $((${#XIP_FILES[@]}+1)) ]]; then
read -e -p "Enter path to Xcode .xip file: " XCODE_XIP
break
else
echo "Invalid selection."
fi
done
fi
XCODE_DIR="$HOME/xcode"
if [[ -d "$XCODE_DIR" ]]; then
if prompt_step "Directory $XCODE_DIR already exists. Overwrite?"; then
rm -rf "$XCODE_DIR"
else
echo "Skipping extraction."
return
fi
fi
mkdir -p "$XCODE_DIR"
pushd "$XCODE_DIR"
echo "Extracting Xcode .xip archive (this may take several minutes)..."
xar -xf "$XCODE_XIP"
echo "Unpacking pbzx stream (this may take several minutes)..."
pbzx -n Content | cpio -i
popd
echo "Xcode .xip extraction complete in $XCODE_DIR."
fi
}
extract_ios_sdk() {
if prompt_step "Extract and prepare iOS SDK from Xcode.app?"; then
# Try to find iOS SDK directories inside $HOME/xcode/Xcode.app
mapfile -t SDK_DIRS < <(find "$HOME/xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/" -maxdepth 1 -type d -name "iPhoneOS*.sdk" 2>/dev/null)
if [[ ${#SDK_DIRS[@]} -eq 0 ]]; then
echo "No iOS SDK directories found. Please provide the path manually."
read -e -p "Enter path to iPhoneOS.sdk directory: " SDK_PATH
else
echo "Found the following iOS SDK directories:"
select SDK_CHOICE in "${SDK_DIRS[@]}" "Enter path manually"; do
if [[ "$REPLY" -gt 0 && "$REPLY" -le "${#SDK_DIRS[@]}" ]]; then
SDK_PATH="${SDK_DIRS[$((REPLY-1))]}"
break
elif [[ "$REPLY" -eq $((${#SDK_DIRS[@]}+1)) ]]; then
read -e -p "Enter path to iPhoneOS.sdk directory: " SDK_PATH
break
else
echo "Invalid selection."
fi
done
fi
read -e -p "Enter iOS SDK version (e.g., 17.0): " IOS_SDK_VERSION
export IOS_SDK_VERSION
mkdir -p iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r "$SDK_PATH"/* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk
cp -r "$HOME/xcode/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/"* iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk/usr/include/c++
fusermount -u "$HOME/xcode" || true
echo "iOS SDK extracted to iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk"
fi
}
pack_ios_sdk() {
if prompt_step "Pack the iOS SDK for cctools-port?"; then
cd iPhoneSDK
echo "Packing iOS SDK (this may take a while)..."
tar -cf - * | xz -9 -c - > iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz
cd ..
echo "Packed SDK: iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz"
fi
}
build_cctools_port() {
if prompt_step "Build cctools-port toolchain?"; then
git clone https://github.com/tpoechtrager/cctools-port.git || true
cd cctools-port/usage_examples/ios_toolchain
sudo apt-get install -y automake autogen libtool-bin
./build.sh ../../../../iPhoneSDK/iPhoneOS${IOS_SDK_VERSION}.sdk.tar.xz arm64
cd ../../..
echo "cctools-port toolchain build complete."
fi
}
copy_toolchain_binaries() {
if prompt_step "Copy toolchain binaries to \$HOME/iostoolchain/usr/bin?"; then
mkdir -p "$HOME/iostoolchain/usr"
cp -r cctools-port/usage_examples/ios_toolchain/target/bin "$HOME/iostoolchain/usr/"
echo "Toolchain binaries copied to $HOME/iostoolchain/usr/bin"
fi
}
set_env_and_show_scons() {
if prompt_step "Show environment setup and SCons build command?"; then
echo "You must keep the built toolchain and iPhoneOS SDK directory."
echo "Set the following environment variable before building:"
echo
echo ' export OSXCROSS_IOS="anything"'
echo
echo "Example SCons build command:"
echo
echo " scons platform=ios arch=arm64 target=template_release \\"
echo " IOS_SDK_PATH=\"$(pwd)/iPhoneSDK\" \\"
echo " IOS_TOOLCHAIN_PATH=\"\$HOME/iostoolchain\" \\"
echo " ios_triple=\"arm-apple-darwin11-\""
echo
if prompt_step "Would you like to generate an executable bash script to run these commands?"; then
SCRIPT_PATH="./build_ios_godot.sh"
cat > "$SCRIPT_PATH" <<EOF
#!/usr/bin/env bash
# Auto-generated script to build Godot for iOS
export OSXCROSS_IOS="anything"
scons platform=ios arch=arm64 target=template_release \\
IOS_SDK_PATH="$(pwd)/iPhoneSDK" \\
IOS_TOOLCHAIN_PATH="\$HOME/iostoolchain" \\
ios_triple="arm-apple-darwin11-"
EOF
chmod +x "$SCRIPT_PATH"
echo "Executable script created at: $SCRIPT_PATH"
fi
fi
}
main() {
extract_xcode_xip
extract_ios_sdk
pack_ios_sdk
build_cctools_port
copy_toolchain_binaries
set_env_and_show_scons
echo "iOS cross-compiling environment setup steps complete."
}
main