

Swift-X tool to cross compile Swift and Objective-C(++) code to Android - lstamour
http://swift-x.org/?p=17

======
therealmarv
When I wanted to code a foundation of reusable code for different devices I
would either do it like Dropbox and use C++ as the most common layer
[http://oleb.net/blog/2014/05/how-dropbox-uses-cplusplus-
cros...](http://oleb.net/blog/2014/05/how-dropbox-uses-cplusplus-cross-
platform-development/) or use Javascript (which I can also use for web pages)
for the program logic like described here
[http://www.skyscanner.net/blogs/developing-mobile-cross-
plat...](http://www.skyscanner.net/blogs/developing-mobile-cross-platform-
library-part-3-javascript)

Also interesting [http://kivy.org](http://kivy.org) allows you to use Python
for iOS, Android, OS X and Windows.

I would not bet on Swift and cross compiling it today... too bleeding edge.
But interesting project... hope it matures. Good luck!

~~~
mwcampbell
(This is a reply to this whole sub-thread, not just this comment.)

Most well-known approaches to cross-platform mobile app development have left
me dissatisfied. The root problem is the required bridging overhead between
the cross-platform code and the platform's native runtime (the ObjC runtime on
iOS; Dalvik/ART on Android). Using C/C++ for the cross-platform code is the
lowest overhead approach on iOS, but it's suboptimal on Android.

So why does this matter in practice? A few reasons:

Multiple coexisting memory management systems: In general, my understanding is
that a garbage collector behaves best when all memory, or very near all of it,
is under the collector's control. My fuzzy intuition is that the least optimal
situation is two coexisting garbage collectors, e.g. Xamarin.Android or a
JavaScript engine other than Rhino on Android. But mixing a garbage collector
with reference counting or manual memory management, such as with native code
on Android or RoboVM or Xamarin.iOS, also seems to be suboptimal. If a
significant amount of memory is allocated outside the scope of the GC, then
the GC doesn't have as much information with which to intelligently decide
when and how much to collect. Also, in hybrid systems like the ones being
discussed here, objects under the GC's control sometimes have to be pinned so
they can be accessed by the outside code; this interferes with copying or
compacting collectors.

More information:

