You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have an application where my initial platform was macosx but where I'm now adding multi-platform support. I'm not sure if this is yet stable enough to do a pull request into the guides, but I thought I'd put it here in case it's helpful to others. @chinedufn if you want to use any of this, please feel free to do so without any need for attribution.
My first attempt was just to bundle more targets into a single build artifact. I quickly discovered that lipo only allows a single artifact per architecture (aarch64 vs x86_64), and cannot combine multiple build targets on the same architecture. Therefor I decided to create a different artifact per target, and configure my XCode project to link to a specific file per target platform.
Note that I am using lipo from the coreutils package installed via Homebrew, and in the following snippets I'm replacing my real crate name with <rust-bridge> or <rust_bridge>.
My build-rust.sh script is as follows:
#!/usr/bin/env bash################################################### We call this from an Xcode run script.##################################################set -e
export BRIDGE_CRATE=<rust-bridge>export PATH="$HOME/.cargo/bin:$PATH:/opt/homebrew/bin"export RUST_LIB_NAME=lib<rust_bridge>export RUST_LIB="${RUST_LIB_NAME}.a"### <snipped code to ensure rustc/cargo are in the PATH>if [[ -z"${PROJECT_DIR}" ]];then
PROJECT_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}")"&> /dev/null &&pwd)echo"PROJECT_DIR: ${PROJECT_DIR}"fiif [[ -z"$CONFIGURATION" ]];then
CONFIGURATION="Debug"ficd$PROJECT_DIR/..
TARGETS=""
NIGHTLY="NO"if [[ "${PLATFORM_NAME}"="macosx" ]];then
TARGETS=(aarch64-apple-darwin x86_64-apple-darwin)
elif [[ "${PLATFORM_NAME}"="iphonesimulator" ]];then
TARGETS=(aarch64-apple-ios-sim x86_64-apple-ios)
elif [[ "${PLATFORM_NAME}"="iphoneos" ]];then
TARGETS=(aarch64-apple-ios)
elif [[ "${PLATFORM_NAME}"="appletvsimulator" ]];then
TARGETS=(aarch64-apple-tvos-sim)
NIGHTLY="YES"elif [[ "${PLATFORM_NAME}"="appletvos" ]];then
TARGETS=(aarch64-apple-tvos x86_64-apple-tvos)
NIGHTLY="YES"elif [[ "${PLATFORM_NAME}"="watchsimulator" ]];then
TARGETS=(aarch64-apple-watchos-sim)
NIGHTLY="YES"elif [[ "${PLATFORM_NAME}"="watchos" ]];then
TARGETS=(aarch64-apple-watchos)
NIGHTLY="YES"elif [[ "${PLATFORM_NAME}"="xrsimulator" ]];then
TARGETS=(aarch64-apple-visionos-sim)
NIGHTLY="YES"elif [[ "${PLATFORM_NAME}"="xros" ]];then
TARGETS=(aarch64-apple-visionos)
NIGHTLY="YES"elseecho"Unsupported platform \`${PLATFORM_NAME}\`">&2exit 1
fiecho"Rust version ($(which rustc 2>&1)): $(rustc --version 2>&1)">&2echo"Rustup version ($(which rustup 2>&1)): $(rustup --version 2>&1)">&2echo"BUILDING configuration: ${CONFIGURATION}; platform: ${PLATFORM_NAME}"## Allows x86_64 architecture in XCode Cloud to cross-compile to aarch64export SDKROOT=$(xcrun -sdk macosx --show-sdk-path)export MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)if [[ $CONFIGURATION=="Release" ]];thenif [[ "${NIGHTLY}"] = "YES" ]];thenfortargetin${TARGETS[@]};doecho"BUILDING FOR RELEASE (${target})">&2
RUSTFLAGS="$RUSTFLAGS -A dead_code" cargo +nightly build -Zbuild-std --package ${BRIDGE_CRATE} --no-default-features --release --target "${target}"doneelsefortargetin${TARGETS[@]};doecho"BUILDING FOR RELEASE (${target})">&2
cargo build --package ${BRIDGE_CRATE} --release --target "${target}"donefi
UNIVERSAL_BUILD_TARGET="./target/universal/release"declare -a COMPILED_LIBS
fortargetin"${TARGETS[@]}";do
COMPILED_LIBS+=("./target/${target}/release/${RUST_LIB}")
doneelif [[ $CONFIGURATION=="Debug" ]];thenif [[ "${NIGHTLY}"="YES" ]];thenfortargetin${TARGETS[@]};doecho"BUILDING FOR DEBUG (${target})">&2
RUSTFLAGS="$RUSTFLAGS -A dead_code" cargo +nightly build -Zbuild-std --package ${BRIDGE_CRATE} --no-default-features --target "${target}"doneelsefortargetin${TARGETS[@]};doecho"BUILDING FOR DEBUG (${target})">&2
cargo build --package ${BRIDGE_CRATE} --target "${target}"donefi
UNIVERSAL_BUILD_TARGET="./target/universal/debug"declare -a COMPILED_LIBS
fortargetin"${TARGETS[@]}";do
COMPILED_LIBS+=("./target/${target}/debug/${RUST_LIB}")
donefiecho"BUILDING UNIVERSAL TARGET"
mkdir -p "${UNIVERSAL_BUILD_TARGET}"
cat <<EOF lipo${COMPILED_LIBS[@]} -create -output "${UNIVERSAL_BUILD_TARGET}/${RUST_LIB_NAME}_${PLATFORM_NAME}.a"EOF
lipo \
${COMPILED_LIBS[@]} \
-create -output "${UNIVERSAL_BUILD_TARGET}/${RUST_LIB_NAME}_${PLATFORM_NAME}.a"
CHECKFILE="${PROJECT_DIR}/Generated/${BRIDGE_CRATE}/${BRIDGE_CRATE}.swift"if [[ !-f"${CHECKFILE}" ]];thenecho"Failed to find expected generated file after compilation, but did not!">&2echo" Expected file: ${CHECKFILE}"exit 1
fi
In my XCode project, rather than directly linking to the build product (which now includes the PLATFORM_NAME in the file name), I added a new Configuration Settings File with the following contents:
I go multiple years between having to configure linkers, so it took me a bit of fighting before I remembered that -l"name" links to libname.a, and I had to exclude lib from the ldflags.
The text was updated successfully, but these errors were encountered:
One thing I'm unclear on is the best set of targets for watchos and iphoneos. I'm only targeting the latest version of iOS, so aarch64 may be good enough. I have compiled the Rust part of my application for watchOS and visionOS, but have not started the Swift part so don't yet know if this is missing anything.
Also I have my XCode project in a swift/ subdirectory of my repository, which is why my script is changing directory. That may not be needed for others.
I have an application where my initial platform was
macosx
but where I'm now adding multi-platform support. I'm not sure if this is yet stable enough to do a pull request into the guides, but I thought I'd put it here in case it's helpful to others. @chinedufn if you want to use any of this, please feel free to do so without any need for attribution.My first attempt was just to bundle more targets into a single build artifact. I quickly discovered that
lipo
only allows a single artifact per architecture (aarch64
vsx86_64
), and cannot combine multiple build targets on the same architecture. Therefor I decided to create a different artifact per target, and configure my XCode project to link to a specific file per target platform.Note that I am using
lipo
from thecoreutils
package installed via Homebrew, and in the following snippets I'm replacing my real crate name with<rust-bridge>
or<rust_bridge>
.My
build-rust.sh
script is as follows:In my XCode project, rather than directly linking to the build product (which now includes the
PLATFORM_NAME
in the file name), I added a newConfiguration Settings File
with the following contents:I go multiple years between having to configure linkers, so it took me a bit of fighting before I remembered that
-l"name"
links tolibname.a
, and I had to excludelib
from the ldflags.The text was updated successfully, but these errors were encountered: