Here’s a series that talks about integrating iOS and Rust. Some of the information is probably a little outdated - I’m going through the series now and will update any information as I verify that it works.
My big open issue with iOS right now is bitcode.
Has anyone come up with a way to output proper LLVM bitcode for iOS? With rustup it’s easy (as of 1.11) to target all iOS platforms, but I produce staticlib’s without bitcode. Trying to create a lib with bitcode inside, you end up with a non-compatible bitcode between LLVM versions.
Some people have mentioned swapping out the default Rust LLVM version for the Apple one, but I personally haven’t gotten that far.
This is my biggest concern for iOS too. I’m using Rust at work for mobile app middleware - they’ve already added bitcode as a hard requirement for iWatch, it’s probably only a matter of time until they enforce that on the phone/tablet platforms too.
I didn’t realise the Apple LLVM fork was readily available - it might be worth investigating what the diff is, though I can’t see what the base revision from the LLVM repo is. If this always has to match the live Xcode version this could be a real pain to maintain. Another problem after bitcode support is that the enforced compile options only allow 2 exception handling mechanisms - between obj-c and C++ both are used, so Rust code won’t link without
Another idea might be to transpile Rust code into C (or possibly C++ for panicking). It might be practical now that
rustc is using the MIR since most of the fancy high-level features have been baked out.
I’d love to make progress on the bitcode problem. It’s pretty crucial for our cross-platform story. But it’s also a nightmare.
It’s probably impossible for Rust to get its LLVM fork onto the same merge-base as Apple’s clang’s - it’s just not practical for us to be shackled to their whims.
I see a few paths to emitting Apple’s bitcode from rustc:
- We ship an entirely separate toolchain for targetting Apple bitcode. This is quite ugly.
- We change rustc to dynamically load LLVM, create a rust-llvm package and an optional rust-llvm-apple package, and have rustc load the apple LLVM to deal with their bitcode.
- We create a rustc_llvm_apple crate and just link two entire LLVMs into rustc at all times. This probably would not fly
- We create a build of rustc called rustc-apple and ship it in an optional rustc-apple package. It is exactly like rustc except instead of linking to rustc_llvm it links to rustc_llvm_apple. When rustc gets a request to emit bitcode it just defers completely to the rustc-apple binary. I actually fancy this solution quite a bit.
We ship an entirely separate toolchain for targetting Apple bitcode. This is quite ugly
We create a build of rustc called rustc-apple and ship it in an optional rustc-apple package. It is exactly like rustc except instead of linking to rustc_llvm it links to rustc_llvm_apple. When rustc gets a request to emit bitcode it just defers completely to the rustc-apple binary. I actually fancy this solution quite a bit.
differ? They sound very similar to me. But then again, I don’t know the internals of rustup and rustc
The difference is mostly in the packing and distribution.
The former approach would require us to either define a custom host triple to represent the architecture the compiler runs on, different from x86_64-apple-darwin, like x86_64-apple-darwin-custom, so that it has a unique tarball name and rustup can uniquely identify it; or it would require reusing the same target triple and giving it a custom installer/tarball name and making it unusable by rustup. And if you wanted to target apple bitcode from more than x86_64-apple-darwin we would need to do the same special-case thing for each.
The latter approach doesn’t require us to commandeer a host triple or create custom packaging. It rather requires updating the build system to produce another compiler and to package it as another optional component that rustup understands. It is probably more work but fits more cleanly into our existing systems.
Another way to say the difference is that the former requires creating new toolchains to target apple bitcode; the latter just requires adding new components (though those components contain entire compilers) to the existing toolchains.
Right, I think I get it.
The crazy thing is, I’m going to assume that LLVM versions from Rust will often be ahead of Apple’s. Which I would assume might mean that Apple is taking away some options to improve performance of your code. I remember thinking Apple’s decision here was cool, but as I’ve started trying to use it, I realize it’s not.