Skip to content
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

Support Apple app store bitcode #35968

Open
brson opened this Issue Aug 24, 2016 · 84 comments

Comments

Projects
None yet
@brson
Copy link
Contributor

brson commented Aug 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:

  • 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 could investigate a bitcode sanitizer to translate our bitcode to theirs. I think the likelihood of success here is low because maintenance. I believe RenderScript does this.

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

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Aug 24, 2016

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.

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 --llvm-root already does).

We create a rustc_llvm_apple crate and just link two entire LLVMs into rustc at all times. This probably would not fly

Just link the system LLVM (statically) for apple distributions. In my experience it already works kinda well.

We could investigate a bitcode sanitizer to translate our bitcode to theirs. I think the likelihood of success here is low because maintenance. I believe RenderScript does this.

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?

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Aug 24, 2016

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.

@bluejekyll

This comment has been minimized.

Copy link

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.

@sanxiyn

This comment has been minimized.

Copy link
Member

sanxiyn commented Aug 24, 2016

It would be useful to have exact error message from llvm-link.

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Aug 24, 2016

@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.

@ricky26

This comment has been minimized.

Copy link
Contributor

ricky26 commented Aug 24, 2016

Just link the system LLVM (statically) for apple distributions. In my experience it already works kinda well.

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’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.

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. panic=abort is strictly required at the moment.)

@bluejekyll

This comment has been minimized.

Copy link

bluejekyll commented Aug 24, 2016

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.

@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.

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Aug 24, 2016

@ricky26 good points.

as far as I'm aware, the only blessed apple-llvm version for App Store uploads is the one shipped with the current Xcode.

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.

This also potentially means maintaining the LLVM bindings for two LLVM versions

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.

@brson

This comment has been minimized.

Copy link
Contributor Author

brson commented Aug 24, 2016

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 --llvm-root already does).

@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.

Just link the system LLVM (statically) for apple distributions. In my experience it already works kinda well.

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.

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)?

The bitcode format is not stable between versions.

does distributing native binary libraries not work anymore for iOS?

It does work today. It is not the preferred method and it's not obvious it will continue to be supported.

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.

@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.

@bluejekyll

This comment has been minimized.

Copy link

bluejekyll commented Aug 24, 2016

As long as Xcode’s LLVM is not some ancient version, I think we’re good in that regard.

From this page https://gist.github.com/yamaya/2924292:

clang-700.0.72 => LLVM 3.7.0
clang-700.1.76 => LLVM 3.7.0
clang-700.1.81 => LLVM 3.7.0
clang-703.0.29 => LLVM 3.8.0
clang-703.0.31 => LLVM 3.8.0
@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Aug 25, 2016

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.

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.

precludes the option of supporting iOS bitcode on non-apple hosts.

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.

The bitcode format is not stable between versions.

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.

@comex

This comment has been minimized.

Copy link
Contributor

comex commented Aug 25, 2016

Some notes:

  • Xcode doesn't even ship with a linkable libLLVM (static or dynamic), only a libclang.dylib which statically links to LLVM.
  • Apple does ship the source to their 'clang' (including LLVM) under 'Developer Tools' on https://opensource.apple.com, but that site tends to take forever to be updated.
  • The story may be better with Swift, which has its own fork of LLVM with release tags - but they may not correspond perfectly to what's shipped with Xcode. (It's possible to use open-source toolchain snapshots with Xcode, but projects built with such toolchains can't be submitted to the App Store.)
@aturon

This comment has been minimized.

Copy link
Member

aturon commented Aug 26, 2016

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Aug 27, 2016

Would be curious to hear how other programming languages plan on dealing with this. In particular mono and go.

@ricky26

This comment has been minimized.

Copy link
Contributor

ricky26 commented Aug 27, 2016

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.

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Aug 27, 2016

Mono proper goes via apple LLVM it would appear: http://tirania.org/blog/archive/2015/Sep-02.html

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Aug 27, 2016

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

@comex

This comment has been minimized.

Copy link
Contributor

comex commented Aug 27, 2016

@mitsuhiko You can have inline assembly in bitcode on iOS and tvOS, but not watchOS, for some reason.

@russellmcc

This comment has been minimized.

Copy link
Contributor

russellmcc commented Dec 29, 2016

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.

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.)

