This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-27
Channels
- # announcements (7)
- # aws (1)
- # beginners (42)
- # calva (65)
- # clj-kondo (5)
- # cljs-dev (11)
- # clojure (69)
- # clojure-australia (7)
- # clojure-dev (4)
- # clojure-europe (9)
- # clojure-gamedev (2)
- # clojurescript (2)
- # conjure (4)
- # cursive (1)
- # data-science (1)
- # datomic (8)
- # events (1)
- # fulcro (35)
- # graalvm-mobile (40)
- # introduce-yourself (1)
- # lsp (26)
- # malli (14)
- # mathematics (2)
- # missionary (5)
- # nextjournal (4)
- # off-topic (4)
- # polylith (10)
- # shadow-cljs (5)
- # test-doc-blocks (1)
- # tools-build (24)
- # tools-deps (1)
- # xtdb (12)
I am curious if this also works on Android, or if it is currently iOS only.
The demo project is iOS only, but I plan on extending it to android at some point. If someone was interested in giving it a shot, I could provide some pointers on how to get started and what the basic structure would look like.
@smith.adriane I would be interested, thanks!
Awesome! The basic plan is pretty simple. You compile your uberjar with native-image
as a native library and communicate with the android app via JNI. If you search some combination of jni, android, and ndk, there should be lots of examples of working with native libraries.
native-image
requires a bunch of special flags, especially when targeting mobile. I followed the example from https://github.com/gluonhq/gluon-samples/tree/master/HelloGluon to find the flags for iOS. It's been a while, but there's a way to view all of the build logs and they print the full native-image
command somewhere in the logs. I combined those args with the arglist that's usually required to make clojure compile. You can see the iOS script at https://github.com/phronmophobic/mobiletest/blob/main/scripts/compile-shared#L28.
I know that's a bit vague, but I'm out of town at the moment. I'm happy to answer more questions since that description is light on details.
The C interface that your clojure program exposes will use graal's C API, https://www.graalvm.org/reference-manual/native-image/C-API/. To use that from clojure, I use https://github.com/cnuernber/dtype-next/. See https://github.com/phronmophobic/mobiletest/blob/main/src/com/phronemophobic/mobiletest.clj#L87
Nice, thanks for the lead!
@smith.adriane I'm trying to run the compile-shared
script and it throws an error while running the line
clojure -X com.phronemophobic.mobiletest/compile-interface-class
The error is
Syntax error (ClassNotFoundException) compiling at (com/phronemophobic/mobiletest.clj:1:1).
org.graalvm.nativeimage.c.function.CEntryPointLiteral
By any chance, you know what I could be doing wrong? I didn't run download-deps
.It's been a while since I've looked at this. Let me check!
thank you! the troublesome line is https://github.com/phronmophobic/mobiletest/blob/main/src/com/phronemophobic/mobiletest.clj#L6
I think the current error you're running into is because the graalvm classes aren't available. You need to compile using graalvm's jdk to make classes like CEntryPointLiteral available.
however, I don't think you'll get very far without doing the prerequisites, https://github.com/phronmophobic/mobiletest#prerequisites
Setting up graalvm is step #2 of the prerequisites
ahh I see, so before even attempting to run compile-shared
I need to compile the project with graal?
compile-shared
will compile the project, but compilation uses graalvm, graalvm's llvm-toolchain, and java's arm64 static libraries
https://github.com/phronmophobic/mobiletest/blob/main/scripts/compile-shared#L28
Yes!! Thanks, I had to setup the $PATH
to use graal before running clojure -X com.phronemophobic.mobiletest/compile-interface-class
no problem!
are you trying to compile clojure for android?
If so, then the static libraries that download-deps
fetches aren't the right ones. You'll need to get the corresponding android deps.
Yes, I was just trying to run native-image
using the flags you suggested extracting from the HelloGluon project
I think you'll get linker errors if you don't have them, but I think that's one of the last steps within the native-image
compilation process
so if you get that far, you're at least headed in the right direction
@smith.adriane, by any chance you remember what the https://github.com/phronmophobic/mobiletest/tree/main/conf/capcache is about? Or how you generate it? while trying to adapt the code to android I tried using the capcache folder from a fresh HelloGloun project, but when running https://github.com/phronmophobic/mobiletest/blob/main/scripts/compile-shared#L28 I'm getting the error
Missing CAP cache value for: NativeCodeInfo:PosixDirectives:ConstantInfo:LC_ADDRESS
If using the capcache of mobiletest I get another error
Missing CAP cache value for: NativeCodeInfo:AArch64LibCHelperDirectives:StructInfo:CPUFeatures:StructFieldInfo:fDCPOP
I don't really know what the capcache is. I just copied the args and configs from the gluon project.
Did you compile an android project successfully with HelloGluon?
I don't remember where the capcache files come from. It's possible that they might be different depending on the compiler platform or target platform
I compiled an iOS project using the HelloGluon script and then used the same flags that the HelloGluon script used by looking at the build logs.
Almost all the flags I use in compile-shared
are copied from the HelloGluon script. I think only flags I added for clojure are:
--report-unsupported-elements-at-runtime \
--initialize-at-build-time="$INITIALIZE_AT_BUILD_TIME" \
--no-fallback \
--no-server \
... and
-J-Dclojure.spec.skip-macros=true \
-J-Dclojure.compiler.direct-linking=true \
-J-Dtech.v3.datatype.graal-native=true \
# non-clojure related, but probably added by me
-J-Xmx20G \
-J-XX:MaxDirectMemorySize=8G \
https://github.com/frankitox/graal-android/blob/main/scripts/compile-shared#L31-L60
Should I first modify the code in src
folder before even attempting to run native-image
?
The compile script uses https://github.com/frankitox/graal-android/blob/main/src/com/phronemophobic/mobiletest.clj as the main which should work regardless of platform
and you would probably get a different error. Excited to see clojure on android! 🤞