
# Objective On iOS: - Allow `std` to do its runtime initialization. - Avoid requiring the user to specify linked libraries and framework in Xcode. - Reduce the amount of work that `#[bevy_main]` does - In the future we may also be able to eliminate the need for it on Android, cc @daxpedda. ## Solution We previously: - Exposed an `extern "C" fn main_rs` entry point. - Ran Cargo in a separate Xcode target as an external build system. - Imported that as a dependency of `bevy_mobile_example.app`. - Compiled a trampoline C file with Xcode that called `main_rs`. - Linked that via. Xcode. All of this is unnecessary; `rustc` is well capable of creating iOS executables, the trick is just to place it at the correct location for Xcode to understand it, namely `$TARGET_BUILD_DIR/$EXECUTABLE_PATH` (places it in `bevy_mobile_example.app/bevy_mobile_example`). Note: We might want to wait with the changes to `#[bevy_main]` until the problem is resolved on Android too, to make the migration easier. ## Testing Open the Xcode project, and build for an iOS target. --- ## Migration Guide **If you have been building your application for iOS:** Previously, the `#[bevy_main]` attribute created a `main_rs` entry point that most Xcode templates were using to run your Rust code from C. This was found to be unnecessary, as you can simply let Rust build your application as a binary, and run that directly. You have two options for dealing with this: If you've added further C code and Xcode customizations, or it makes sense for your use-case to continue link with Xcode, you can revert to the old behaviour by adding `#[no_mangle] extern "C" main_rs() { main() }` to your `main.rs`. Note that the old approach of linking a static library prevents the Rust standard library from doing runtime initialization, so certain functionality provided by `std` might be unavailable (stack overflow handlers, stdout/stderr flushing and other such functionality provided by the initialization routines). The other, preferred option is to remove your "compile" and "link" build phases, and instead replace it with a "run script" phase that invokes `cargo build --bin ...`, and moves the built binary to the Xcode path `$TARGET_BUILD_DIR/$EXECUTABLE_PATH`. An example of how to do this can be viewed at [INSERT LINK TO UPDATED EXAMPLE PROJECT]. To make the debugging experience in Xcode nicer after this, you might also want to consider either enabling `panic = "abort"` or to set a breakpoint on the `rust_panic` symbol. --------- Co-authored-by: François Mockers <mockersf@gmail.com> Co-authored-by: François Mockers <francois.mockers@vleue.com>
69 lines
1.9 KiB
Bash
Executable File
69 lines
1.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# based on https://github.com/mozilla/glean/blob/main/build-scripts/xc-universal-binary.sh
|
|
|
|
set -eux
|
|
|
|
PATH=$PATH:$HOME/.cargo/bin
|
|
|
|
PROFILE=debug
|
|
RELFLAG=
|
|
if [[ "$CONFIGURATION" != "Debug" ]]; then
|
|
PROFILE=release
|
|
RELFLAG=--release
|
|
fi
|
|
|
|
set -euvx
|
|
|
|
# add homebrew bin path, as it's the most commonly used package manager on macOS
|
|
# this is needed for cmake on apple arm processors as it's not available by default
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
|
|
# Make Cargo output cache files in Xcode's directories
|
|
export CARGO_TARGET_DIR="$DERIVED_FILE_DIR/cargo"
|
|
|
|
# Xcode places `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin`
|
|
# at the front of the path, with makes the build fail with `ld: library 'System' not found`, upstream issue:
|
|
# <https://github.com/rust-lang/rust/issues/80817>.
|
|
#
|
|
# Work around it by resetting the path, so that we use the system `cc`.
|
|
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
|
|
|
|
IS_SIMULATOR=0
|
|
if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
|
|
IS_SIMULATOR=1
|
|
fi
|
|
|
|
EXECUTABLES=
|
|
for arch in $ARCHS; do
|
|
case "$arch" in
|
|
x86_64)
|
|
if [ $IS_SIMULATOR -eq 0 ]; then
|
|
echo "Building for x86_64, but not a simulator build. What's going on?" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# Intel iOS simulator
|
|
export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
|
|
TARGET=x86_64-apple-ios
|
|
;;
|
|
|
|
arm64)
|
|
if [ $IS_SIMULATOR -eq 0 ]; then
|
|
# Hardware iOS targets
|
|
TARGET=aarch64-apple-ios
|
|
else
|
|
# M1 iOS simulator
|
|
TARGET=aarch64-apple-ios-sim
|
|
fi
|
|
esac
|
|
|
|
cargo build $RELFLAG --target $TARGET --bin bevy_mobile_example
|
|
|
|
# Collect the executables
|
|
EXECUTABLES="$EXECUTABLES $DERIVED_FILE_DIR/cargo/$TARGET/$PROFILE/bevy_mobile_example"
|
|
done
|
|
|
|
# Combine executables, and place them at the output path excepted by Xcode
|
|
lipo -create -output "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" $EXECUTABLES
|