Skip to content
This repository has been archived by the owner on Feb 24, 2023. It is now read-only.

Commit

Permalink
prep for v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
seancorfield committed Sep 16, 2021
1 parent af16cd3 commit e9f027d
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 52 deletions.
11 changes: 7 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
.calva/output-window/
.classpath
.clj-kondo/.cache
.cpcache
.eastwood
.factorypath
.hg/
.hgignore
.java-version
.lein-*
.lsp/.cache
.lsp/sqlite.db
.nrepl-history
.nrepl-port
.project
.rebel_readline_history
Expand All @@ -16,9 +22,6 @@
*.jar
*.swp
*~
/checkouts
/classes
/classes
/clojure_test_*
/cljs-test-runner-out
/derby.log
/target
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

* v0.2.0 -- 2021-09-15
* Address #3 by adding an `uber` task which includes the log4j2 plugins cache conflict handler.
* Added support for many more options that `tools.build` tasks accept.
* Overhaul/expansion of docstrings.
* Update `tools.build` to v0.4.0 801a22f.

* v0.1.3 26b884c -- 2021-09-07
* Update `tools.build` to v0.2.2 3049217.

Expand Down
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ your `:build` alias can just be:

```clojure
:build {:deps {io.github.seancorfield/build-clj
{:git/tag "v0.1.3" :git/sha "26b884c"}}
{:git/tag "v0.2.0" :git/sha "..."}}
:ns-default build}
```

Expand All @@ -36,9 +36,11 @@ _[Several functions in `clojure.tools.build.api` return `nil` instead]_
* `clean` -- clean the target directory,
* `deploy` -- deploy to Clojars,
* `jar` -- build the (library) JAR and `pom.xml` files,
* `uber` -- build the (application) uber JAR, with optional `pom.xml` file creation and/or AOT compilation,
* `run-tests` -- run the project's tests.

For `deploy` and `jar`, you must provide at least `:lib` and `:version`.
For `uber`, you must provide at least `:lib` for the name of the JAR file.
Everything else has "sane" defaults, but can be overridden.

You might typically have the following tasks in your `build.clj`:
Expand All @@ -57,6 +59,17 @@ You might typically have the following tasks in your `build.clj`:
(bb/deploy)))
```

Or if you are working with an application, you might have:

```clojure
(defn ci "Run the CI pipeline of tests (and build the uberjar)." [opts]
(-> opts
(assoc :lib lib :main main)
(bb/run-tests)
(bb/clean)
(bb/uber)))
```

In addition, there is a `run-task` function that takes an options hash
map and a vector of aliases. This runs an arbitrary Clojure main function,
determined by those aliases, in a subprocess. `run-tests` uses this by
Expand Down Expand Up @@ -110,10 +123,11 @@ The following defaults are provided:
* `:target` -- `"target"`,
* `:basis` -- `(create-basis {:project "deps.edn"}`,
* `:class-dir` -- `(str target "/classes")`,
* `:jar-file` -- `(format \"%s/%s-%s.jar\" target lib version)`.
* `:jar-file` -- `(format \"%s/%s-%s.jar\" target lib version)`,
* `:uber-file` -- `(format \"%s/%s-%s.jar\" target lib version)` if `:version` is provided, else `(format \"%s/%s-standalone.jar\" target lib)`.

For the functions defined in `org.corfield.build`, you can override
the defaults as follows:
the high-level defaults as follows:

* `clean`
* `:target`,
Expand All @@ -122,11 +136,17 @@ the defaults as follows:
* `:target`, `:class-dir`, `:jar-file`,
* `jar`
* Requires: `:lib` and `:version`,
* `:target`, `:class-dir`, `:basis`, `:scm`, `:src-dirs`, `:tag` (defaults to `(str "v" version)`), `:jar-file`,
* `:target`, `:class-dir`, `:basis`, `:resource-dirs`, `:scm`, `:src-dirs`, `:tag` (defaults to `(str "v" version)`), `:jar-file`,
* `uber`
* Requires: `:lib`,
* `:target`, `:class-dir`, `:basis`, `:compile-opts`, `:main`, `:ns-compile`, `:resource-dirs`, `:scm`, `:src-dirs`, `:tag` (defaults to `(str "v" version)` if `:version` provided), `:uber-file`, `:version`
* `run-tests`
* `:aliases` -- for any additional aliases beyond `:test` which is always added,
* Also accepts any options that `run-task` accepts.

See the docstrings of those task functions for more detail on which options
they can also accept and which additional defaults they offer.

As noted above, `run-task` takes an options hash map and a vector of aliases.
The following options can be provided to `run-task` to override the default
behavior:
Expand Down
3 changes: 2 additions & 1 deletion deps.edn
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{:deps
{io.github.clojure/tools.build {:git/tag "v0.2.2" :git/sha "3049217"}
{io.github.clojure/tools.build {:git/tag "v0.4.0" :git/sha "801a22f"}
io.github.seancorfield/build-uber-log4j2-handler {:git/tag "v0.1.0" :git/sha "ab8e499"}
io.github.slipset/deps-deploy {:sha "b4359c5d67ca002d9ed0c4b41b710d7e5a82e3bf"}}}
213 changes: 170 additions & 43 deletions src/org/corfield/build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,86 +3,212 @@
(ns org.corfield.build
"Common build utilities.
The following defaults are provided:
The following high-level defaults are provided:
:target \"target\",
:basis (create-basis {:project \"deps.edn\"},
:class-dir (str target \"/classes\"),
:jar-file (format \"%s/%s-%s.jar\" target lib version)
:jar-file (format \"%s/%s-%s.jar\" target lib version),
:uber-file (format \"%s/%s-%s.jar\" target lib version)
or, if :version is not provided:
(format \"%s/%s-standalone.jar\" target lib)
You are expected to provide :lib and :version as needed.
The following build functions are provided, with the
The following build task functions are provided, with the
specified required and optional hash map options:
clean -- opt :target,
deploy -- req :lib, :version
opt :target, :class-dir, :jar-file
(see docstring for additional options)
jar -- req :lib, :version
opt :target, :class-dir, :basis, :scm, :src-dirs, :tag, :jar-file,
opt :target, :class-dir, :basis, :scm, :src-dirs,
:resource-dirs, :tag, :jar-file
(see docstring for additional options)
uber -- req :lib
opt :target, :class-dir, :basis, :scm, :src-dirs,
:resource-dirs, :tag, :uber-file, :version
(see docstring for additional options)
run-task -- [opts aliases]
opt :java-opts -- defaults to :jvm-opts from aliases
:jvm-opts -- added to :java-opts
:main -- defaults to clojure.main
:main-args -- defaults to :main-opts from aliases
:main-opts --
:main-opts -- added to :main-args
run-tests -- opt :aliases (plus run-task options)
invokes (run-task opts (into [:test] aliases))
All of the above return the opts hash map they were passed
(unlike some of the functions in clojure.tools.build.api)."
(:require [clojure.tools.build.api :as b]
(unlike some of the functions in clojure.tools.build.api).
The following low-level defaults are also provided to make
it easier to call the task functions here:
:ns-compile if :main is provided and :sort is not, this
defaults to the :main namespace (class),
:scm if :tag is provided, that is used here, else
if :version is provided, that is used for :tag
here with \"v\" prefixed,
:src-dirs [\"src\"]
:src+dirs this is a synthetic option that is used for the
file/directory copying that is part of `jar` and
`uber` and it is computed as :src-dirs plus
:resource-dirs, essentially, with the former
defaulted as noted above and the latter defaulted
to [\"resources\"] just for the copying but otherwise
has no default (for `tools.build/write-pom`)."
(:require [clojure.string :as str]
[clojure.tools.build.api :as b]
[clojure.tools.deps.alpha :as t]
[deps-deploy.deps-deploy :as dd]))
[deps-deploy.deps-deploy :as dd]
[org.corfield.log4j2-conflict-handler
:refer [log4j2-conflict-handler]]))

(defn- default-target
[target]
(or target "target"))

(defn- default-basis
[basis]
(or basis (b/create-basis {:project "deps.edn"})))

(def ^:private default-target "target")
(def ^:private default-basis (b/create-basis {:project "deps.edn"}))
(defn- default-class-dir [target] (str target "/classes"))
(defn- default-jar-file [target lib version]
(format "%s/%s-%s.jar" target (name lib) version))
(defn- default-class-dir
[class-dir target]
(or class-dir (str (default-target target) "/classes")))

(defn- default-jar-file
[target lib version]
(format "%s/%s-%s.jar" (default-target target) (name lib) version))

(defn clean
"Remove the target folder."
[{:keys [target] :as opts}]
(println "\nCleaning target...")
(b/delete {:path (or target default-target)})
(b/delete {:path (default-target target)})
opts)

(defn- jar-opts
"Provide sane defaults for jar/uber tasks.
:lib is required, :version is optional for uber, everything
else is optional."
[{:keys [basis class-dir conflict-handlers jar-file lib
main ns-compile resource-dirs scm sort src-dirs tag
target uber-file version]
:as opts}]
(let [scm-default (cond tag {:tag tag}
version {:tag (str "v" version)})
version (or version "standalone")
xxx-file (default-jar-file target lib version)]
(assoc opts
:basis (default-basis basis)
:class-dir (default-class-dir class-dir target)
:conflict-handlers
(merge log4j2-conflict-handler conflict-handlers)
:jar-file (or jar-file xxx-file)
:ns-compile (or ns-compile (when (and main (not sort))
[main]))
:scm (merge scm-default scm)
:src-dirs (or src-dirs ["src"])
:src+dirs (into src-dirs (or resource-dirs ["resources"]))
:uber-file (or uber-file xxx-file))))

(defn jar
"Build the library JAR file.
Requires: lib, version"
[{:keys [target class-dir lib version basis scm src-dirs tag jar-file] :as opts}]
Requires: :lib, :version
Accepts any options that are accepted by:
* tools.build/write-pom
* tools.build/jar
Writes pom.xml into META-INF in the :class-dir, then
copies :src-dirs + :resource-dirs into :class-dir, then
builds :jar-file into :target (directory)."
{:arglists '([{:keys [lib version
basis class-dir jar-file main manifest repos
resource-dirs scm src-dirs src-pom tag target]}])}
[{:keys [lib version] :as opts}]
(assert (and lib version) "lib and version are required for jar")
(let [target (or target default-target)
class-dir (or class-dir (default-class-dir target))
basis (or basis default-basis)
src-dirs (or src-dirs ["src"])
tag (or tag (str "v" version))
jar-file (or jar-file (default-jar-file target lib version))]
(let [{:keys [class-dir jar-file src+dirs] :as opts}
(jar-opts opts)]
(println "\nWriting pom.xml...")
(b/write-pom {:class-dir class-dir
:lib lib
:version version
:scm (cond-> (or scm {})
tag (assoc :tag tag))
:basis basis
:src-dirs src-dirs})
(println "Copying src...")
(b/copy-dir {:src-dirs src-dirs
(b/write-pom opts)
(println "Copying" (str (str/join ", " src+dirs) "..."))
(b/copy-dir {:src-dirs src+dirs
:target-dir class-dir})
(println "Building jar" (str jar-file "..."))
(b/jar opts))
opts)

(defn uber
"Build the application uber JAR file.
Requires: :lib
Accepts any options that are accepted by:
* `tools.build/write-pom`
* `tools.build/compile-clj`
* `tools.build/uber`
The uber JAR filename is derived from :lib,
and :version if provided.
If :version is provided, writes pom.xml into
META-INF in the :class-dir, then
Compiles :src-dirs into :class-dir, then
copies :src-dirs and :resource-dirs into :class-dir, then
builds :uber-file into :target (directory)."
{:argslists '([{:keys [lib
basis class-dir compile-opts filter-nses
ns-compile repos resource-dirs scm sort
src-dirs src-pom tag target uber-file version]}])}
[{:keys [lib] :as opts}]
(assert lib ":lib is required for uber")
(let [{:keys [class-dir ns-compile sort src-dirs src+dirs uber-file version]
:as opts}
(jar-opts opts)]
(println (assoc opts :basis "{...}"))
(if version
(do
(println "\nWriting pom.xml...")
(b/write-pom opts))
(println "\nSkipping pom.xml because :version was omitted..."))
(println "Copying" (str (str/join ", " src+dirs) "..."))
(b/copy-dir {:src-dirs src+dirs
:target-dir class-dir})
(println (str "Building jar " jar-file "..."))
(b/jar {:class-dir class-dir
:jar-file jar-file}))
(if (or ns-compile sort)
(do
(println "Compiling" (str (str/join ", " src-dirs) "..."))
(b/compile-clj opts))
(println "Skipping compilation because :main, :ns-compile, and :sort were omitted..."))
(println "Building uberjar" (str uber-file "..."))
(b/uber opts))
opts)

(defn deploy
"Deploy the JAR to Clojars.
Requires: lib, version"
[{:keys [target class-dir lib version jar-file] :as opts}]
(assert (and lib version) "lib and version are required for deploy")
(let [target (or target default-target)
class-dir (or class-dir (default-class-dir target))
Requires: :lib, :version
Accepts any options that are accepted by:
* `deps-deploy/deploy`
If :artifact is provided, it will be used for the deploy,
else :jar-file will be used (making it easy to thread
options through `jar` and `deploy`, specifying just :jar-file
or relying on the default value computed for :jar-file)."
{:arglists '([{:keys [lib version
artifact class-dir installer jar-file pom-file target]}])}
[{:keys [lib version class-dir jar-file target] :as opts}]
(assert (and lib version) ":lib and :version are required for deploy")
(let [target (default-target target)
class-dir (default-class-dir class-dir target)
jar-file (or jar-file (default-jar-file target lib version))]
(dd/deploy (merge {:installer :remote :artifact jar-file
:pom-file (b/pom-path {:lib lib :class-dir class-dir})}
Expand All @@ -92,11 +218,12 @@
(defn run-task
"Run a task based on aliases.
If :main-args is not provided and not :main-opts are found
If :main-args is not provided and no :main-opts are found
in the aliases, default to the Cognitect Labs' test-runner."
[{:keys [java-opts jvm-opts main main-args main-opts] :as opts} aliases]
(println "\nRunning task for:" aliases)
(let [basis (b/create-basis {:aliases aliases})
(let [task (str/join ", " (map name aliases))
_ (println "\nRunning task for:" task)
basis (b/create-basis {:aliases aliases})
combined (t/combine-aliases basis aliases)
cmds (b/java-command
{:basis basis
Expand All @@ -109,7 +236,7 @@
main-opts)})
{:keys [exit]} (b/process cmds)]
(when-not (zero? exit)
(throw (ex-info (str "Task failed for: " aliases) {}))))
(throw (ex-info (str "Task failed for: " task) {}))))
opts)

(defn run-tests
Expand Down

0 comments on commit e9f027d

Please sign in to comment.