This repository has been archived by the owner on Feb 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lifted from and tested against depstar, expectations, honeysql, and next.jdbc.
- Loading branch information
1 parent
91ff79d
commit fe2d586
Showing
4 changed files
with
299 additions
and
13 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 |
---|---|---|
@@ -1,14 +1,24 @@ | ||
pom.xml | ||
pom.xml.asc | ||
*.jar | ||
*.class | ||
/lib/ | ||
/classes/ | ||
/target/ | ||
/checkouts/ | ||
.lein-deps-sum | ||
.lein-repl-history | ||
.lein-plugins/ | ||
.lein-failures | ||
.classpath | ||
.clj-kondo/.cache | ||
.cpcache | ||
.eastwood | ||
.factorypath | ||
.java-version | ||
.lsp/sqlite.db | ||
.nrepl-port | ||
.cpcache/ | ||
.project | ||
.rebel_readline_history | ||
.settings | ||
.socket-repl-port | ||
.sw* | ||
.vscode | ||
*.class | ||
*.jar | ||
*.swp | ||
*~ | ||
/classes | ||
/classes | ||
/clojure_test_* | ||
/cljs-test-runner-out | ||
/derby.log | ||
/target |
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 |
---|---|---|
@@ -1,2 +1,156 @@ | ||
# build-clj | ||
|
||
Common build tasks abstracted into a library. | ||
|
||
Having implemented `build.clj` in several of my open source projects | ||
I found there was a lot of repetition across them, so I factored out | ||
the common functionality into this library. | ||
|
||
Since it depends on `tools.build` and | ||
[Erik Assum's `deps-deploy`](https://github.com/slipset/deps-deploy), | ||
your `:build` alias can just be: | ||
|
||
```clojure | ||
:build {:deps {io.github.seancorfield/build-clj | ||
{:git/tag "v0.1.0" :git/sha "..."}} | ||
:ns-default build} | ||
``` | ||
|
||
Your `build.clj` can start off as follows: | ||
|
||
```clojure | ||
(ns build | ||
(:require [clojure.tools.build.api :as b] | ||
[org.corfield.build :as bb])) | ||
|
||
(def lib 'myname/mylib) | ||
;; if you want a version of MAJOR.MINOR.COMMITS: | ||
(def version (format "1.0.%s" (b/git-count-revs nil))) | ||
``` | ||
|
||
The following common build tasks are provided, all taking an options | ||
hash map as the single argument _and returning that hash map unchanged_ | ||
so you can reliably thread the build tasks. | ||
_[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, | ||
* `run-tests` -- run the project's tests. | ||
|
||
For `deploy` and `jar`, you must provide at least `:lib` and `:version`. | ||
Everything else has "sane" defaults, but can be overridden. | ||
|
||
You might typically have the following tasks in your `build.clj`: | ||
|
||
```clojure | ||
(defn ci "Run the CI pipeline of tests (and build the JAR)." [opts] | ||
(-> opts | ||
(assoc :lib lib :version version) | ||
(bb/run-tests) | ||
(bb/clean) | ||
(bb/jar))) | ||
|
||
(defn deploy "Deploy the JAR to Clojars." [opts] | ||
(-> opts | ||
(assoc :lib lib :version version) | ||
(bb/deploy))) | ||
``` | ||
|
||
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 | ||
adding a `:test` alias and in the absence of any `:main-opts` behind those | ||
aliases, assumes it should run `cognitect.test-runner`'s `-main` function. | ||
|
||
If you want a `run-tests` task in your `build.clj`, independent of the `ci` | ||
task shown above, the following can be added: | ||
|
||
```clojure | ||
(defn run-tests "Run the tests." [opts] | ||
(-> opts (bb/run-tests))) | ||
``` | ||
|
||
`run-task` picks up `:jvm-opts` and `:main-opts` from the specified aliases | ||
and uses them as the `:java-args` and `:main-args` respectively in a call to | ||
`clojure.tools.build.api/java-command` to build the `java` command to run. | ||
By default, it runs `clojure.main`'s `-main` function with the specified | ||
`:main-args`. | ||
|
||
For example, if your `deps.edn` contains the following alias: | ||
|
||
```clojure | ||
:eastwood {:extra-deps {jonase/eastwood {:mvn/version "0.5.1"}} | ||
:main-opts ["-m" "eastwood.lint" "{:source-paths,[\"src\"]}"]} | ||
``` | ||
|
||
Then you can define an `eastwood` task in your `build.clj` file: | ||
|
||
```clojure | ||
(defn eastwood "Run Eastwood." [opts] | ||
(-> opts (bb/run-task [:eastwood]))) | ||
``` | ||
|
||
Or you could just make it part of your `ci` pipeline without adding that function: | ||
|
||
```clojure | ||
(defn ci "Run the CI pipeline of tests (and build the JAR)." [opts] | ||
(-> opts | ||
(assoc :lib lib :version version) | ||
(bb/run-task [:eastwood]) | ||
(bb/run-tests) | ||
(bb/clean) | ||
(bb/jar))) | ||
``` | ||
|
||
## Defaults | ||
|
||
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)`. | ||
|
||
For the functions defined in `org.corfield.build`, you can override | ||
the defaults as follows: | ||
|
||
* `clean` | ||
* `:target`, | ||
* `deploy` | ||
* Requires: `:lib` and `:version`, | ||
* `:target`, `:class-dir`, `:jar-file`, | ||
* `jar` | ||
* Requires: `:lib` and `:version`, | ||
* `:target`, `:class-dir`, `:basis`, `:src-dirs`, `:tag` (defaults to `(str "v" version)`), `:jar-file`, | ||
* `run-tests` | ||
* `:aliases` -- for any additional aliases beyond `:test` which is always added, | ||
* Also accepts any options that `run-task` accepts. | ||
|
||
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: | ||
|
||
* `:java-opts` -- used _instead of_ `:jvm-opts` from the aliases, | ||
* `:jvm-opts` -- used _in addition to_ the `:java-opts` vector or _in addition to_ `:jvm-opts` from the aliases, | ||
* `:main` -- used _instead of_ `'clojure.main` when building the `java` command to run, | ||
* `:main-args` -- used _instead of_ `:main-opts` from the aliases, | ||
* `:main-opts` -- used _in addition to_ the `:main-args` vector or _in addition to_ `:main-opts` from the aliases. | ||
|
||
> Note: if `:main-args` is not provided and there are no `:main-opts` in the aliases provided, the default will be `["-m" "cognitect.test-runner"]` to ensure that `run-tests` works by default without needing `:main-opts` in the `:test` alias (since it is common to want to start a REPL with `clj -A:test`). | ||
## Projects Using `build-clj` | ||
|
||
You can see how `build-clj` is used to reduce boilerplate in the | ||
`build.clj` file of the following projects: | ||
|
||
* [`depstar`](https://github.com/seancorfield/depstar/blob/develop/build.clj) | ||
* [`expectations`](https://github.com/clojure-expectations/clojure-test/blob/develop/build.clj) | ||
* [`honeysql`](https://github.com/seancorfield/honeysql/blob/develop/build.clj) | ||
* [`next.jdbc`](https://github.com/seancorfield/next-jdbc/blob/develop/build.clj) | ||
|
||
# License | ||
|
||
Copyright © 2021 Sean Corfield | ||
|
||
Distributed under the Apache Software License version 2.0. |
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,3 @@ | ||
{:deps | ||
{io.github.clojure/tools.build {:git/tag "v0.1.9" :git/sha "6736c83"} | ||
io.github.slipset/deps-deploy {:sha "b4359c5d67ca002d9ed0c4b41b710d7e5a82e3bf"}}} |
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,119 @@ | ||
;; copyright (c) 2021 sean corfield, all rights reserved. | ||
|
||
(ns org.corfield.build | ||
"Common build utilities. | ||
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) | ||
You are expected to provide :lib and :version as needed. | ||
The following build 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 | ||
jar -- req :lib, :version | ||
opt :target, :class-dir, :basis, :src-dirs, :tag, :jar-file, | ||
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 -- | ||
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] | ||
[clojure.tools.deps.alpha :as t] | ||
[deps-deploy.deps-deploy :as dd])) | ||
|
||
(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 clean | ||
"Remove the target folder." | ||
[{:keys [target] :as opts}] | ||
(println "\nCleaning target...") | ||
(b/delete {:path (or target default-target)}) | ||
opts) | ||
|
||
(defn jar | ||
"Build the library JAR file. | ||
Requires: lib, version" | ||
[{:keys [target class-dir lib version basis src-dirs tag jar-file] :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))] | ||
(println "\nWriting pom.xml...") | ||
(b/write-pom {:class-dir class-dir | ||
:lib lib | ||
:version version | ||
:scm {:tag tag} | ||
:basis basis | ||
:src-dirs src-dirs}) | ||
(println "Copying src...") | ||
(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})) | ||
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)) | ||
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})} | ||
opts))) | ||
opts) | ||
|
||
(defn run-task | ||
"Run a task based on aliases. | ||
If :main-args is not provided and not :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}) | ||
combined (t/combine-aliases basis aliases) | ||
cmds (b/java-command | ||
{:basis basis | ||
:java-opts (into (or java-opts (:jvm-opts combined)) | ||
jvm-opts) | ||
:main (or 'clojure.main main) | ||
:main-args (into (or main-args | ||
(:main-opts combined) | ||
["-m" "cognitect.test-runner"]) | ||
main-opts)}) | ||
{:keys [exit]} (b/process cmds)] | ||
(when-not (zero? exit) | ||
(throw (ex-info (str "Task failed for: " aliases) {})))) | ||
opts) | ||
|
||
(defn run-tests | ||
"Run tests. | ||
Always adds :test to the aliases." | ||
[{:keys [aliases] :as opts}] | ||
(-> opts (run-task (into [:test] aliases)))) |