Hacker News new | past | comments | ask | show | jobs | submit login
Running Swift code on Android (goyet.com)
196 points by Ecco on Oct 14, 2015 | hide | past | favorite | 69 comments

A coworker showed me this project, which does the same but also includes .NET and regular Java: http://elementscompiler.com/elements/silver/

Looking at their github, they appear to be making progress against re-implementing the Swift core library by binding to native classes with similar functionality. Like Arrays: https://github.com/remobjects/SwiftBaseLibrary/blob/master/S...

Wow, going after Xamarin (prioritizing iPhone developers instead of Microsofties) and only asking for donations!

This is a great find; thanks for the link.

Let's not forget RoboVM, which is free (with paid options): https://robovm.com/

I've used this before and was amazed how well it worked, particularly with libgdx: https://libgdx.badlogicgames.com/

Not affiliated with either, by the way.

Have you by any chance used JavaFXPorts? http://docs.gluonhq.com/javafxports/

No I haven't I'm afraid. But it's definitely something to look at from the RoboVM world. Bit overloaded with work at the moment unfortunately.

And just the use of the words JavaFX and iOS in the same sentence seems weird! More than happy to be proved wrong though....

RoboVM is only free for the 30 days trial.

They've changed that very recently then. It used to be free but you just didn't get interface builder support.

The other language front-ends (C# and Oxygene, their Pascal-based language) are commercial products. IMO, making the Swift front-end free indefinitely wasn't a smart business move, because now any savvy developer will just use the Swift front-end and not have to pay anything.

They could do what Qt does and charge for commercial addons. The Qt ones are pretty compelling: in-app purchases, for example.

Plus I imagine that people using the other front ends are doing it for other reasons. C# and Pascal seem like enterprise moves (for the enterprises of >2005 and <2005).

This is not going after xamarin, it's just a toy problem.

What makes the Elements compiler just a toy in your opinion?

The biggest limitation I saw was no support for the .NET base class libraries at all, which not only makes for some strange looking C# but also rules out using any of the existing 3rd party .NET libraries out there. They market this as an advantage but I'm not convinced.

What he demonstrated is basic cross compilation techniques. There is nothing new or novel about this. You are hardly going to be able to build a full future app with exclusive Swift for the android using that method without a lot of tears, sweat, blood and effort.

Have you thought about extracting the XAR archive of LLVM bitcode from Xcode 7.0+'s libswiftCore.dylib's __LLVM,__bundle section and linking your NDK project against that? You'll probably quickly run into linking dependencies outside of libswiftCore but perhaps you could A) stub out those missing dependencies B) build them from opensource.apple.com's CF, libobjc, etc projects or C) try and extract the __LLVM,__bundle's of the dependencies themselves. Rinse and repeat until everything works? :)

That's a very smart idea! I might give this a try, thanks :)

I'm excited to see what happens in the Linux and BSD space when they finally open source Swift. I hope it finds an audience excited enough to help reimplement some of the functionality that will be missing from the lack of Apple APIs.

It would be great to see an open source ecosystem for Swift, written in Swift on all *nix platforms.

Honestly the desktop Linux (and BSD) world is rather better served by fun new language technologies than iOS or Android is. In an environment already targetted by Go and Rust and C++14 and Haskell and Erlang and Clojure and Scala and Perl6, what exactly does Swift (much less Java) really have to distinguish itself?

I also don't get it.

What makes Swift better than other ML like languages for the mainstream developer is the tooling. e.g. Playgrounds and IDE support, and Apple forcing developers to adopt it (Objective-C had only a few WWDC sessions).

For anything else, Haskell, OCaml, Rust and even F# are better options, as they are more mature, already portable and lots of libraries to choose from.

Honestly, I think Swift is a pretty good ML-like on its own merits. A lot of the other options have snags that might make Swift look appealing.

Haskell is really weird. Even for someone reasonably experienced in functional programming, there are tons of new concepts you need to master to be minimally productive in the language. Beyond that, it introduces a whole new problem class of space leaks that you need to reason about. It's not a bad language, but it is a much more radical leap from anything else you're likely to have tried than Swift is.

OCaml is fairly verbose, still doesn't have a great parallelism story AFAIK, and has a quirky type system (1.5 + 1.5 is a type error) and a not-very-well-loved standard library.

