-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rustc and XCFramework won't work #79408
Comments
Does that mean that this issue can be closed? |
Well not really, since the ios and mac targets have two issues that I seen so far:
So to summarize: The llvm targets for ios/darwin need to specify the version (as in e.g. aarch64-apple-ios13.0) (which should probably best be set via a cargo option or env var). Further, since maccatalyst is supported, the simulator target should set its environment to simulator to prevent llvm from generating a "fat" binary. |
I also encountered this issue when trying to put together an |
You have to rebuild the standard library in order to use a custom target as mentioned in: https://doc.rust-lang.org/nightly/rustc/targets/custom.html. Write the above target-spec into a file named
I should note, however, that my resulting static library does not include the
Nonetheless, it can be inserted into an
|
If you set the version high enough, it appears you do get the newer load command:
|
Ah yes, sorry my answer was edited multiple times, so this probably did not come across. Those load commands are emitted for the newer llvm-targets automatically (XCode itself is using the same LLVM-Targets). |
@ubamrein have you been able to archive an iOS app that includes an xcframework built this way? I'm getting:
|
For our CI we use the following script (note we also had problems with the new aarch64-simulator target, so we excluded that in the build process). The script essentially checks for a valid rust installation on the CI, then builds the standard library for the new ios target, generates C-Bindings with cbindgen, and finally combines headers and static lib to a xcframework. Hopefully this helps you :)
|
@ubamrein thanks for the script, it helped me debug. I am actually doing something pretty similar to you however I'm building fat binaries with both After ruling out most of the differences between our two approaches, I narrowed the issue down to build profile.
Which seems to indicate (1.52-nightly) Rust's llvm includes attributes that Xcode's version doesn't know about yet. Using the For posterity, my script looks like:
The reason I don't have a module map is because I'm packaging this xcframework using the swift package manage, which will automatically generate one for you for binary xcframework targets (: |
@dcow I have a similar thing working with current nightlies. You just need to use Irrelevant to rust-lang/rust, but I did things a bit differently:
|
I just have different target JSON files rather than modifying a single one with
I'm able to run on the simulator using the script I posted above, that all works fine. After running
We're not using Carthage, just pure SwiftPM. I have a swift package project that includes Swift code to interface with the FFI. I build the binary xcframework using the artifacts from the crate where I've added my FFI. In the swift package I have a directory where I copy the xcframework and use it as a binary target. There is a swift target containing code to interface with the rust crate via the published FFI, which depends on the binary target. I guess my goal was to have this working in swift package manager and building via the The swift package looks like:
We do use xcode, of course, and I may try to get what you have working over in CiteprocRSKit setup for us, so thanks for the leads. I do get the impression Apple is leaning into xcframeworks for integrating binary artifacts into the swift ecosystem although I absolutely respect the aesthetic beauty of getting the build working by passing everything through via Xcode. Building for all platforms is an annoying kink in the workflow but not a showstopper for our use case and not without it's own advantages/tradeoffs. It would be cool if you could create a dynamic "script" target using swiftpm that would have access to all the appropriate env vars and just call out to cargo. The artifacts of such could be specified in the build script and then included normally in the appropriate search paths. Just wanted to provide a little rationale in response to your "why do it this way" and "never build pure rust xcframework" questions/comments. Back to rust stuff: I tested 1.55 nightly with the new Xcode 13 beta (which uses llvm 12+). I no longer have an issue building or archiving. I think that confirms the llvm version mismatch hypothesis. It's possible this scenario could happen again in the future though, so it may always be something to watch out for. And it wouldn't happen if we didn't have to use rust nightly to build xcframeworks. So the original issue still stands: building an xcframework requires rust nightly because it requires a custom target because the main rust does not use a sufficiently specified llvm target. |
During this whole debugging process, I stumbled upon https://github.com/getditto/rust-bitcode, allowing to build rust with a specific Apple llvm-backend, to allow the usage of bitcode. Since I had the compiler checked out anyways, I tested it and it seems to work with current upstream rust. |
Update from me, which is of course still off-topic for the Rust repo, but hopefully useful. Doing it the fully Xcode way finally hit a snag. My Swift code needs to re-export items from the FFI headers. Swift is generally bad at this, and if you do, it gets in the way of using module stability to make the final product work across different swift compilers than it was compiled with. There isn't an obvious way (using custom modulemaps) to bring the ffi module into scope in the .swiftinterface file. So it just says "no such module YourRustFFIModule". Works fine when the swift compiler versions match. Works fine if you don't re-export anything. Use a different Xcode with re-exports and you're in trouble. So if @dcow'a solution can do this, it would have the advantage. I suspect it can, because it seems like consumers would be able to compile your package from source and so the swiftc version mismatch is irrelevant. However I am guessing that it requires providing a download URL for the Rust xcframework to pop in the Package.swift, to avoid placing many versions of multiple large binary blobs in git. I will maybe give this a go. |
We need to use a custom target spec for the iOS simulator. More details: rust-lang/rust#79408 Since that issue, all the targets except the x86_64 simulator have been updated (one landed last night). There is a PR that updates the simulator: rust-lang/rust#87699 Once that PR is merged we can remove the `x86_64-apple-ios7.0.json` custom target spec and use the builtin.
Rust 1.55 works fine with XCode 13 (13.1), however for 1.56 Without bitcode builds fine. |
Hi
We are currently trying to build a xcframework, which includes a rust static library as a binary target. When we build the xcframework with
xcodebuild -create-xcframework -library target/aarch64-apple-ios/release/libxcframework_test.a -headers test.h -output test.xcframework
we getThe CodingKeys(stringValue: "SupportedPlatform", intValue: nil) is empty in library -arm64.
.To reproduce the failure just build a static lib with a function in it e.g.:
cargo build --release --target aarch64-apple-ios
Interestingly enough, the binary works when statically linked during the usual build process in XCode (so the code itself seems to be correct).
Further, for the darwin binary (target macos) the xcframework creation process succeeds.
I think with rustc 1.43 the xcframework also worked for the ios platform, but other than that we have no idea what is wrong.
It is though certainly somehow linked to rust, as C/C++ libraries work (e.g. libsodium) with exact the same command/folder-structure.
[EDIT] We found that LC_VERSION_MIN_* is emitted instead of LC_BUILD_VERSION in the load commands of the MachO binary. Apparently this is the newly used command to specify the platform.
As a comparison:
XCODE:
RUST:
[EDIT 2]
Getting closer found #29664 and made a new target, where I set the llvm-target to the one with the correct version like this:
Now I can create an xcframework again!
The text was updated successfully, but these errors were encountered: