I've been trying to employ Kawa Scheme for developing Android project. I've found two repositories on GitHub: one called 'android-kawa', and another called 'KawaDroid'. They're both a bit dated (last updates were around 2012). In the case of 'android-kawa' I was able to reach the author, but he said he did't remeber enough to help me.
In the 'android-kawa' repo there's a bunch of scripts for setting up and working with the project. One of the scripts downloads the Kawa 1.13 tarball, applies some patches and then attempts to build it.
However, the build isn't supported in Termux, bevaise the config.guess
script doesn't recognize the system. This issue can be easily resolved by downloading the latest versions of config.guess
and config.sub
.
Another problem is the format of the JVM bytecode. When I use the latest Java compiler, the generated bytecode contains (I believe) instructions for JVM8+, which aren't supported by the dx
command. This isn't a problem if I run Java inside of Termux, because it installs the regular JVM, but if I want to include the Kawa jar
in my APK (which is something that I want), then it becomes an obstacle.
This, again, can be resolved by forcing the Java version to 7 in javac
. (But then, the compiler complsins that Java 1.7 is deprecated. I guess this is why the buildAPKs project uses ecj
instead of javac
)
Also, when I ./configure
Kawa, I can pass it the path to the android.jar
file (./configure --with-android=...
). I have two android.jar
files on my system:
~ $ locate android.jar
/data/data/com.termux/files/usr/share/aapt/android.jar
/data/data/com.termux/files/usr/share/java/android.jar
I don't know where they came from or how they differ between one another, but I've been prefering the second one.
So, when I have the kawa.jar
available - and when I try to compile it with the command
~/android-kawa $ java -cp $(dirname $(locate android.jar |tail -n 1)) -jar kawa/kawa-1.13.jar -C KawaHello/src/kawa/android/hello.scm
I get the following error:
internal error while compiling KawaHello/src/kawa/android/hello.scm
java.lang.NoClassDefFoundError: android/view/View
at gnu.kawa.android.defs.<clinit>(defs.scm)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1155)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:42)
at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:185)
at java.base/java.lang.reflect.Field.acquireFieldAccessor(Field.java:1132)
at java.base/java.lang.reflect.Field.getFieldAccessor(Field.java:1113)
at java.base/java.lang.reflect.Field.get(Field.java:425)
at gnu.expr.ModuleInfo.setupModuleExp(ModuleInfo.java:195)
at kawa.standard.require.importDefinitions(require.java:308)
at kawa.standard.require.scanForDefinitions(require.java:219)
at kawa.lang.Syntax.scanForm(Syntax.java:65)
at kawa.lang.Translator.scanForm(Translator.java:1120)
at gnu.kawa.lispexpr.LispLanguage.parse(LispLanguage.java:64)
at gnu.expr.Compilation.process(Compilation.java:1908)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:305)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
at kawa.repl.compileFiles(repl.java:823)
at kawa.repl.processArgs(repl.java:444)
at kawa.repl.main(repl.java:869)
Caused by: java.lang.ClassNotFoundException: android.view.View
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ... 24 more
I have obviously tried it without the -cp
argument (with the same effect). The android/view/View.class
entry is present in the list returned by jar -tf android.jar
.
How can I further investigate in the root cause of the problem, and most importantly, how can I solve it?
It turned out that I have invoked Java incorrectly, and that it didn't see the android.jar
file. It helped to invoke the compiler in the following way:
~/android-kawa $ java -cp $(locate android.jar |tail -n 1):kawa/kawa-1.13.jar kawa.repl -C KawaHello/src/kawa/android/hello.scm
(the difference is that I only have one -cp
argument with jar
files separated by :
, and that I explicitly give the kawa.repl
class name)