-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Add Graal native image config and tests The clj-yaml jar now includes the necessary native-image config for GraalVM's `native-image`. This config is picked up automatically by GraalVM `native-image` and frees up native-image users from having to figure out and specify this config. We now have a babashka `test-native` task that verifies that clj-yaml does in fact work when compiled with GraalVM `native-image`. We natively compile our full test suite. The native image is built against a locally built clj-yaml jar file instead of local sources. This verifies that our native image config within our jar is picked up. * ci: yaml fix
- Loading branch information
Showing
11 changed files
with
251 additions
and
8 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ runs: | |
with: | ||
distribution: 'temurin' | ||
java-version: ${{ inputs.jdk }} | ||
if: inputs.jdk != 'skip' | ||
|
||
- name: Install Clojure Tools | ||
uses: DeLaGuardo/[email protected] | ||
|
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
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
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
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
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
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
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
1 change: 1 addition & 0 deletions
1
resources/META-INF/native-image/clj-commons/clj-yaml/native-image.properties
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Args = --initialize-at-build-time=org.yaml.snakeyaml |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
(ns test-native | ||
(:require [lread.status-line :as status] | ||
[babashka.fs :as fs] | ||
[babashka.tasks :as t] | ||
[cheshire.core :as json] | ||
[clojure.edn :as edn] | ||
[clojure.math :as math] | ||
[clojure.string :as str])) | ||
|
||
(defn- find-graal-prog [prog-name] | ||
(or (fs/which prog-name) | ||
(fs/which (str (fs/file (System/getenv "JAVA_HOME") "bin")) prog-name) | ||
(fs/which (str (fs/file (System/getenv "GRAALVM_HOME") "bin")) prog-name))) | ||
|
||
(defn- find-graal-native-image | ||
"The Graal team now bundle native-image with Graal, there is no longer any need to install it." | ||
[] | ||
(status/line :head "Locate GraalVM native-image") | ||
(let [native-image (or (find-graal-prog "native-image") | ||
(status/die 1 "failed to to find GraalVM native-image, it should be bundle with your Graal installation"))] | ||
(status/line :detail (str "found: " native-image)) | ||
native-image)) | ||
|
||
(defn get-classpath [] | ||
(status/line :head "Get classpath") | ||
(let [classpath (-> "target/native-classpath.edn" | ||
slurp | ||
edn/read-string)] | ||
|
||
(println "\nClasspath:") | ||
(println (str "- " (str/join "\n- " classpath))) | ||
(str/join fs/path-separator classpath))) | ||
|
||
(defn generate-reflection-config [target-file] | ||
;; we add these classes to support our "allow unsafe" tests | ||
(->> [{:name "javax.script.ScriptEngineManager" | ||
:queryAllDeclaredConstructors true} | ||
{:name "java.net.URLClassLoader" | ||
:queryAllDeclaredConstructors true} | ||
{:name "java.net.URL" | ||
:queryAllDeclaredConstructors true | ||
:methods [{:name "<init>" :parameterTypes ["java.lang.String"] }]}] | ||
(json/generate-string) | ||
(spit target-file))) | ||
|
||
(defn run-native-image [{:keys [:graal-native-image | ||
:reflection-config | ||
:target-path :target-exe :classpath :native-image-xmx | ||
:entry-class]}] | ||
(status/line :head "Graal native-image compile AOT") | ||
(let [full-target-exe (fs/which target-exe)] | ||
(when (fs/exists? full-target-exe) | ||
(fs/delete full-target-exe))) | ||
(let [native-image-cmd [graal-native-image | ||
(str "-H:Path=" target-path) | ||
(str "-H:Name=" target-exe) | ||
"--features=clj_easy.graal_build_time.InitClojureClasses" | ||
"-O1" ;; basic optimization for faster build | ||
(str "-H:ReflectionConfigurationFiles=" reflection-config) ;; to support unsafe yaml test | ||
"-H:+ReportExceptionStackTraces" | ||
"--verbose" | ||
"--no-fallback" | ||
"-cp" classpath | ||
(str "-J-Xmx" native-image-xmx) | ||
entry-class]] | ||
(t/shell native-image-cmd))) | ||
|
||
(defn humanize-bytes [bytes] | ||
(let [units ["bytes" "KB" "MB" "GB"] | ||
max-exponent (dec (count units)) | ||
base 1024 | ||
exponent (if (zero? bytes) | ||
0 | ||
(int (math/floor (/ (math/log bytes) (math/log base))))) | ||
exponent (if (> exponent max-exponent) | ||
max-exponent | ||
exponent) | ||
in-bytes (format "%,d bytes" bytes)] | ||
(if (zero? exponent) | ||
in-bytes | ||
(format "%.2f %s (%s)" | ||
(/ bytes (math/pow base exponent)) | ||
(units exponent) | ||
in-bytes)))) | ||
|
||
(defn -main [& _args] | ||
(let [native-image-xmx "6g" | ||
target-path "target" | ||
target-exe "clj-yaml-test" | ||
graal-native-image (find-graal-native-image) | ||
reflection-config "target/reflect-config.json"] | ||
(status/line :head "Creating native image for test") | ||
(status/line :detail "java -version") | ||
(t/shell "java -version") | ||
(status/line :detail (str "\nnative-image max memory: " native-image-xmx)) | ||
(fs/create-dirs target-path) | ||
(status/line :head "Creating clj-yaml jar to test against") | ||
(t/clojure "-T:build jar") | ||
(status/line :head "Generating reflection config to support unsafe tests") | ||
(generate-reflection-config reflection-config) | ||
(status/line :head "AOT Compiling test sources") | ||
(t/clojure "-T:build compile-clj-for-native-test") | ||
(let [classpath (get-classpath)] | ||
(run-native-image {:graal-native-image graal-native-image | ||
:reflection-config reflection-config | ||
:target-path target-path | ||
:target-exe target-exe | ||
:classpath classpath | ||
:native-image-xmx native-image-xmx | ||
:entry-class "clj_yaml.native_test_runner"})) | ||
(status/line :head "Native image built") | ||
(let [full-target-exe (fs/which (fs/file target-path target-exe))] | ||
(status/line :detail "built: %s, %s" full-target-exe (humanize-bytes (fs/size full-target-exe))) | ||
(status/line :head "Running tests natively") | ||
(t/shell full-target-exe))) | ||
nil) | ||
|
||
(when (= *file* (System/getProperty "babashka.file")) | ||
(apply -main *command-line-args*)) | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
(ns clj-yaml.native-test-runner | ||
"Test runner used for Graal native image tests. | ||
Namespace cannot be automatically discovered during a native image test, | ||
so we specify them explicitly so that they will be compiled in. | ||
Any new test namespaces will need to be manually added." | ||
(:gen-class) | ||
(:require | ||
[clojure.test :as t] | ||
[clj-yaml.core-test])) | ||
|
||
(defn | ||
-main | ||
[& _args] | ||
(println "clojure version" (clojure-version)) | ||
(println "java version" (System/getProperty "java.version")) | ||
(println | ||
"running native?" | ||
(= "executable" (System/getProperty "org.graalvm.nativeimage.kind"))) | ||
(let | ||
[{:keys [fail error]} | ||
(apply | ||
t/run-tests | ||
'(clj-yaml.core-test))] | ||
(System/exit (if (zero? (+ fail error)) 0 1)))) |