This file has been truncated. show original
## Boot and deps.edn
At some point, we all decided that scripting builds with executable code was a bad idea, so we tossed out makefiles in favor of specifying our builds in a data file (`package.json`, `build.xml`, `project.clj`, etc) and having a build tool do the heavy lifting. These data files could be leveraged by IDEs and other tools. When projects inevitably need to do things their build tool couldn't anticipate, they use plugins or bash scripts in order to...script their build with executable code. Oops.
The truth is, we never stopped scripting builds, we just made it more annoying. In Clojure land, the things Leiningen can't do just end up in a plugin or an ad hoc bash script. To make matters worse, the `project.clj` format isn't even technically static data, because it is [very willing](https://github.com/technomancy/leiningen/blob/c73d4557c21aac5955b3996f2c190a1425b02853/sample.project.clj#L12) to execute code. It is the worst of both worlds: more restrictive and idiosyncratic than normal code, yet still impossible for external tools to reliably parse. That sucks!
Perhaps in response to this, [Boot](http://boot-clj.com/) came along and offered a way to just script our builds directly using Clojure. Suddenly, it was trivial to do things that were painful when our builds were hidden behind the brittle abstraction of a "data" file. But as the author of the Cursive IDE [pointed out](https://www.reddit.com/r/Clojure/comments/4awi60/why_i_love_boot/d156ikm/), it is even harder for tools to parse a `build.boot` than a `project.clj`. That means it will be difficult and error-prone for Cursive to provide code completion to Boot projects. It also means that cool things like [Github's security alerts](https://github.com/blog/2470-introducing-security-alerts-on-github) will likely never be possible for Boot projects. That sucks!
It's pretty clear that both declarative and imperative build systems have flaws. What if there was a way to get the benefits of both? I want to specify dependencies declaratively, and script my builds imperatively. Trying to do these wildly different things the same way will always lead to problems.