[http://developer.android.com/training/articles/perf-
tips.htm...](http://developer.android.com/training/articles/perf-tips.html)
(see the section "Use Native Methods Carefully")

[http://developer.xamarin.com/guides/android/advanced_topics/...](http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/)

[http://developer.xamarin.com/guides/cross-
platform/applicati...](http://developer.xamarin.com/guides/cross-
platform/application_fundamentals/memory_perf_best_practices/)

[http://www.virtualdub.org/blog/pivot/entry.php?id=360](http://www.virtualdub.org/blog/pivot/entry.php?id=360)

Basically, having two coexisting memory management systems is messy. I'd
rather avoid it.

Bridging adds overhead: Consider the cost of copying strings between the
cross-platform component and the native string implementation, or mapping an
array of cross-platform objects to a native array of wrappers so the objects
can be used from UI code. There's always some overhead for marshaling. Maybe
it's not much in practice, and I'm just being anal. But just knowing that it's
there bothers me. The best way to keep software fast is simply to minimize the
amount of pointless crap it has to do. So it seems best to minimize
indirection and overhead by having just one implementation of strings,
collections, etc.

Heavy use of external functions obstructs whole-program optimization: The
Android performance tips document referenced above mentions this in the
context of JNI methods and JIT compilation. I imagine the same applies to
ART's AOT compilation, since the native methods are still opaque to the
compiler, unlike the Dex bytecode. And for combinations such as
Xamarin.Android or a JS engine other than Rhino on Android, there are two JIT
compilers working suboptimally, because neither of them can see into the
other's world.

Hybrid setups thwart obfuscation on Android: It's common for Android
developers to use ProGuard (or its commercial big brother DexGuard) to shrink,
obfuscate, and optimize their apps. Having a significant non-Java component in
the app seriously limits the effectiveness of this practice.

Hybrid setups limit the usefulness of debuggers: If you're mixing Java and
native code on Android, or using Xamarin, RoboVM, or a JavaScript engine, can
you get a single useful stack trace across the platform-specific and cross-
platform components when something goes wrong, as it inevitably will?

So are we doomed to rewrite the same common logic in Objective-C for iOS, Java
for Android, JavaScript for client-side web apps, and (C#|JavaScript|C++) for
Windows Phone, if we want that code to integrate well with the host platform?
Luckily, no.

RubyMotion has the right idea, I think, and there's apparently an Android
version on the way, but nothing for Windows Phone/WinRT or client-side web
apps.

Another option is to write common code in Java, then use J2ObjC for iOS,
IKVM.NET for Windows and Windows Phone, and GWT for the Web. Some teams within
Google are doing this (minus the part about IKVM.net on Windows, AFAIK),
including the team that developed J2ObjC. This approach certainly doesn't have
the polish of a commercial product like RubyMotion or the Xamarin tools. But
on the other hand, all the tools are free, so this should appeal to cash-
strapped indie developers. One thing I don't like about J2ObjC is that the JRE
emulation library has a larger footprint than I'd like. On a more aesthetic
level, I don't like the fact that this approach takes Java, which is designed
to be a platform unto itself, and tries to make it work on other host
platforms.

And then there's RemObjects Elements
([http://www.remobjects.com/elements/](http://www.remobjects.com/elements/)),
a compiler toolchain with two language front-ends and three platform back-
ends. On the language side, we have a choice of C# or Oxygene (a language
based on Object Pascal). Either of these languages can be compiled to .NET
bytecode, JVM bytecode (and from there to Dalvik bytecode for Android), or
native code for the Objective-C runtime. (Note that the C# language front-end
only provides the language; it doesn't attempt to bring the .NET class library
to the other platforms.) Each platform back-end uses the target platform's
preferred memory management system. That means GC for .NET and Java, and
automatic reference counting for the Objective-C runtime. There's a cross-
platform standard library called Sugar for things like collections, date/time
manipulation, making HTTP requests, and XML, but emphatically _not_ UI. Sugar
has a very small footprint; in fact, many Sugar classes and methods are mapped
to their platform-provided counterparts at compile time. Like the Xamarin
suite, RemObjects C# and Oxygene are commercial products, but the pricing is
very reasonable. I'm looking forward to trying this toolchain on a real
project, probably using the C# front-end.

I know this has been a long comment; it covers a topic I've been thinking
about a lot for more than a year. I know a lot of developers will just accept
the added complexity and inefficiency I've described, for the sake of getting
things done, i.e. accepting complexity and runtime inefficiency in exchange
for developer efficiency. But then, added complexity translates to developer
inefficiency at some point, especially when something goes wrong. And
inflicting runtime inefficiency feels wrong when the machines in question
aren't ours. That is, the trade-off between programmer time and machine time
is different for client-side apps than for server-side apps. Luckily, it
appears we can have the best of all worlds, especially with the RemObjects
products, at least if we're willing and able to pay for excellent tools and
accept that some of those tools will be closed-source.

(I guess readers will have to trust that this whole comment isn't actually a
marketing piece for RemObjects. I just discovered the RemObjects products last
night, and they don't seem to be well known, so I'm excited about them.)

~~~
SirWart
Having worked on mobile code sharing a lot at Dropbox, I would say that the
bridging overhead may not be a huge issue depending on how you structure your
code. The approach we took was to keep all the UI completely native in the
platform's native language, and put only the networking/database/model logic
in the shared code. This means that typically you only have to cross the
bridging layer when you hit disk or network, which is already going to be
heavily IO bound anyway.

I've heard of companies being successful using C# as the shared language, but
in our case we wanted to distribute SDKs, so we picked C++ since it wouldn't
require us to include a runtime with the SDK. It's definitely not the easiest
way to do things though if you're not already familiar with C++.

I'm not as familiar with Android compared to iOS, but ease of debugging is
definitely a real problem with C++ on Android. I haven't tried very many of
the other cross-platforms options, but would consider ease of debugging as one
of my highest priorities since it's one of the hardest things to engineer
around.

------
pavlov
From the project's GitHub page, some more details on what it actually does:

 _swift-x is a python script that simplifies the compiling of Swift and
Objective-C(++) code into object files._

 _... [It] is a two stage wrapper for clang and the swift compiler that uses
the Android NDK tools to produce android compatible .o files._

 _The first stage uses clang or swift to compile source code and emit LLVM-IR
code which is passed to the Android second stage tools which compile the IR
into .o files._

So you get working object code, but you still need to figure out how to get
Android versions of the Cocoa Touch libraries if you use any of those APIs.

~~~
sspiff
You can't just take a Swift app for iOS and compile it for Android, sure.

But this could be useful for people who enjoy Swift, and want to reuse blocks
of logic from their iOS app to an Android port.

I'm wondering though, I thought Swift compiled down to code that uses things
like the Foundation framework (NSString etc), which would also be missing on
Android. It would be hard to do anything without these classes, wouldn't it?

~~~
pavlov
There are several independent open-source implementations of Foundation like
GNUStep and Cocotron.

Once you have the Obj-C runtime and cross-compiler working, porting either of
those to Android should be fairly simple... But I suspect that Swift may have
dependencies on new or recent Foundation features which could be missing from
the open-source versions (for understandable reasons, they lag behind Apple by
several years).

~~~
WoodenChair
These guys already did port those frameworks to Android:
[http://www.apportable.com](http://www.apportable.com)

------
lukeh
FWIW I took a recent look at porting the Apple Objective-C runtime to Linux
(with the vague idea that if Apple open source Swift, it might be easier to
get it working with their own runtime rather than the GNUstep one).

One nice thing about clang is that there's no problem outputting Objective-C
code that uses the Apple runtime on other platforms: just use -fobjc-
runtime=macosx. The catch is that because class, protocol, etc definitions are
just data, you need a way to get notified by the runtime linker when an object
is mapped into the process address space. (You could scan the current address
space at startup, but that makes it difficult to support dynamic loading,
although probably not impossible now that I think about it. I thought I was
nearly there with ld.so audit interface, but audit modules are loaded into
their own namespace, so you can't easily communicate with the global libobjc.)

------
mpweiher
I got some minimal Objective-C code running on Android a while ago, see
[http://blog.metaobject.com/2012/12/android-ndk-now-
includes-...](http://blog.metaobject.com/2012/12/android-ndk-now-includes-
clang-with.html)

This tool appears to fix the problem with the NDK make tool not recognizing .m
files. I worked around this once by naming them with the .c extension and
using compiler flags to set the language to Objective-C. Another time, I think
I hacked the makefiles, but that was extremely painful.

Of course, there's apportable
([http://www.apportable.com/open_source](http://www.apportable.com/open_source)),
their low-level stuff (runtime, Foundation) is open-source.

------
bezalmighty
Its great to see work being put into building community tools like this for
Swift, thanks for the contribution.

BTW if you are in SF, we are running a Swift hackathon @ GitHub HQ in a few
weeks:
[http://www.swifthack.splashthat.com](http://www.swifthack.splashthat.com)

------
empressplay
Anything that makes it easier for entrepreneurs to make their apps available
on both iOS and Android is productive and welcome.

------
wben
Super nice work. Thanks for posting.