Rust can be pretty hard to use and not very ergonomic. If anybody's first Rust stab at a Rust program doesn't run into "such-and-such does not live long enough," that's pretty astonishing. You have to think about a lot more than with Swift.

F# is tied to .NET, which is sufficient to be unappealing for a lot of people.

> Even for someone reasonably experienced in functional programming, there are tons of new concepts you need to master to be minimally productive in the language.

Mostly agree, but it does depend on how you define minimally productive. I also believe this is more of a pedagogy problem. For instance, someone can tell me what their definition of being minimally productive is in Haskell and if it is within my skills I can get them there pretty quickly.

> Beyond that, it introduces a whole new problem class of space leaks that you need to reason about.

I feel like "whole new problem class" is unfair since other languages have memory leaks.

Also, there are techniques developing for dealing with space leaks just like other languages have techniques for memory leaks:


> It's not a bad language, but it is a much more radical leap from anything else you're likely to have tried than Swift is.

Perhaps I've drunk the koolaid, but it doesn't seem that radical after having learned it.

> OCaml is fairly verbose

Agreed, it's the main thing that has put me off of learning what is probably an awesome language. To be honest I just can't get over all the let's :/

I find this a little hypocritical since I found it easy to get over lisps/schemes parenthesis.

> still doesn't have a great parallelism story AFAIK

Right, but they are apparently fixing that fairly quickly: https://news.ycombinator.com/item?id=9582980

To be fair that was posted 146 days ago though and I don't know what current progress is.

> and has a quirky type system (1.5 + 1.5 is a type error)

Interesting, that's because you need to use .+ right?

> and a not-very-well-loved standard library.

I'm always torn on whether or not this is a huge problem. Part of me loves being able to build everything as libraries since anyone can essentially build onto the language. With a good enough package manager this seems ideal. The part of me that wants things to be fast and minimal though craves a great standard library so I can have fewer dependencies and a more "standard" experience. A good standard library also has the advantage of giving you good or good enough options without having to do tons of research on the best libraries for a given task.

Haskell for instance can require some knowledge of the library ecosystem to have the best experience. I'm not sure I'd say the standard library (or Prelude as we call it) is horrible, but it's definitely not as performant as it could be since many (all?) things are based on strings being represented as a linked list. The library solution for this is use Text for anything with unicode or use bytestring for ascii only IIRC.

It is the other way around. Using Rust on iOS is pain. Using Swift is not pain because it is supported by Apple. So it is easier to bring my Swift code and knowledge that I use on iOS to other platforms because other platforms (Linux) don't require sophisticated tooling and support. So I can create apps in Swift for iOS but also backend in Swift for Linux and it is the major benefit.

So... what you say is practical, but it creeps me out. This is the same logic behind "just code for windows because that's what everyone runs and treat everything else as a port". We suffered through that for a decade already, let's not repeat the mistake.

Don't tie your ecosystem to a proprietary (yes, Swift is still a 100% proprietary environment!) toolchain. We've done that several times already in this industry and the results have never been good.

  > Using Rust on iOS is pain.
Is there something more specific than the general fact that cross-compilation is a bit involved at the moment? Just curious :)

You need to write your bridging yourself and it might not always be possible because you need to bridge Rust <-> Objective-C.

Swift with Objective-C is bridged automatically.

I use rust with ios, and my bridging header just includes a single C header file. I don't see how it's any more complicated than using a C library.

Yeah, it bridges to C so you need to build another bridge to have nice Objective-C API. Not mentioning, you will have hard times calling Objective-C API from Rust.

You don't have this problem with Swift.

You don't need to involve Objective-C to use a C API in Swift. You can call C functions directly in Swift and wrap them in a nice Swift API.

I know that but if I decide to use Rust instead of Swift, why would I be wrapping Rust in Swift through C? And still it doesn't solve a problem how Rust can call anything from Cocoa or my existing code.

> if I decide to use Rust instead of Swift, why would I be wrapping Rust in Swift through C?

To avoid the unnecessary overhead of dynamically dispatched Objective-C method calls.

To me, it seems more sensible to go

  Rust -> C -> Swift

  Rust -> C -> Objective-C -> Swift

Rust can call anything that exposes a C-compatible ABI, and Rust code can expose a C-compatible ABI so any language that can call into C (i.e. all languages) can call into Rust.

