Skip to content
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

Accept compiler options when building app #32

Merged
merged 5 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ A containerization tool for Clojure applications. It uses [Google Jib](https://g

## Usage

> `build`:

Build a Clojure application

| Option | Default | Description |
| -- | -- | -- |
| `-c` `--classpath PATHS` | `--` | Directories and zip/jar files on the classpath in the same format expected by the java command |
| `-s` `--source-path PATH` | `--` | Directories containing source files. This option can be repeated many times |
| `-m` `--main-class NAMESPACE` | `--` | Namespace that contains the application's entrypoint, with a :gen-class directive and a -main function |
| `-r` `--resource-path PATH` | `--` | Directories containing resource files. This option can be repeated many times |
| `-o` `--output PATH` | `--` | Directory where the application's files will be written to |
| `-C` `--compiler-options OPTIONS` | No | Options provided to the Clojure compiler, see `clojure.core/*compiler-options*` |

> `containerize`:

Containerize a Clojure application
Expand All @@ -24,6 +37,7 @@ Containerize a Clojure application
| `-s` `--source-path PATH` | `--` | Directories containing source files. This option can be repeated many times |
| `-r` `--resource-path PATH` | `--` | Directories containing resource files. This option can be repeated many times |
| `-u` `--user USER` | `root` | Define the default user for the image |
| `-C` `--compiler-options OPTIONS` | `nil` | Options provided to the Clojure compiler, see `clojure.core/*compiler-options*` |

> `image`:

Expand Down
18 changes: 12 additions & 6 deletions src/vessel/builder.clj
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@
"Compiles the main-ns by writing compiled .class files to target-dir.

Displays a spin animation during the process."
[^Symbol main-ns ^Sequential classpath source-paths ^File target-dir]
[^Symbol main-ns ^Sequential classpath source-paths ^File target-dir compiler-options]
(let [forms `(try
(binding [*compile-path* ~(str target-dir)]
(binding [*compile-path* ~(str target-dir)
*compiler-options* (merge *compiler-options* ~compiler-options)]
(clojure.core/compile (symbol ~(name main-ns))))
(catch Throwable err#
(println)
Expand Down Expand Up @@ -103,11 +104,11 @@
Returns a map of compiled class files (as instances of
java.io.File) to their sources (instances of java.io.File as well
representing directories or jar files on the classpath)."
[classpath-files ^Symbol main-class source-paths ^File target-dir]
[classpath-files ^Symbol main-class source-paths ^File target-dir compiler-options]
(let [namespaces (find-namespaces-on-classpath classpath-files)
classes-dir (misc/make-dir target-dir "classes")
classpath (cons classes-dir classpath-files)
_ (do-compile main-class classpath source-paths classes-dir)]
_ (do-compile main-class classpath source-paths classes-dir compiler-options)]
(reduce (fn [result ^File class-file]
(let [source-file (or (get-class-file-source namespaces (misc/relativize class-file classes-dir))
;; Defaults to the first element of source-paths if the class file doesn't match any known source.
Expand Down Expand Up @@ -230,16 +231,21 @@
* :target-dir (java.io.File) an existing directory where the
application's files will be written to.

And it accepts the following optional keys:

* :compiler-options (map) options for the Clojure compiler, refer
to `clojure.core/*compiler-options*` for the supported keys.

Returns a map containing the following namespaced keys:
* :app/classes - a map from target files (compiled class files and
resources) to their source classpath root (either directories or jar files present
on the classpath);
* :app/lib - a sequence of java.io.File objects containing libraries
that the application depends on."
[{:keys [classpath-files ^Symbol main-class resource-paths source-paths ^File target-dir]}]
[{:keys [classpath-files ^Symbol main-class resource-paths source-paths ^File target-dir compiler-options]}]
{:pre [classpath-files main-class source-paths target-dir]}
(let [web-inf (misc/make-dir target-dir "WEB-INF")
classes (compile classpath-files main-class source-paths web-inf)
classes (compile classpath-files main-class source-paths web-inf compiler-options)
dirs+jar-files (set/union resource-paths (set (vals classes)))
libs (misc/filter-files (set/difference (set classpath-files) dirs+jar-files))
resource-files (copy-files dirs+jar-files web-inf)]
Expand Down
15 changes: 14 additions & 1 deletion src/vessel/program.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns vessel.program
(:gen-class)
(:require [clojure.java.io :as io]
(:require [clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as string]
[vessel.api :as api]
[vessel.cli :as cli]
Expand Down Expand Up @@ -50,6 +51,12 @@
:desc "Directory where the application's files will be written to"
:parse-fn io/file
:validate cli/file-or-dir-must-exist]
["-C" "--compiler-options OPTIONS"
:id :compiler-options
:desc "Options provided to the Clojure compiler, see clojure.core/*compiler-options*"
:default nil
:parse-fn edn/read-string
:validate [#(or (nil? %) (map? %)) "Compiler options must be a valid Clojure map"]]
miorimmax marked this conversation as resolved.
Show resolved Hide resolved
verbose]}

"containerize"
Expand Down Expand Up @@ -115,6 +122,12 @@
:id :user
:desc "Define the default user for the image"
:default "root"]
["-C" "--compiler-options OPTIONS"
:id :compiler-options
:desc "Options provided to the Clojure compiler, see clojure.core/*compiler-options*"
:default nil
:parse-fn edn/read-string
:validate [#(or (nil? %) (map? %)) "Compiler options must be a valid Clojure map"]]
verbose]}

"image"
Expand Down
19 changes: 19 additions & 0 deletions test/unit/vessel/builder_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[matcher-combinators.test :refer [match?]]
[vessel.builder :as builder]
[vessel.misc :as misc]
[vessel.sh :as sh]
[vessel.test-helpers :refer [classpath ensure-clean-test-dir]])
(:import java.io.File))

Expand Down Expand Up @@ -130,3 +131,21 @@
(is (thrown-match? clojure.lang.ExceptionInfo
#:vessel.error{:category :vessel/compilation-error}
(builder/build-app (assoc options :main-class 'my-app.compilation-error)))))))

(deftest use-provided-compiler-options-when-building-app-test
(let [project-dir (io/file "test/resources/my-app")
target (io/file "target/tests/builder-test/build-app-test")
classpath-files (map io/file (string/split (classpath project-dir) #":"))
options {:classpath-files classpath-files
:resource-paths #{(io/file project-dir "src")}
:source-paths #{(io/file project-dir "resources")}
:target-dir target
:main-class 'my-app.server
:compiler-options {:direct-linking true
:testing? true}}
sh-args (atom [])]
(with-redefs [sh/javac (constantly nil)
sh/clojure #(reset! sh-args [%1 %2 %3])]
(builder/build-app options))

(is (re-matches #".*clojure\.core/\*compiler-options\* \(clojure\.core/merge clojure\.core/\*compiler-options\* \{:direct-linking true, :testing\? true\}\).*" (last @sh-args)))))