diff --git a/.github/workflows/graal_test.yml b/.github/workflows/graal_test.yml new file mode 100644 index 00000000..fb405510 --- /dev/null +++ b/.github/workflows/graal_test.yml @@ -0,0 +1,50 @@ +name: graal-test + +on: [push, pull_request] + +jobs: + + clojure: + + strategy: + matrix: + os: [ubuntu-latest, macOS-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + # It is important to install java before installing clojure tools which needs java + # exclusions: babashka, clj-kondo and cljstyle + - uses: graalvm/setup-graalvm@v1 + with: + version: 'latest' + java-version: '17' + components: 'native-image' + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install clojure tools + uses: DeLaGuardo/setup-clojure@10.0 + with: + lein: 2.9.1 # Leiningen + bb: latest # Babashka + + # Optional step: + - name: Cache clojure dependencies + uses: actions/cache@v3 + with: + path: | + ~/.m2/repository + ~/.gitlibs + ~/.deps.clj + # List all files containing dependencies: + key: cljdeps-${{ hashFiles('deps.edn') }} + # key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }} + # key: cljdeps-${{ hashFiles('project.clj') }} + # key: cljdeps-${{ hashFiles('build.boot') }} + restore-keys: cljdeps- + + - name: Execute graal-test + run: bb test:graal diff --git a/.gitignore b/.gitignore index 27d94bae..f2c08f97 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ pom.xml* /doc/ .idea/ *.iml +graal_test +graal_test.build_artifacts.txt +.cache diff --git a/bb.edn b/bb.edn new file mode 100644 index 00000000..2acb809b --- /dev/null +++ b/bb.edn @@ -0,0 +1,6 @@ +{:paths ["bb"] + :tasks {:requires ([graal-test]) + test:graal {:doc "Run native-image tests" + :task (do (graal-test/uberjar) + (graal-test/native-image) + (graal-test/test-native-image))}}} diff --git a/bb/graal_test.clj b/bb/graal_test.clj new file mode 100755 index 00000000..18e67f1b --- /dev/null +++ b/bb/graal_test.clj @@ -0,0 +1,37 @@ +#!/usr/bin/env bb + +(ns graal-test + (:require + [babashka.fs :as fs] + [babashka.process :refer [shell]] + [clojure.string :as str])) + +(defn uberjar [] + (let [command "lein with-profiles +graal-test uberjar" + command (if (fs/windows?) + (if (fs/which "lein") + command + ;; assume powershell module + (str "powershell.exe -command " (pr-str command))) + command)] + (shell command))) + +(defn executable [dir name] + (-> (fs/glob dir (if (fs/windows?) + (str name ".{exe,bat,cmd}") + name)) + first + fs/canonicalize + str)) + +(defn native-image [] + (let [graalvm-home (System/getenv "GRAALVM_HOME") + bin-dir (str (fs/file graalvm-home "bin"))] + (shell (executable bin-dir "gu") "install" "native-image") + (shell (executable bin-dir "native-image") "-jar" "target/graal.jar" "--no-fallback" "graal_test"))) + +(defn test-native-image [] + (let [{:keys [out]} + (shell {:out :string} (executable "." "graal_test") "1" "2" "3")] + (assert (str/includes? out (str '("1" "2" "3"))) out) + (println "Native image works!"))) diff --git a/project.clj b/project.clj index 426616ce..436f64b2 100644 --- a/project.clj +++ b/project.clj @@ -64,7 +64,14 @@ [com.taoensso/nippy "3.2.0"] [com.taoensso/carmine "3.1.0" :exclusions [com.taoensso/timbre]] - [com.draines/postal "2.0.5"]]}} + [com.draines/postal "2.0.5"]]} + + :graal-test + {:dependencies [[org.clojure/clojure "1.11.1"] + [com.github.clj-easy/graal-build-time "0.1.4"]] + :main taoensso.timbre.graal-test + :aot [taoensso.timbre.graal-test] + :uberjar-name "graal.jar"}} :test-paths ["test" #_"src"] diff --git a/src/taoensso/timbre.cljc b/src/taoensso/timbre.cljc index d81ffc4c..7d5603f9 100644 --- a/src/taoensso/timbre.cljc +++ b/src/taoensso/timbre.cljc @@ -749,12 +749,9 @@ (defn- fline [and-form] (:line (meta and-form))) -;; Try enable reproducible builds by ensuring that `log!` macro expansion -;; produces deterministic callsite-ids, Ref. #354 -#?(:cljs (def ^:private deterministic-rand rand) ; Dummy, non-deterministic - :clj (let [;; Must be delayed for GraalVM compatibility, Ref. #360 - rand_ (delay (java.util.Random. 715873))] - (defn- deterministic-rand [] (.nextDouble ^java.util.Random @rand_)))) +(enc/defonce ^:private callsite-counter + "Simple counter, used to uniquely identify each log macro expansion." + (enc/counter)) (defmacro log! ; Public wrapper around `-log!` "Core low-level log macro. Useful for tooling/library authors, etc. @@ -786,12 +783,9 @@ ?file (when (not= ?file "NO_SOURCE_PATH") ?file) - ;; Identifies this particular macro expansion; note that this'll - ;; be fixed for any fns wrapping `log!` (notably `tools.logging`, - ;; `slf4j-timbre`, etc.): - callsite-id - (hash [level msg-type args ; Unevaluated args (arg forms) - ?ns-str ?file ?line (deterministic-rand)]) + ;; Note that this'll be const for any fns wrapping `log!` + ;; (notably `tools.logging`, `slf4j-timbre`, etc.) + callsite-id (callsite-counter) vargs-form (if (symbol? args) diff --git a/test/taoensso/timbre/graal_test.clj b/test/taoensso/timbre/graal_test.clj new file mode 100644 index 00000000..0c082c49 --- /dev/null +++ b/test/taoensso/timbre/graal_test.clj @@ -0,0 +1,6 @@ +(ns taoensso.timbre.graal-test + (:require [taoensso.timbre :refer [info]]) + (:gen-class)) + +(defn -main [& args] + (info args))