graalvm-mobile

https://github.com/phronmophobic/mobiletest
phronmophobic 2021-07-03T00:26:06.215300Z

I've been thinking about the best way to target mobile with clojure for a while. I saw a couple people join and thought it might be worth sharing what I've learned so far. Now that graalvm has added iOS and android targets, I don't think there are any technical roadblocks that would prevent clojure on mobile, but there is plenty of work to do. Recently, I was able to build a simple todo app in clojure that ran on my iPhone. I intend to publish the example once I clean it up. I published a very bare bones proof of concept at https://github.com/phronmophobic/mobiletest. It even can eval clojure code at runtime thanks to sci, :sci: . The next steps, as I see them, are: • Decide on a strategy for UI graphics and events (SwiftUI, Epoxy, React Native, membrane, something else?) • Decide on a strategy to interop with platform APIs • Improve tooling and documentation • Decide on a strategy for repl driven development (or else, why bother 😛). I've started with iOS since that's the mobile device I regularly use, but I haven't seen anything to indicate that the same process wouldn't apply to android (before clojure, I was working on cross-platform mobile games in c++). I would love to hear any feedback or ideas: • What do people think would be a good fit for building UIs? • What kinds of apps are folks hoping to build? • I'm also curious why people are interested in using graalvm+clojure vs cljs+react native. Personally, I just don't like html/css/javascript, but realistically, it seems like folks have found cljs+react native to be productive.

borkdude 2021-07-03T07:24:23.230700Z

You could still do the control logic from the REPL

borkdude 2021-07-03T07:24:39.231300Z

And then compile to native as the very last step

1
phronmophobic 2021-07-03T19:24:11.242400Z

> I think the interop with platform API is extremely important and a sustainable way of maintaining the bridge must be thought of. Java objC bridges have failed to be maintained in the past. Apple's documentation has an API (eg. https://developer.apple.com/tutorials/data/documentation/technologies.json?language=objc ) that I think provides enough info to automatically generate an API. Objective-c is dynamic enough that stubs shouldn't be necessary. Swift only APIs will probably require stubs.

emccue 2021-07-03T19:38:47.243700Z

> I'm also curious why people are interested in using graalvm+clojure vs cljs+react native

emccue 2021-07-03T19:39:05.243900Z

Idk if this counts as justification, but it feels like an unexplored space

emccue 2021-07-03T19:39:37.244100Z

and I "trust" jvm clojure more

indy 2021-07-03T19:48:46.244300Z

That's neat, the Apple documentation API, creating stubs would be straight forward. But I'm not able wrap my head around how the data structures will move in and out of the G+C compiled code to ObjC/Swift, if you get what I mean. Not sure how to put it clearly, but with stubs I'll know the types and signatures and all that metadata but how do I program against those data-structures when I'm writing in Clojure.

phronmophobic 2021-07-03T21:08:34.244700Z

It's still a rough plan, but the idea is to have clj->objc and objc->clj functions for structures like NSDictionary, NSArray, NSString, etc. For classes, you can use https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/index.html, to set and get properties. That should make working with objective-c APIs possible from clojure, but not necessarily pleasant. There will probably be some amount of effort needed to make working with platform APIs more comfortable.

1
borkdude 2021-07-03T21:10:46.245Z

In babashka I worked my way around all of this native stuff by using JSON or Transit serialization ;)

1
raspasov 2021-07-06T01:10:49.249900Z

One use-case that I think can be super useful is calling native APIs from the REPL. I had to build a custom camera component in Swift and I felt like going back to the dark ages, using the debugger, setting break points, etc. If I had a Clojure REPL into Swift/Objective-C (ideally Swift) the experience could potentially be much better.

raspasov 2021-07-06T01:13:26.250200Z

I’m not sure how possible that would be… Since you’d have to compile some Objective-C on the fly and execute it? I believe that is possible (but I have never tried it myself, have only heard/read stories). Not sure about that strategy with Swift.

raspasov 2021-07-06T01:16:10.250400Z

Just found this: https://github.com/johnno1962/InjectionIII

raspasov 2021-07-06T01:16:21.250700Z

Perhaps worth a look.

phronmophobic 2021-07-06T01:24:26.250900Z

I was able to get some basic objective-c interop working using https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend?language=objc (along with a few other https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc calls). I think that should enable most objective c interop, but I'm not sure how how easy it is to make a repl for Swift. I'll check out the project the InjectionIII project, but Swift seems overall less friendly for dynamic runtime interaction.

1
raspasov 2021-07-06T01:30:31.251100Z

This project (InjectionIII) actually seems like the real deal… It looks like you can eval Swift/Obj-C on the fly.

indy 2021-07-03T04:07:15.229800Z

I’ve been learning iOS too lately and story boarding is different from HTML/CSS. Currently finding it better than the flow-spoiling experience of tweaking HTML/CSS. But that could just be the high of learning something new. But not sure how the tooling will work for this since the swift code and story boarding experience seem very coupled. Graalvm+Clojure native than Cljs+react since I think intuitively that the former might be far more performant. I think the interop with platform API is extremely important and a sustainable way of maintaining the bridge must be thought of. Java objC bridges have failed to be maintained in the past. It would also be an interesting approach if I could write the UI bits in Xcode and controllerish logic in Clojure. If perf is great with g+c then it would be the best thing ever.

indy 2021-07-03T18:03:04.235500Z

I'm getting the following error when I run https://github.com/phronmophobic/mobiletest/blob/main/scripts/compile-shared The build folder seems to have downloaded the deps.

Exception in thread "main" com.oracle.svm.core.util.UserError$UserException: Could not find platform class org.graalvm.nativeimage.Platform$IOS_AARCH64 that was specified explicitly on the command line using the system property svm.platform
	at com.oracle.svm.core.util.UserError.abort(UserError.java:68)
	at com.oracle.svm.hosted.NativeImageGenerator.defaultPlatform(NativeImageGenerator.java:332)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.installNativeImageClassLoader(NativeImageGeneratorRunner.java:172)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:114)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:541)
Error: Image build request failed with exit status 1

indy 2021-07-03T18:05:12.235800Z

My Graal isn't the latest version, if that matters.

borkdude 2021-07-03T18:08:45.236200Z

You should first run the download script

borkdude 2021-07-03T18:09:09.236400Z

ah yes, graal version may also matter, use 21.1.0

indy 2021-07-03T18:10:27.236600Z

I did run the download script, trying it with the latest Graal

phronmophobic 2021-07-03T18:13:06.236800Z

not sure if this is causing the error, but you'll also have to install the llvm tool chain:

gu install llvm-toolchain

indy 2021-07-03T18:34:58.237Z

I had that installed too. But I guess the version was the issue, the compilation has started with the latest version. 🤞:skin-tone-4:

🤞 1
indy 2021-07-03T18:57:15.237300Z

The build fails in xcode. Any idea what is causing this?

indy 2021-07-03T18:57:46.237700Z

(I'm on Xcode 12.5.1 )

phronmophobic 2021-07-03T19:13:53.238200Z

you have to build for device.

phronmophobic 2021-07-03T19:14:28.239300Z

I haven’t tried building for simulator, but it requires a different architecture

phronmophobic 2021-07-03T19:18:04.241200Z

@kslvsunil , hopefully, that unblocks you, but that’s probably a good note for me to put in the Readme!

indy 2021-07-03T19:21:58.241400Z

Woohoo, works! This is really cool

indy 2021-07-03T19:22:05.241600Z

Thank you 🙂

phronmophobic 2021-07-03T19:22:36.241800Z

:bananadance::toot::clojure-spin:

phronmophobic 2021-07-03T19:22:51.242Z

it should start a sci repl that you can connect to

phronmophobic 2021-07-03T19:23:05.242200Z

not super useful since there's no interop yet, but it's still neat

indy 2021-07-03T19:26:59.242600Z

Oh, haha. I was scratching my head as to what was even compiled when I saw that "Hello, world!" was coming from ContentView

indy 2021-07-03T19:27:30.242800Z

Coool, will hack around with it, cheers

phronmophobic 2021-07-03T19:29:42.243Z

Yep, mobiletest is computational only. No UI yet.

indy 2021-07-03T19:30:13.243200Z

Yup, figured 🙂

phronmophobic 2021-07-03T19:33:00.243400Z

Ok, just updated the readme to add a step for selecting a non simulator target.

1