I'm working on a project using Clojure and RoboVM. We use AOT compilation to compile Clojure to JVM classes, and then use RoboVM to compile the JVM classes to native code. In our Clojure code, we call Java APIs provided by RoboVM, which wrap the native iOS APIs.
But we've found an issue with inheritance and class-level static initialization code. Many iOS APIs require inheriting from a base object and then overriding certain methods. Currently, Clojure runs a superclass's static initialization code at compile time, whether using ":gen-class" or "proxy" to create the subclass. However, RoboVM's base "ObjCObject" class (link: 1), which most iOS-specific classes inherit from, requires the iOS runtime to initialize, and throws an error at compile time since the code isn't running on a device.
CLJ-1315 addressed a similar issue by modifying "import" to load classes without running static initialization code. I've written my own patch which extends this behavior to work in ":gen-class" and "proxy" as well. The unit tests pass, and we're using this code successfully in our iOS app.
Patch: clj-1743-2.patch
Here's some sample code that can be used to demonstrate the current behavior (Full demo project at (link: https://github.com/figly/clojure-static-initialization)):
`
package clojure_static_initialization;
public class Demo {
static {
System.out.println("Running static initializers!");
}
public Demo () {
}
}
`
(ns clojure-static-initialization.gen-class-demo
(:gen-class :extends clojure_static_initialization.Demo))
`
(ns clojure-static-initialization.proxy-demo)
(defn make-proxy []
(proxy [clojure_static_initialization.Demo] []))
`
(link: 1) https://github.com/robovm/robovm/blob/master/objc/src/main/java/org/robovm/objc/ObjCObject.java