Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSupport Apple app store bitcode #35968
Comments
brson
added
A-LLVM
A-build
E-hard
C-enhancement
O-ios
T-tools
T-compiler
labels
Aug 24, 2016
This comment has been minimized.
This comment has been minimized.
Dynamically loading LLVM is certainly not an option. The LLVM API is less stable than its bitcode and, if we build against LLVM x.y, then having LLVM x.z instead of x.y will almost certainly break rustc. Just link to the system LLVM statically (like
Just link the system LLVM (statically) for apple distributions. In my experience it already works kinda well.
Okay… so, the thing is that LLVM bitcode format is kinda stable between versions of LLVM. Does apple do something unusual to make that not true, or is the bitcode format used not LLVM altogether (i.e. has apple specific stuff)? I feel like I heard all the way back in 2013-ish that using LLVM bitcode as distribution format is stupid. I certainly agree; does distributing native binary libraries not work anymore for iOS? |
This comment has been minimized.
This comment has been minimized.
|
I’m also very interested in what would happen when Apple upgrades to LLVM version with incompatible bitcode format internally and people still compile stuff with old compilers. |
This comment has been minimized.
This comment has been minimized.
bluejekyll
commented
Aug 24, 2016
|
I experimented briefly with this, i.e. output bitcode during cargo builds, then tried to create a static library with the bitcode included. When I tried to llvm-link against the bitcode library, I got an incompatible LLVM version from the bitcode. I don't have an easy test to reproduce this, but my guess is there is just a dumb version check that denies linking between different LLVM versions? Or, I just did something entirely wrong. I will try to come up with a test case when I have some time to look at this again. |
This comment has been minimized.
This comment has been minimized.
|
It would be useful to have exact error message from llvm-link. |
This comment has been minimized.
This comment has been minimized.
|
@bluejekyll LLVM has a number of bitcode files in its test directory. Tests against these bitcode files are run continuously (llvm-dis-3.8/opt-3.8 understands a 3 year old bitcode file from 3.2 just fine, for example), so it must be some apple stuff. |
This comment has been minimized.
This comment has been minimized.
This is somewhat easier said than done - as far as I'm aware, the only blessed apple-llvm version for App Store uploads is the one shipped with the current Xcode. This also potentially means maintaining the LLVM bindings for two LLVM versions (not necessarily two neighbouring minor versions, either). I don't think it's valid to just use an old version of apple-llvm.
I think they avoid this by only allowing the latest Xcode to submit apps (and I'm pretty sure it's burned into the output image which LLVM version you used). IIRC, the bitcode is packaged for each architecture, since cross-architecture bitcode isn't generated by clang (I think that's an anti-goal of clang and bitcode in general). It's stored in a section for each object file so at the very least it's duplicated. That could be part of why someone mentioned that bitcode might not be the best way of going about this. I feel a bit like all of the recommended solutions are somewhat icky. The least messy way I can think of is to allow different targets to overload the codegen behaviour and have the Apple codegen path be in a dynamic crate. (Which would just be the regular codegen path compiled against apple-llvm.) Since this bug mentions the App Store, is it worth talking about the exception handling story here? (i.e. |
This comment has been minimized.
This comment has been minimized.
bluejekyll
commented
Aug 24, 2016
@nagisa thanks for letting me know this. It gives me hope that there might still be a solution here, and that I was probably doing something wrong. |
This comment has been minimized.
This comment has been minimized.
|
@ricky26 good points.
Isn’t Xcode LLVM on apple the same thing as system LLVM? I meant the Xcode LLVM then. We would have to make sure xcode is always the most recent version when shipping rustc trains. Of course the way apple does things rules out us producing a valid apple bitcode with an old version of rustc and essentially forces us throw all the benefits our stability story provides out the window, and I don’t see any way this could be fixed.
We already maintain¹ support for LLVM versions 3.7 through 3.9 (and potentially trunk). As long as Xcode’s LLVM is not some ancient version, I think we’re good in that regard. If Xcode LLVM is really some ancient/custom/etc version, then I don’t see us being able to support this feature at all, then. Especially since we have no option of sending patches to that LLVM in order to add the features we need. I also wouldn’t want to lock rustc into supporting 3.7 forever in case Apple decided to not update Xcode LLVM until 2038. ¹: however, if rustc was built against LLVM x.y, it must be linked to LLVM x.y exactly. |
This comment has been minimized.
This comment has been minimized.
@nagisa The C++ API is unstable, but we use the C API and have had a lot of success supporting multiple versions of LLVM at once. I don't see the difference in terms of API support.
We could just blanket ship Apple's LLVM for all apple platforms, but this means coupling our LLVM to Apples for even desktop machine code generation, and precludes the option of supporting iOS bitcode on non-apple hosts.
The bitcode format is not stable between versions.
It does work today. It is not the preferred method and it's not obvious it will continue to be supported.
@ricky26 We successfully maintain compatibility between several versions of LLVM. As long as Apple's and ours don't drift too far apart it should be doable, but there's always the risk of such great breakage that the divide can't be crossed, and I know there are major API changes coming. |
This comment has been minimized.
This comment has been minimized.
bluejekyll
commented
Aug 24, 2016
From this page https://gist.github.com/yamaya/2924292:
|
This comment has been minimized.
This comment has been minimized.
That is not true. We have (quite large!) a number of bindings to C++ APIs in form of rustllvm. There’s a number of cases where we compile that wrapper depending on the version of LLVM compiled against. In case version of LLVM used and compiled against does not match, you’ll get dynamic linker errors, or worse, run into issues at runtime.
If Apple does not want to take bitcode generated by anything else than their fork of LLVM, then I don’t see how we could do anything here short of maintaining a similar fork and reverse-engineering their internal patches.
Sure, but it is quite fair to assume¹ that bitcode between various revisions of LLVM known as 3.7.0, for example, is sufficiently compatible for purposes of generating bitcode for consumption by another build of LLVM from 3.7.0 series. Its certainly better than linking to libLLVM dynamically. ¹: especially given that bitcode from 3.2 series is still compatible with 3.8 LLVM, even if its a very small specimen. |
This comment has been minimized.
This comment has been minimized.
|
Some notes:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Would be curious to hear how other programming languages plan on dealing with this. In particular mono and go. |
This comment has been minimized.
This comment has been minimized.
|
Unity's answer to this problem is il2cpp - building all of their IL assemblies into C++ code. Relevant golang bug: golang/go#12682; the suggestion there seems to be that they could use the LLVM go toolchain (which isn't as featured as the standard go toolchain). All in all, the story for bitcode support outside of Apple is poor. |
This comment has been minimized.
This comment has been minimized.
|
Mono proper goes via apple LLVM it would appear: http://tirania.org/blog/archive/2015/Sep-02.html |
This comment has been minimized.
This comment has been minimized.
|
One stumbling block will be that you cannot carry inline assembly in bitcode :( For the mono story I had a quick exchange with Miguel de Icaza about what Mono does for the curious: https://twitter.com/mitsuhiko/status/769458873237434368 |
This comment has been minimized.
This comment has been minimized.
|
@mitsuhiko You can have inline assembly in bitcode on iOS and tvOS, but not watchOS, for some reason. |
This comment has been minimized.
This comment has been minimized.
|
Any movement on this? I don't feel at all good about using Rust on iOS without a plan for supporting bitcode. Apple has a history of making optional things like this non-optional fairly suddenly, and indeed bitcode is already required on watchOS and tvOS.
This approach (by @ricky26) seems to be the most natural to me as a rustc user. |
This comment has been minimized.
This comment has been minimized.
|
I don't believe anything has changed on this recently to my knowledge at least. With LLVM's recent announcement about versioning they indicated that bitcode should (I think) always be loadable by future versions of LLVM. That may mean that this issue is "solved" on a fundamental level, but it'd still require a more ergonomic interface to extract all the bitcode. |
This comment has been minimized.
This comment has been minimized.
adrianbrink
commented
Feb 25, 2017
|
Are there any updates on this? |
This comment has been minimized.
This comment has been minimized.
samkhawase
commented
May 10, 2017
|
This commenter on HackerNews has succeeded in using Bitcode generated from Rust on macOS and iOS. The thread has some detailed information on how to enable bitcode for rust binaries, which sounds like a great news! |
This comment has been minimized.
This comment has been minimized.
|
As the commenter in question, quick notes:
|
This comment has been minimized.
This comment has been minimized.
mpiannucci
commented
Dec 27, 2018
|
Has anyone tried this recently? It looks like armv7 is the biggest issue? |
This comment has been minimized.
This comment has been minimized.
jlouazel
commented
Feb 17, 2019
|
Hi everyone. I have been following this thread for a while now and I am very excited to see the Apple bitcode being supported with Rust. Has anyone been able so far to make this work? What is currently missing and how could we help? |
This comment has been minimized.
This comment has been minimized.
appaquet
commented
Feb 19, 2019
|
After a few hours of hunting down this issue, I found the reason Rust's bitcode embedding is not working in Xcode. The short answer is that Xcode's LLVM version is expecting LLVM 6.0 bitcode, while Rust has bumped to LLVM 7.0 in July 2018. Now, the long answer... As we can see in LLVM 7.0's changelog, they changed signatures for By the way, Kotlin Native added support for embed-bitcode in October 2018 and is apparently working fine in Xcode. The reason is that Kotlin still uses LLVM 6.0. Seeing that, I tried to compile using an older version of Rust before the bump to 7.0. I tried with I also tried to compile without using Xargo with no success. All dependencies need to be compiled with bitcode embedding. So bottom line, unless Apple bumps their LLVM version, I don't think we'll see support for embedded bitcode anytime soon... Unless someone finds a clever way to convert embedded bitcode to 6.0's bitcode... |
This comment has been minimized.
This comment has been minimized.
chrisballinger
commented
Feb 19, 2019
|
@appaquet Thank you for getting to the bottom of it! It was quite the mystery for me and I don't think I ever was going to dive as deep as you did. Good to know that it should likely start working once Apple bumps the LLVM version. |
This comment has been minimized.
This comment has been minimized.
jlouazel
commented
Feb 20, 2019
|
Thanks @appaquet for your clear answer. Now I guess we just have to rely on Apple to do the right thing |
This comment has been minimized.
This comment has been minimized.
oleksandr-yefremov
commented
Feb 20, 2019
|
Sideview from somebody who has interest in multiplatform for mobile and compared most of the promising solutions (React Native, Flutter, Kotlin/Native, Rust) React Native. Supports bitcode from inception, because essentially bridge is written in C++ and is just interpreting JS code in runtime. Flutter. Does not support bitcode yet - flutter/flutter#15288 Kotlin/Native. JetBrains is considering mobile platforms as a priority and although it took them a while and it's only bitcode markers (not full bitcode yet), it's good enough to start working with - see JetBrains/kotlin-native#1564 and JetBrains/kotlin-native#1202 (comment) Rust. Supports bitcode for LLVM 7, whereas Apple uses version 6. If I want to have both business logic and UI crossplatform, then I would go with React Native or Flutter. But for many, many serious apps this path is too risky. React Native is not performant enough and API and dependency stability is an issue (is v1.0 ever gonna come?). Flutter is a bit immature but seems to gain more and more traction. Now if I want to share only business logic in some kind of modules (like earlier big apps did with C++ and JNI/Obj-C++) and then build truly native UI on top, in the beginning I have a choice between all four. Then I cross out React Native, because taking full blown JavaScriptCore and bridge to run business logic between JS<->Native seems a bit over the top (initializing this bridge is quite expensive, too). Flutter potentially can be used but is not intended that way, so again I'd end up using UI framework for running business logic. Plus it does not support bitcode. To sum up why bitcode is very important for iOS devs. Can't write anything on tvOS or watchOS. Many 3rd party frameworks which are distributed as binaries have bitcode enabled (dozens of examples, from the top of my head Google IMA - most popular video advertisement). Some security audits require it. And finally, whenever Apple says "starting next year we don't accept apps without fully embedded bitcode anymore", everybody gets a ticking timer.
Yeah, right, this is what Apple is notorious for ;) |
This comment has been minimized.
This comment has been minimized.
jlouazel
commented
Feb 21, 2019
•
|
Thanks you so much for this detailed explanation @oleksandr-yefremov. I've been reading a bit on the subject and I found this interesting comment: https://gist.github.com/yamaya/2924292#gistcomment-2738480 The version of LLVM is tied to the version of Swift used in XCode. So far the following support was applied:
While looking at the I don't know if there are further blockers here, but it seems to me we might be able to use Rust to output Bitcode binaries |
This comment has been minimized.
This comment has been minimized.
vincentisambart
commented
Feb 21, 2019
|
It seems Xcode 10.2 will include Swift 5.0 and should be indeed be released pretty soon. But on the other hand LLVM 8.0 is scheduled to be released next week. Rust will pretty likely upgrade before Apple starts using it. For Rust to properly support bitcode, we would need the Apple ARM architectures builds of Rust to use a pinned version of LLVM (maybe from the https://github.com/apple/swift-llvm repo – Apple doesn't seem use the released LLVM package but their own branches). That version of LLVM would only be updated when Apple releases a new final version of Xcode with a different LLVM version. Btw, it seems the latest Rust is buildable with LLVM 6 so that definitely seem doable: https://github.com/rust-lang/rust/blob/master/src/bootstrap/native.rs#L282 |
This comment has been minimized.
This comment has been minimized.
|
@vincentisambart Rust has been already using LLVM 8 for nightly builds for 5 months IIRC. |
This comment has been minimized.
This comment has been minimized.
alper
commented
Feb 21, 2019
I've been chasing something along these lines for a while (and have now exited) and I'm guessing platform-wise it does not make sense for Apple to do this, because:
|
This comment has been minimized.
This comment has been minimized.
vincentisambart
commented
Feb 21, 2019
•
Then even if Apple starts supporting LLVM 7 bitcode, the bitcode generated by recent official builds of Rust might not work. Even if it does, it might break the next time Rust moves to a version of LLVM with an incompatible change in the generated bitcode.
Then having the official |
This comment has been minimized.
This comment has been minimized.
sercand
commented
Feb 21, 2019
This comment has been minimized.
This comment has been minimized.
|
Not to derail this entirely but wouldn't it overall make more sense to try to enable transpiling to C for such cases? It's unlikely that Rust will be able to stay up to date with the bitcode requirements from Apple's side. |
This comment has been minimized.
This comment has been minimized.
jlouazel
commented
Feb 21, 2019
|
Even if there are indeed potential sources of incompatibilities, it opens the door for tests where we could try to compile with a compatible older version of Rust, one that embeds the right LLVM version for Apple. In a complete cross-platform approach, this is still quite blocking obviously as we would need to be able to compile the same source code both from the latest version of Rust to benefit from the latest improvements and also to be able to compile from an older version of Rust, specifically to output bitcode compatible binaries for the Apple ecosystem. That's doable, but not suitable. I'm still pretty excited to see this happening as it will at least open the doors for more people to test this and push us all forward in the right direction. |
This comment has been minimized.
This comment has been minimized.
iragsdale
commented
Feb 21, 2019
|
Speaking as someone who is right now trying to decide on an approach for writing cross-platform mobile code for a fairly large team, we literally cannot use Rust if we can't generate bitcode. One of our apps relies on bitcode to be able to generate a small enough binary to download over cell networks, and we have some large customers that insist on that. Based on everything I see about Rust I think it has the most long-term upside of any of the possibilities I see out there (Kotlin Multiplatform, cross-compiling Swift, Mono, Dart, C++, React Native), but would definitely need bitcode to be fully supported, even if that meant not being able to keep up with the latest Rust releases. |
This comment has been minimized.
This comment has been minimized.
mpiannucci
commented
Feb 21, 2019
|
Even if bitcode worked, Rust still can't target watchOS or tvOS anyways can it? |
This comment has been minimized.
This comment has been minimized.
The problem here is that Rust's LLVM is too new, not that it is too old. I agree that we should have a better compatibility story here. |
This comment has been minimized.
This comment has been minimized.
Pacoup
commented
Feb 21, 2019
|
How feasible is it for rustc to support multiple LLVMs? |
This comment has been minimized.
This comment has been minimized.
|
It already uses multiple LLVMs. For the emscripten targets it uses emscripten's LLVM fork that is on LLVM 6 atm. |
This comment has been minimized.
This comment has been minimized.
The issue is not that it's too old or too new but that even if rust matches the LLVM version, at any iOS release this can break again. Apple (as far as I know) does not in any way guarantee any stability with regards to bitcode. |
This comment has been minimized.
This comment has been minimized.
iragsdale
commented
Feb 21, 2019
In practice we see major Xcode updates once a year when new iOS versions come out. When this stuff happens developers get a pretty clear heads up that they have to start submitting apps with a newer version of Xcode, so it is rarely surprising. I wouldn't say this is particularly hard to plan for. |
This comment has been minimized.
This comment has been minimized.
Since there is absolutely no guarantee around bitcode at all that could turn into something very hard to plan for. Imagine they would decide from one release to another to use their own bitcode format that does not end up in an open source release of LLVM. |
This comment has been minimized.
This comment has been minimized.
iragsdale
commented
Feb 21, 2019
If we're just going to assume Apple is going to make breaking changes without regard to anyone else, sure. Having some more clear documentation around their plans for Bitcode doesn't improve that much if we assume that they are malicious or just plain don't care. But they have clearly made Swift an important part of their platform and many thousands of developers depend on it, including their own teams and some of their most important partners. Swift is based on the fully open source LLVM and is itself being developed fully in the open, including the toolchain that Xcode uses to generate the bitcode apple accepts. So, for them to just suddenly change that format without anybody noticing or caring would require them to take both their Swift and LLVM repositories private, right? It is certainly possible, but it doesn't seem super likely to me. If the Rust team decides that the risk of that is a good reason not to support bitcode, that's certainly their prerogative. I'd be a bit sad about that, but it's not my place to tell others where to spend their time. |
This comment has been minimized.
This comment has been minimized.
sercand
commented
Feb 22, 2019
Apple releases Xcode Beta around the beginning of June and the final version in September. After 6-9 months later it stops accepting apps build with older Xcode versions to Appstore. I think there is enough time to prepare bitcode changes during that timeline. |
This comment has been minimized.
This comment has been minimized.
appaquet
commented
Feb 22, 2019
|
Just tested with Xcode 10.2 beta 3 (which includes Swift 5 w/ LLVM 7) and I could link with a Rust recent nightly with embedded bitcode. Obviously, this only works with iOS targets, since Rust doesn't have watchOS/tvOS targets. I also agree that Rust needs to be able to use Apple LLVM fork for all Apple related targets in order to maintain bitcode compatibility. |
This comment has been minimized.
This comment has been minimized.
Pacoup
commented
Feb 22, 2019
|
Yeah, the beta release window sounds reasonable. I think the idea that Apple is gonna close source LLVM or their bitcode format is very unlikely, but Apple requiring bitcode in future iOS releases definitely sounds like it will happen. And who knows, maybe they'll even start requiring bitcode for Mac App Store submissions with project Marzipan. The kind of non-guaranteed way of dealing with compatibility being proposed is admittedly icky, but I think mobile platforms should eventually become Tier 1 platforms, especially for cases where you would have used C++ otherwise, like for video game development. Plus, you could also develop games with Rust for the Apple TV. I'm hoping an officially sanctioned approach by the Compiler team would encourage someone to work on this, but I think an earlier comment by @brson sums up the hesitation:
Or maybe bitcode will stabilize in the future and we'll all forget this debate ever happened |
This comment has been minimized.
This comment has been minimized.
Pacoup
commented
Feb 22, 2019
|
I will eat my hat now In which I said:
Which was mostly in response to the distrust expressed by @mitsuhiko:
But if you look at issue #48833, there is definitely a precedent. As @comex previously wrote:
And @michaeleiselsc's story from the same issue:
Given that the idea is using Apple's LLVM with Rust, it doesn't sound that bad, but there is definitely a risk of having the occasional nasty bug because of diverging implementations I still think using Apple's LLVM should be supported, but there should be clear warnings in the documentation explaining there are no guarantees things will keep working (A Tier 1.5 or something). |
appaquet
referenced this issue
Mar 1, 2019
Open
Support tvOS and watchOS (and simulator) targets #48862
This comment has been minimized.
This comment has been minimized.
tmm1
commented
Mar 19, 2019
Thanks for pointing this out @oleksandr-yefremov! I dug in a bit further and was able to replicate the kotlin/native approach in golang. I believe you folks should be able to do the same, which would allow for using rust in bitcode-enabled iOS/tvOS/watchOS apps without necessarily emitting bitcode. |
brson commentedAug 24, 2016
Bitcode is the future of Apple's app distribution and we don't support it now. Doing so is tricky because Apple choses whatever rev of LLVM they want and upgrade it per their whims. We can't couple our LLVM to theirs because we have our own needs and can't be forced to upgrade whenever Apple decides.
Here are some options:
I think the LLVM dynamic loading and defer-to-alternate-rustc solutions are most promising.
cc https://users.rust-lang.org/t/ios-rust-integration/6928/4
cc @bluejekyll