Skip to content

Adapt to GraalVM v22 #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ jobs:
- 'graalvm'
- 'graalvm-community'
java-version:
- '17.0.8'
- '20.0.2'
- '22.0.1'
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ Single segment namespaces are problematic in general in Clojure and, because the
[clj-easy/graal-build-time] WARN: Single segment namespace found for class: digest__init.class. Because this class has no package, it cannot be registered for initialization at build time.
```

Starting with GraalVM v22, because it enables`--strict-image-heap` by default, you'll also see `native-image` fail your build when single segment namespaces are present.
See https://github.com/clj-easy/graal-build-time/issues/35[#35] for details if you are curious.

## Develop

Run `bb tasks` for all relevant project tasks.
Expand Down
7 changes: 6 additions & 1 deletion bb.edn
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
:task (do
(doseq [dir ["target" ".cpcache"]]
(fs/delete-tree dir))
(shell {:dir "test-hello-world"} "bb clean"))}
(doseq [dir ["test-hello-world" "test-single-segment"]]
(shell {:dir dir} "bb clean")))}

compile-sources {:doc "Compile sources"
:task (if (seq (fs/modified-since bs/class-dir ["deps.edn" "src"]))
Expand All @@ -47,6 +48,10 @@
:task (shell {:dir "test-hello-world"}
"bb build")}

build-single-segment {:doc "Build jars, classes for single segment testing"
:task (shell {:dir "test-single-segment"}
"bb build")}

test {:doc "Runs tests"
:task (clojure "-X:test")}

Expand Down
3 changes: 3 additions & 0 deletions build-helper/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{:paths ["src"]
:deps {io.github.clojure/tools.build {:mvn/version "0.10.4"}
babashka/fs {:mvn/version "0.4.19"}}}
61 changes: 61 additions & 0 deletions build-helper/src/build_helper/core.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
(ns build-helper.core
"Reusable build support for internal test projects"
(:require
[clojure.string :as str]
[clojure.tools.build.api :as b]))

(defmacro with-err-str
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~@body
(str s#))))

(defn uber [{:keys [lib main uber-file]}]
(let [class-dir "target/classes"
src-dirs ["src"]
basis (b/create-basis)]
(println "Writing pom")
(->> (b/write-pom {:class-dir class-dir
:lib lib
:version "1.0.0"
:basis basis
:src-dirs ["src"]})
with-err-str
str/split-lines
;; Avoid confusing future me/you: suppress "Skipping coordinate" messages for our jars, we don't care, we are creating an uberjar
(remove #(re-matches #"^Skipping coordinate: \{:local/root .*target/(lib1|lib2|graal-build-time).jar.*" %))
(run! println))
(b/copy-dir {:src-dirs src-dirs
:target-dir class-dir})
(println "Compile sources to classes")
(b/compile-clj {:basis basis
:src-dirs src-dirs
:class-dir class-dir
:ns-compile [main]})
(println "Building uberjar" uber-file)
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis
:main main})))

(defn jar [{:keys [lib jar-file]}]
(let [class-dir "target/classes"
src-dirs ["src"]
basis (b/create-basis)]
(println "Writing pom")
(b/write-pom {:class-dir class-dir
:lib lib
:version "1.0.0"
:basis basis
:src-dirs ["src"]})
(b/copy-dir {:src-dirs src-dirs
:target-dir class-dir})
(println "Compile sources to classes")
(b/compile-clj {:basis basis
:src-dirs src-dirs
:class-dir class-dir})
(println "Building jar" jar-file)
(b/jar {:class-dir class-dir
:jar-file jar-file
:basis basis})))
44 changes: 4 additions & 40 deletions test-hello-world/build.clj
Original file line number Diff line number Diff line change
@@ -1,43 +1,7 @@
(ns build
(:refer-clojure :exclude [compile])
(:require
[clojure.string :as str]
[clojure.tools.build.api :as b]))

(def lib 'hello-world/hello-world)
(def class-dir "target/classes")
(def uber-file "target/hello-world.jar")
(def src-dirs ["src"])
(def basis (b/create-basis))

(defmacro with-err-str
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~@body
(str s#))))
(:require [build-helper.core :as bh]))

(defn uber [_]
(println "Writing pom")
(->> (b/write-pom {:class-dir class-dir
:lib lib
:version "1.0.0"
:basis basis
:src-dirs ["src"]})
with-err-str
str/split-lines
;; Avoid confusing future me/you: suppress "Skipping coordinate" messages for our jars, we don't care, we are creating an uberjar
(remove #(re-matches #"^Skipping coordinate: \{:local/root .*target/(lib1|lib2|graal-build-time).jar.*" %))
(run! println))
(b/copy-dir {:src-dirs src-dirs
:target-dir class-dir})
(println "Compile sources to classes")
(b/compile-clj {:basis basis
:src-dirs src-dirs
:class-dir class-dir
:ns-compile '[hello-world.main]})
(println "Building uberjar")
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis
:main 'hello-world.main}))
(bh/uber {:lib 'hello-world/hello-world
:main 'hello-world.main
:uber-file "target/hello-world.jar"}))
3 changes: 1 addition & 2 deletions test-hello-world/deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
:deps {lib1/lib1 {:local/root "lib1/target/lib1.jar"}
lib2/lib2 {:local/root "lib2/target/lib2.jar"}
clj-easy/graal-build-time {:local/root "target/graal-build-time.jar"}}
:aliases {:build {:deps {io.github.clojure/tools.build {:mvn/version "0.9.4"}
babashka/fs {:mvn/version "0.4.19"}}
:aliases {:build {:deps {clj-easy/build-helper {:local/root "../build-helper"}}
:ns-default build}}}
24 changes: 3 additions & 21 deletions test-hello-world/lib1/build.clj
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
(ns build
(:refer-clojure :exclude [compile])
(:require [clojure.tools.build.api :as b]))

(def lib 'gbt-test-org/lib1)
(def class-dir "target/classes")
(def jar-file "target/lib1.jar")
(def src-dirs ["src"])
(def basis (b/create-basis))
(:require [build-helper.core :as bh]))

(defn jar [_]
(b/write-pom {:class-dir class-dir
:lib lib
:version "1.0.0"
:basis basis
:src-dirs ["src"]})
(b/copy-dir {:src-dirs src-dirs
:target-dir class-dir})
(b/compile-clj {:basis basis
:src-dirs src-dirs
:class-dir class-dir})
(b/jar {:class-dir class-dir
:jar-file jar-file
:basis basis}))
(bh/jar {:lib 'gbt-test-org/lib1
:jar-file "target/lib1.jar"}))
2 changes: 1 addition & 1 deletion test-hello-world/lib1/deps.edn
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{:paths ["src"]
:aliases {:build {:deps {io.github.clojure/tools.build {:mvn/version "0.9.4"}}
:aliases {:build {:deps {clj-easy/build-helper {:local/root "../../build-helper"}}
:ns-default build}}}
24 changes: 3 additions & 21 deletions test-hello-world/lib2/build.clj
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
(ns build
(:refer-clojure :exclude [compile])
(:require [clojure.tools.build.api :as b]))

(def lib 'gbt-test-org/lib2)
(def class-dir "target/classes")
(def jar-file "target/lib2.jar")
(def src-dirs ["src"])
(def basis (b/create-basis))
(:require [build-helper.core :as bh]))

(defn jar [_]
(b/write-pom {:class-dir class-dir
:lib lib
:version "1.0.0"
:basis basis
:src-dirs ["src"]})
(b/copy-dir {:src-dirs src-dirs
:target-dir class-dir})
(b/compile-clj {:basis basis
:src-dirs src-dirs
:class-dir class-dir})
(b/jar {:class-dir class-dir
:jar-file jar-file
:basis basis}))
(bh/jar {:lib 'gbt-test-org/lib2
:jar-file "target/lib2.jar"}))
2 changes: 1 addition & 1 deletion test-hello-world/lib2/deps.edn
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{:paths ["src"]
:aliases {:build {:deps {io.github.clojure/tools.build {:mvn/version "0.9.4"}}
:aliases {:build {:deps {clj-easy/build-helper {:local/root "../../build-helper"}}
:ns-default build}}}
4 changes: 1 addition & 3 deletions test-hello-world/src/hello_world/main.clj
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
(ns hello-world.main
(:require [single-segment-example]
[hello.core]
(:require [hello.core]
[gbt-test-org.core]
[gbt-test-org.p2.core])
(:gen-class))

(defn -main []
;; sanity for test nses loaded and included
(single-segment-example/dummy)
(hello.core/dummy)
(gbt-test-org.core/dummy)
(gbt-test-org.p2.core/dummy)
Expand Down
8 changes: 0 additions & 8 deletions test-hello-world/src/single_segment_example.clj

This file was deleted.

45 changes: 45 additions & 0 deletions test-single-segment/bb.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{:tasks
{:requires ([babashka.fs :as fs]
[babashka.tasks :as tasks]
[clojure.string :as str])
:enter (when (not (str/starts-with? (:name (current-task)) "-"))
(println (format "-[test-single-segment %s]----" (:name (current-task)))))
:init (do
(defn clojure
"Clojure defaulting to stderr output"
[arg & args]
(apply tasks/clojure (str "-J-Dclojure.main.report=stderr " arg) args)))

-artifact "target/single-segment.jar"

clean
{:task (doseq [dir ["target" ".cpcache"]]
(fs/delete-tree dir))}

graal-build-time-jar
{:doc "Build and grab a copy of local graal build time jar from above."
:task (do
(shell {:dir ".."} "bb jar")
(let [jar-name (-> (shell {:out :string :dir ".."}
"bb jar-name")
:out
str/split-lines
last)]
(println "copying" jar-name)
(fs/create-dirs "target")
(fs/copy (str "../" jar-name)
"target/graal-build-time.jar"
{:replace-existing true})))}

build {:doc "Build classes and uberjar"
:depends [-artifact
graal-build-time-jar]
:task
(if (seq (fs/modified-since -artifact ["src"
"bb.edn"
"deps.edn"
"build.clj"]))
(do
(println "Building" -artifact)
(clojure "-T:build uber"))
(println -artifact "already built"))}}}
7 changes: 7 additions & 0 deletions test-single-segment/build.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(ns build
(:require [build-helper.core :as bh]))

(defn uber [_]
(bh/uber {:lib 'single-segment/single-segment
:main 'single-segment.main
:uber-file "target/single-segment.jar"}))
4 changes: 4 additions & 0 deletions test-single-segment/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:deps {org.clj-commons/digest {:mvn/version "1.4.100"}
clj-easy/graal-build-time {:local/root "target/graal-build-time.jar"}}
:aliases {:build {:deps {clj-easy/build-helper {:local/root "../build-helper"}}
:ns-default build}}}
7 changes: 7 additions & 0 deletions test-single-segment/src/single_segment/main.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(ns single-segment.main
"Exists to test our emitting of warning message for single segement namespaces"
(:require [digest]) ;; this deprecated ns is, as you can see, single segment
(:gen-class))

(defn -main []
(println "md5 digest for clojure" (digest/md5 "clojure")))
31 changes: 23 additions & 8 deletions test/clj_easy/graal_build_time/packages_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,41 @@
[clojure.java.io :as io]
[clojure.test :refer [deftest is testing]]))

(deftest package-list-test
(deftest hello-world-package-list-test
(-> (p/process ["bb" "build-hello-world"] {:inherit true})
(p/check))
(let [expected-packages "clojure, clj_easy.graal_build_time, gbt_test_org, hello, hello_world"
expected-warning #"^\[clj-easy/graal-build-time\] WARN: Single segment .* single_segment_example__init.class"]
(let [expected-packages "clojure, clj_easy.graal_build_time, gbt_test_org, hello, hello_world"]
(testing "packages from directory"
(is (= expected-packages
(-> (packages/-list (->> ["test-hello-world/target/classes"
"test-hello-world/lib1/target/lib1.jar"
"test-hello-world/lib2/target/lib2.jar"
"test-hello-world/target/graal-build-time.jar"]
(mapv #(.toPath (io/file %)))))
(packages/-listStr)))))
(testing "packages from jar"
(is (= expected-packages
(-> (packages/-list [(.toPath (io/file "test-hello-world/target/hello-world.jar"))])
(packages/-listStr)))))))

(deftest single-segment-warning-message-test
(-> (p/process ["bb" "build-single-segment"] {:inherit true})
(p/check))
(let [expected-packages "clojure, clj_easy.graal_build_time, single_segment"
expected-warning #"^\[clj-easy/graal-build-time\] WARN: Single segment .* digest__init.class"]
(testing "packages from directory"
(is (re-find
expected-warning
(with-out-str
(is (= expected-packages
(-> (packages/-list (->> ["test-hello-world/target/classes"
"test-hello-world/lib1/target/lib1.jar"
"test-hello-world/lib2/target/lib2.jar"
"test-hello-world/target/graal-build-time.jar"]
(-> (packages/-list (->> ["test-single-segment/target/classes"
"test-single-segment/target/graal-build-time.jar"]
(mapv #(.toPath (io/file %)))))
(packages/-listStr))))))))
(testing "packages from jar"
(is (re-find
expected-warning
(with-out-str
(is (= expected-packages
(-> (packages/-list [(.toPath (io/file "test-hello-world/target/hello-world.jar"))])
(-> (packages/-list [(.toPath (io/file "test-single-segment/target/single-segment.jar"))])
(packages/-listStr))))))))))
Loading