There exist Rust crates that make it easy to call Objective-C APIs. See https://github.com/SSheldon/rust-objc/ .

Thanks :)

It's not better. No one said it was. The target audience is developers who are using it as their primary language.

> Generally speaking, the NDK makes sense only for a small percentage of apps, so in the general case Google advise against trying to write a whole Android app using the NDK.

Yep, it is easier to make languages target DEX than suffer the pain of the NDK.

They not only advise against it, they make it really uncomfortable for us to use it (vs iOS and WP experience).

> Yep, it is easier to make languages target DEX than suffer the pain of the NDK.

Why do you say that? Plenty of Android apps use non-trivial amounts of C/C++ code, and Dropbox has a tool called Djinni that can automatically generate JNI glue code. My guess is that if it's feasible to use pure Dex bytecode, then debugging is easier (because there's only one kind of call stack), memory can be managed more effectively (because the Dalvik/ART garbage collector can manage everything), and performance isn't impacted by the overhead of JNI. But I have nothing to back that up.

Yes there are plenty of apps that use a lot of C and C++, and we all join in the Anonymous NDK user group meetings.

- The bug tracker is full of NDK issues

- GDB works, eventually. If one has the right set of versions and mobile firmware

- Integration with the first official IDE (Eclipse CDT) kind of worked, after one turned off indexers, did a few plugin customizations, and even then not really

- When Android Studio was announced, silence ensued about NDK future. When Jetbrains announced CLion, there was the hope that it might came to Android Studio, still silent all the way up to Google IO 2015.

- No pre-defined templates for mixed code applications

- Even today Gradle support for NDK builds is flaky and not final. I am yet to be able to have the samples build out of the box.

- The set of official C++ libraries is quite limited, most game related APIs are exposed. Even C++ libraries used by the Java layers like Skia are not exposed to the NDK.

- By limiting NDK to a few basic POSIX APIs and Android game related APIs, everyone has to pack into their APK everything from JNI wrappers, image loaders, network access, the whole stuff.

Now compare this with using C++ in iOS with help of Objective-C++ or on Windows Phone with help of C++/CX.

First class tooling support, mixed debugging that works and no need to keep on writing wrappers.

Even Microsoft's tooling for Android NDK is looking better than what Google does for their own platform.

As for Djinni, I am yet to make it work on Windows.

> Yep, it is easier to make languages target DEX than suffer the pain of the NDK.

So what does this look like in practice? Genuinely curious :-)

By targeting DEX, which happens to be documented, there is at least the hope that for the Android tooling that Google cares about, it is just like Java running and there are less hurdles.

So, you get the same benefits of the languages that target other VMs like JVM, CLR, BEAM and so on.

As long as, the language semantics can map into the VM semantics, all the libraries and platform tooling are available without the need of writing wrappers.

True, that is a big "as long as", but it still is less problematic than going through the current state of the NDK.

That is the approach take by Elements for their tools (http://www.elementscompiler.com), for example.

It could still be used in order to share a module between iOS & Android. For something not related to UI, like persistence, it can make sense. In all the other cases, Kotlin is probably a better choice for Android.

> Namely, instead of generating machine code targetting a specific architecture, LLVM generates assembly code for an imaginary machine, and then converts that intermediate representation to actual code for whichever architecture we're interested in.

Why is that not possible for real-world languages? e.g. have one language which would include the specifics and complications of each language of the world and use it as intermediary for going back and forth to any language in the world.

It's not really that easy even in LLVM. Just like how real world languages don't map 1:1 to each other with all their idioms and untranslatable phrases, LLVM IR isn't a generic virtual machine. Instead, LLVM IR targets various overall architectures such as "64bit ARM processor" with "such-and-such ABI", so there is a limit to which processors the final assembly can be generated for.

Why can't they just compile the swift core library into the executable? I imagine some things are architecture specific, like launching new threads (iOS calls down to objectiveC code which then handles the system call,etc). I imagine the problem is that you can't compile just the non architecture specific parts. Unless you wrote some code to strip out those parts...hmm is that possible?

Also, how come it doesn't look like they had to provide the path to the runtime? Built into the compiler I guess?

With regard to LLVM, the concept of emitting code for a "virtual machine" that is then translated to code for any of several target machines is ancient. One example is the Pascal-P environment from the 1970s. The compiler emitted "P-code" that was then translated to machine language. Oddly enough, P-code was so close to the machine language of the PDP-11 that the translator was trivial!

Just curious why someone would want to do this?

According to the article, you would have to use the NDK to make this work and...

> And of course since we're missing the SwiftCore library this is restricted to a small subset of Swift.

So, it seems more of an academic exercise than a practical thing?

At this point, exactly! Now once Apple fully open-sources Swift, one might try to push things further.

Practical research often starts as academic exercise.

True - but is there a compelling reason we'd want Swift running on Android? I mean, we can say we want it just because (and maybe that's just fine), but is there a stronger reason to want it given many frameworks for mobile apps already compile into more-or-less native apps for each device?