This approach (by @ricky26) seems to be the most natural to me as a rustc user.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Dec 29, 2016

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.

@adrianbrink

This comment has been minimized.

Copy link

adrianbrink commented Feb 25, 2017

Are there any updates on this?

@samkhawase

This comment has been minimized.

Copy link

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!

https://news.ycombinator.com/item?id=14305084

@comex

This comment has been minimized.

Copy link
Contributor

comex commented May 10, 2017

As the commenter in question, quick notes:

  • I used -C lto --emit llvm-bc to get rustc to emit one .bc file containing the current crate and all dependencies. This works, but is essentially a hack; in particular, it doesn't work for C dependencies, including jemalloc (though that isn't used on iOS anyway). It would be better if rustc properly supported emitting Mach-Os with "embedded bitcode"; you can look at the clang source to see how it's done.

  • If you want to try it and don't mind the hack, it does seem to 'just work', except for the version issue:

  • The main practical obstacle is that Rust syncs with LLVM trunk more frequently than Xcode, which seems to only do so yearly. Newer LLVM versions can load old bitcode, but not the other way around, so you have to either use an old version of rustc or build the latest against an old LLVM. (Actually, rustc 1.17 seems to still work with Xcode 8.x, but not nightly since the LLVM 4.0 upgrade; that's just coincidence though.)

  • Ideally Rust would ship official binaries built against a suitable LLVM version. In practice, it seems to be fine to use the correct version of stock LLVM, but if you do want to use Apple's fork:

    • As I said in a previous comment, Xcode doesn't ship LLVM binaries in any linkable form, even dynamically; only clang and libclang.dylib (which exports the Clang API but not the LLVM one).
    • But, as I also said, the source code usually goes up on opensource.apple.com (under Developer Tools -> clang; the archive includes all of LLVM), just somewhat inconsistently/after a delay. However, especially given the expanded backwards compatibility guarantees noted by @alexcrichton, it may not be the end of the world to not always be up to date. Currently, the most recent source release is for Xcode 8.2.1, whereas the latest is 8.3.2.
@mpiannucci

This comment has been minimized.

Copy link

mpiannucci commented Dec 27, 2018

Has anyone tried this recently? It looks like armv7 is the biggest issue?

@TimNN TimNN referenced this issue Jan 2, 2019

Open

bitcode support #26

@jlouazel

This comment has been minimized.

Copy link

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?
Thanks!

@appaquet

This comment has been minimized.

Copy link

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 @llvm.memcpy, @llvm.memmove, and @llvm.memset, and Xcode build error was clear about the wrong argument type as seen in my previous comment.

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 nightly-2018-06-01-x86_64-apple-darwin, and success, it compiles !

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...

@chrisballinger

This comment has been minimized.

Copy link

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.

@jlouazel

This comment has been minimized.

Copy link

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

@oleksandr-yefremov

This comment has been minimized.

Copy link

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.
Rust and Kotlin/Native are both aiming for this niche, have decent tooling, produce native binary (performance and footprint!). Bitcode is a big problem for those who want to adopt Rust as a language for building multiplatform modules on mobile platforms. And now Kotlin/Native has an advantage.

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.

Now I guess we just have to rely on Apple to do the right thing

Yeah, right, this is what Apple is notorious for ;)
I don't know what would be the best solution (temporarily downgrading to LLVM 6 is not option, right?), but Rust is losing iOS and mobile crossplatform developers completely.

@jlouazel

This comment has been minimized.

Copy link

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:

Xcode 8.3  --> swift 3.1 --> llvm 4.0.0
Xcode 9.0  --> swift 4.0 --> llvm 4.0.0
Xcode 9.3  --> swift 4.1 --> llvm 5.0.2
Xcode 10.0 --> swift 4.2 --> llvm 6.0.1

While looking at the swift-5.0-branch, I noticed the declared version of LLVM in it is 7.0.0: https://github.com/apple/swift-llvm/blob/swift-5.0-branch/CMakeLists.txt#L25-L33

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 🎉

@vincentisambart

This comment has been minimized.

