Last active
June 20, 2019 22:42
-
-
Save joinr/6ff4a9ad39f8c730621a7aee81178b0f to your computer and use it in GitHub Desktop.
example of a main shim namespace for clojure to avoid AOT'ing everything and allow fast starts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;Shim class for running app without | |
;;aot compilation issues. | |
;;entrypoint for some gui. | |
(ns blah.main | |
(:gen-class :main true)) | |
;;This is the main entry point for the app. | |
;;It's a good example of a shim-class, and | |
;;requires some arcane features to get things | |
;;working to avoid aot compilation of dependent | |
;;namespaces, and to load them at runtime. | |
(defn -main [& args] | |
;;clojure.set isn't imported by default, causing errors when | |
;;aot-compiling in some places. | |
(require 'clojure.set) | |
;;if we don't use this, i.e. establish a root binding | |
;;for the *ns* var, we can't use in-ns later.... | |
;;which leads to compile-time and run-time errors.. | |
;;[optional] | |
;;I like to use splash screens for gui stuff; e.g. splasher is a dependency. You can elide this. | |
(require 'splasher.core) | |
;;[optional] | |
;;if you're loading a logo for splasher you need to get io loaded as well. | |
(require 'clojure.java.io) | |
(if (seq args) | |
;;You can change this to process your args, or pass them on to something, | |
;;like say a blah.cli/cli processor for your app. | |
;;In this case, I just divert to the REPL | |
(clojure.main/repl) | |
;;otherwise, we invoke some runtime resolve magic to load our | |
;;namespace, with a splashscreen. | |
(binding [*ns* *ns*] | |
;;rather than :require it in the ns-decl, we load it | |
;;at runtime, let it hang out for 20 seconds or some time while we | |
;;load more stuff in the background. | |
(future ((resolve 'splasher.core/splash!) | |
(clojure.java.io/resource "logo.png") | |
:duration 20000)) | |
;; | |
(require 'blah.core) | |
(in-ns 'blah.core) | |
;;if we don't use resolve, then we get compile-time aot | |
;;dependency on blah.core. This allows us to shim the | |
;;class. Assume blah.core/hub is a function that | |
;;launches a GUI frontend based in swing and | |
;;takes an :exit? arg. So we replace the typical | |
;;-main function, say what leiningen's default template | |
;;populates in our blah.core namespace, and eliminate | |
;;the gen-class from blah.core. In project.clj | |
;;we'd change the main to this class, blah.main, | |
;;and remove aot-all if it exists. We can now launch | |
;;much faster e.g. even if doing repl development (no need to AOT compile | |
;;the blah.core namespace, which could involve compiling a boatload of | |
;;stuff which takes too long for my taste (especially if I've already | |
;;tested it at the REPL anyway). Note: you can still AOT everything | |
;;if you want to. | |
((resolve 'blah.core/hub) :exit? true)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment