-
-
Notifications
You must be signed in to change notification settings - Fork 180
Boot for Leiningen Users
All of the different abstractions used to control how Leiningen works (plugins, profiles, middleware, injections, etc.) can all be implemented as boot tasks. This document shows some of the common patterns Leiningen users will be accustomed to and their boot equivalents.
The equivalent of Leiningen profiles and middleware in boot are tasks that modify the environment and return clojure.core/identity
, the no-op task middleware.
For example, a task to add the test
directory to the :source-paths
when running tests, similar to the test
profile in Leiningen:
(deftask testing
"Profile setup for running tests."
[]
(set-env! :source-paths #(conj % "test"))
identity)
Profiles are "activated" simply by adding them to the pipeline, for example:
$ boot testing run-tests
This is equivalent to Lein's
$ lein with-profile testing run-tests
The equivalent of lein pprint
in boot is:
boot show -e
At first glance, it seems like lein trampoline
and boot's pods
mechanism server a similar purpose. But really they serve very
distinct purposes. lein trampoline
is an optimization lein uses to
cache your project's classpath so that the lein program can do less
work before starting the project JVM.
Boot's pods mechanism on the other hand are intended to provide the classpath isolation that lein achieves by launching the project code in a separate JVM from the one lein itself is running in.
The difference is that boot pods are first-class and in-process. Since they're in the same process, and because they're first class you can have anonymous pods, you can put a pod in a future, etc. You can make functions that take pods as arguments and functions that return pods.
boot itself is a small java program distributed as an uberjar -
boot.sh
. This uberjar can be executed directly because we exploit a nice property of jar files - you can put random garbage at the front of a jar file and the jvm will still load it without problems. So we inject a shebang and a call to java -jar there.
The java program
boot.sh
provides a single class -boot.App
.boot.App
has static methods that provide amain()
entry point for the jar, and methods to create new pods. Boot runs all clojure code in pods so yourbuild.boot
script is actually running in a pod but your pod can accessboot.App
and use it to create new pods that it can evaluate expressions in. All pods communicate with each other viaboot.App
.
AAAA: So far I've ported `lein uberjar` to a boot.build file. But I still don't know how to port `lein run` and `lein run -m my.non-main.namespace` and `lein speclj`. That's what's keeping me from switching from Leiningen to Boot.
AAAA: I understand that `lein spec` needs a third party plugin to be created.
AAAA: But it would be nice if the Boot website or FAQ or wiki had some instructions on porting `lein uberjar`, `lein run`, and `lein run -m some.custom.namespace` to Boot from Leiningen.
...
AAAA: As it is, these are blockers so that I can't switch to Boot yet, even though I see that it would be more helpful for me than Leiningen.
...
CCCC: AAAA: does 'boot uber jar' produce an uberjar for you similar to lein uberjar?
AAAA: CCCC: I've gotten the `lein uberjar` part figured out (the exact details vary depending on project requirements); it's the rest I still don't have yet
CCCC: i haven't used lein in a while, can you describe what lein run is supposed to do?
BBBB: AAAA: boot does not have any dependencies of its own
BBBB: AAAA: re: your question about boot's deps vs your project deps
BBBB: AAAA: that's the point of having pods, it serves a similar purpose to lein's second jvm
BBBB: but more granular and first-class
AAAA: BBBB: At the very least it depends on clojure.core
BBBB: AAAA: not really, it doesn't bring in a clojure dependency in your project
AAAA: BBBB: but only if you're using Pods, right? otherwise it still does, right?
BBBB: clojure.core is *provided* at runtime by boot, but that doesn't have any restriction on your project
BBBB: AAAA: just do `boot pom -p foo -v 1.0` and inspect the pom.xml it generates
BBBB: you'll see no dependencies at all
BBBB: so if your project needs a clojure dependency you need to add it
BBBB: AAAA: your question about uberjar and lein run is here: https://github.com/adzerk-oss/boot-uberjar-example
BBBB: it addresses both of them
BBBB: boot has an "uber" task that can be composed with any packaging task, like jar, war, zip, whatever
BBBB: we've decoupled those
BBBB: and lein run is just making your own task that runs something
BBBB: AAAA: for more info about what gets packaged in your uberjar i recommend looking at `boot uber -h`
AAAA: Great thanks.
BBBB: AAAA: it would be very awesome if you would update the wiki with any information you think is helpful
BBBB: AAAA: https://github.com/boot-clj/boot/wiki/Boot-for-Leiningen-Users
BBBB: also, re: trampoline vs. pods
BBBB: the lein "trampoline" is not the same thing as pods at all
noprompt joined the chat room.
BBBB: trampoline is an optimization lein uses to cache classpath stuff
BBBB: running multiple jvms
BBBB: pods are first-class and in-process
BBBB: boot itself is a small java program
BBBB: distributed as an uberjar (boot.sh)
BBBB: this uberjar can be executed directly because we exploit a nice property of jar files---you can put random garbage at the front of a jar file and the jvm will still load it without problems
BBBB: so we inject a shebang and a call to java -jar there
BBBB: boot.sh, the java program, provides a single class, boot.App
BBBB: boot.App has static methods that provide a main() entry point for the jar, and methods to create new pods
BBBB: boot runs all clojure code in pods
BBBB: so your build.boot script is actually running in a po
BBBB: pod
BBBB: but your pod can access boot.App and use it to create new pods that it can evaluate expressions in
BBBB: all pods communicate with each other via boot.App
BBBB: this is very different from lein trampoline
BBBB: since they're in the same process, and becuase they're first class you can have anonymous pods, you can put a pod in a future, etc
BBBB: you can make functions that take pods as arguments and functions that return pods
You can find other developers and users in the #hoplon
channel on freenode IRC or the boot slack channel.
If you have questions or need help, please visit the Discourse site.
- Environments
- Boot environment
- Java environment
- Tasks
- Built-ins
- Third-party
- Tasks Options
- Filesets
- Target Directory
- Pods
- Boot Exceptions
- Configuring Boot
- Updating Boot
- Setting Clojure version
- JVM Options
- S3 Repositories
- Scripts
- Task Writer's Guide
- Require inside Tasks
- Boot for Leiningen Users
- Boot in Leiningen Projects
- Repl reloading
- Repository Credentials and Deploying
- Snippets
- Troubleshooting
- FAQ
- API docs
- Core
- Pod
- Util