Copy link

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
You would definitely need people stepping in when an issue is created to update the required version of LLVM (the one for LLVM 6: #55842).

@mati865

This comment has been minimized.

Copy link
Contributor

mati865 commented Feb 21, 2019

@vincentisambart Rust has been already using LLVM 8 for nightly builds for 5 months IIRC.
LLVM 6 is minimal supported version if you want to build it yourself and it's tested on CI: https://github.com/rust-lang/rust/blob/706e67b0a0143d651eb03f2fa2c30645899e81ff/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile

@alper

This comment has been minimized.

Copy link

alper commented Feb 21, 2019

Now I guess we just have to rely on Apple to do the right thing

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:

  • Swift wants to be Rust in a bunch of ways (see the ownership manifesto for one) but is lagging behind a lot
  • Apple needs Swift to be and remain their main platform language so it does not make sense for them to facilitate another big language on their platform nor for them to push Swift into other environments
@vincentisambart

This comment has been minimized.

Copy link

vincentisambart commented Feb 21, 2019

Rust has been already using LLVM 8 for nightly builds for 5 months IIRC.

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.

LLVM 6 is minimal supported version if you want to build it yourself and it's tested on CI

Then having the official *-apple-ios builds of Rust be built with LLVM 6 (or better something like https://github.com/apple/swift-llvm/releases/tag/swift-4.2.2-RELEASE – if that works) might fix the bitcode problems.

@sercand

This comment has been minimized.

Copy link

sercand commented Feb 21, 2019

I think Rust currently ships with two LLVM backends (Emscripten and standard) after merging of #46819.
Although #46819 mentions ios LLVM backend for bitcode it did not implemented.

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Feb 21, 2019

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.

@jlouazel

This comment has been minimized.

Copy link

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.

@iragsdale

This comment has been minimized.

Copy link

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.

@mpiannucci

This comment has been minimized.

Copy link

mpiannucci commented Feb 21, 2019

Even if bitcode worked, Rust still can't target watchOS or tvOS anyways can it?

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Feb 21, 2019

It's unlikely that Rust will be able to stay up to date with the bitcode requirements from Apple's side.

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.

@Pacoup

This comment has been minimized.

Copy link

Pacoup commented Feb 21, 2019

How feasible is it for rustc to support multiple LLVMs?

Related: Support tvOS and watchOS (and simulator) targets

@CryZe

This comment has been minimized.

Copy link
Contributor

CryZe commented Feb 21, 2019

It already uses multiple LLVMs. For the emscripten targets it uses emscripten's LLVM fork that is on LLVM 6 atm.

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Feb 21, 2019

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.

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.

@iragsdale

This comment has been minimized.

Copy link

iragsdale commented Feb 21, 2019

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.

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.

@mitsuhiko

This comment has been minimized.

Copy link
Contributor

mitsuhiko commented Feb 21, 2019

I wouldn't say this is particularly hard to plan for.

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.

@iragsdale

This comment has been minimized.

Copy link

iragsdale commented Feb 21, 2019

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.

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.

@sercand

This comment has been minimized.

Copy link

sercand commented Feb 22, 2019

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.

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.

@appaquet

This comment has been minimized.

Copy link

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.

@Pacoup

This comment has been minimized.

Copy link

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:

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

Or maybe bitcode will stabilize in the future and we'll all forget this debate ever happened 🙏

@Pacoup

This comment has been minimized.

Copy link

Pacoup commented Feb 22, 2019

I will eat my hat now 😞

In which I said:

the idea that Apple is gonna close source LLVM or their bitcode format is very unlikely

Which was mostly in response to the distrust expressed by @mitsuhiko:

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.

But if you look at issue #48833, there is definitely a precedent. As @comex previously wrote:

there have been cases where features show up in Xcode's LLVM before LLVM trunk - such as the entire arm64 port, when it was originally developed, because Apple wanted to keep it secret that they were planning to ship arm64 devices

And @michaeleiselsc's story from the same issue:

an app I was working on got hit hard by random restarts in December 2016, and it's caused by a specific issue that open-source LLVM only fixed December 2017. When we moved from open-source LLVM to Apple's LLVM in December 2016, the problem was fixed

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 😢. It's not a risk all projects can shoulder. Transpiling does sound like a better option at this point, but so far, it doesn't sound all that possible.

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).

@tmm1

This comment has been minimized.

Copy link

tmm1 commented Mar 19, 2019

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)

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.