> but is there a compelling reason we'd want Swift running on Android?

Yes because it's a language of higher level than C++ that can theoretically run on all platforms. Now I don't know about you but I'd much rather write the core of my software in a language that can be used on all platforms. This way I can leverage the same business logic everywhere and just have different, dedicated logic for UIs.

I once tried to use C++ for this but the STL is supremely lacking in almost every way compared to the standard libraries that come with almost every other language. There just isn't much choice out there.

Doesn't Java (what Android is already written in) provide that same benefit? Surely it's easier to get a basic JVM running on the iOS?

> Surely it's easier to get a basic JVM running on the iOS?

Gah, I'm not sure how you'd do that and still be able to deploy an application to the iOS app store. I would imagine cross compiling Swift would be orders of magnitude easier.

You already can (sort of): http://RoboVM.com It also works with other JVM languages such as Kotlin which is somewhat similar to Swift.

Oh I hadn't seen that one, that's actually pretty neat. Their pricing is...interesting though. Zero company support at all for the solo package which seems insane to me but other than that it's pretty cool. I wonder how well it works and how it supports third party Java libraries (if at all).

Compile to native code?

Java isn't married with a JIT, there are quite a few commercial AOT compilers.

Even Oracle is finally planning to add one after Java 9.

Sure that's fair I was mostly commenting with porting the JVM versus bypassing it all together. I'd love to see more commercial support for compiling Java and other languages to native just so they can be more portable.

Isn't the compelling reason always write once, run everywhere? Pick your favorite language and wouldn't you want to use that on Android and iOS? Swift is fast becoming the standard for iOS development. So, if you want to support Android too, any effort you can reuse is a win.

Not sure of the state of Scala on Android, but having a language that actually has real closures is appealing. To say nothing of ADTs, nullability, etc...

From my understanding it isn't that great. But Kotlin works well and it's far better at those things than Java. Theres also Clojure but I don't know how well supported it is. Running both of those on iOS is also possible via RoboVM - no need to wait for a good Swift on Android solution.

are you using Kotlin personally ? I have heard a lot of good things about Kotlin (especially the fact that Kotlin code seamlessly works with existing java code). But not sure if I should wait till 1.0

I haven't for any real projects, I've only played around with it. But it seems like there's a decent number of people using it today, so my guess would be that waiting isn't necessary. If I were working on a cross platform mobile/web app today, I'd probably choose Kotlin.

This is really cool! Also interesting because of Microsoft's efforts to make iOS apps cross compatible with Windows through what I would expect is a similar process of cross-compiling and porting libraries.

Having to deal with mangled symbols is pretty annoying. Is it not possible to give a directive to the Swift compiler to disable mangling? Like rust has:


How would it resolve the differences in types without mangling?

No. Currently to call Swift from C (or any other language that supports C-like things) you either have to use the mangled names or write an obj-c wrapper.

This is awesome resource. Thank you for sharing.

You're welcome!

Wow, sorry for slightly going on a tangent, but this is really cool. Imagine all the products had a single syntactic guide to follow. Underlying tech may differ, but a uniform process for creation. There are a million flaws with this, but just a thought.

And can I just add — WOOOOOO!! Okay. Sorry.

actually, you could build an Android command-line executable by using NDK target BUILD_EXECUTABLE. This way is imho clear for the demo purposes by leaving the JNI stuff out of scope

Presently I am a student of the Swift language and always in the back of my mind is the tedious thought that I will have to learn how to do this for ‘Android, one day. Having a compiler do this for you, makes sense. It would be a real blessing.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact