Want this course?
Boot and Dependencies
Course: JVM Fundamentals for Clojure
Learn how to manage Clojure dependencies using Boot.
Whoa-kay, now we're gonna be talking about dependencies with Boot. Managing dependencies with Boot is very similar to Leiningen but it has some differences. So as you may know, Boot runs... The dependencies can be loaded at runtime, so there is no separate like, project file that describes all the options for the project. So you can just add dependencies here using this set-env command.
Most Boot projects have a bill.boot file, which is what I've got open here. And that's what describes all the Boot tasks that you wanna be able to run. So this one has some dependencies and you notice that they look very much like Leiningen dependencies. They've got the same structure, using a symbol with a name space and a name. They've got the version number in a version string. And then scope, scope is... You can do that in Leiningen too.
So the dependencies look very much the same. You use a set-env to add the dependencies. Now, we might wanna do some of the same things that we do normally in Leiningen, which is, for instance, look at this. You can list all of your dependencies. So that is actually Boot show -d. Now make a tree, nice looking tree, out of all your dependencies. There we go. And we see the same thing, we've got the top level dependencies along the left hand edge, and the transitive dependencies in a tree format.
Now if you do line show -p, you will get all of the conflicts. There we go. So we have check marks where there's no problem, where it resolved it itself. There's a warning, a, you know, what is that? Exclamation point, where it thinks that there's something you need to do. So this is saying hey, look, this closure-compiler-externs was required by both clojurescript and doo and it had two different versions, right? So this one it says there's no problem so you can probably leave it. Or you can go through all of these and add the exclusions, et cetera, just like in the Leiningen example.
So Boot also uses the .m2 directory, which I'll show you again. The .m2 directory is like the common place where Maven goes. It's because it's Maven 2, I believe, that standardized this directory format and location. So if you look in repository... Like, let's look up this dependency here, org.clojure/clojurescript. So the first thing we're gonna do is cd org, then cd clojure, then cd clojurescript.
Just go right down the name and split it on dots and slashes and you'll be good. Okay, so, and then the final one I don't believe will be spilt at all by dots. Not sure about that. Okay, so now we see all the versions. What version do we have here? Ooh, this long version. I'm gonna copy this 'cause I don't wanna retype it. Cd, boom, no such file directory. Huh, look at that. So is that... Not there? Huh, it's not there. Well, I guess that version is not there because I haven't downloaded it. Anyway, you see all the versions that are in the cache. Boot will download it when it needs it but since it doesn't, I haven't run that Boot command in awhile, it's not there.
So these are all the versions that are downloaded. You can go into any of them. 0.1450, okay. Now, look at this, we've got the JAR, we've got the POM, we've also got SHAs of each so that we can make sure that we didn't have any errors downloading it or there wasn't a man-in-the-middle-attack or something. And there we go. We got all the stuff cached on our hard drives so you don't have to keep downloading it each time. I do wanna reiterate that Boot lets you add dependencies on the fly. It's one of the cool things. You know, it's kind of trying to go back to the days of Lisp where you just start up a REPL and you would never have to restart it. Which Leiningen unfortunately does not do. There's some hacks for it, but it doesn't work too well. But in Boot you just keep adding dependencies and it will download them. And in fact, each task is segregated, in terms of its class path and its dependencies, from the other tasks. Segregated tasks means each one could have its own set of dependencies and they could conflict, but they won't conflict because they're segregated.
They could have different versions for each task which is actually really nice. Going back to this, I just wanna go over this again that you have a symbol and then the version string and that's how Leiningen does it, that's how Boot does it. In fact, I'm not sure about this, but they might use the same underlying library that reads this format and goes and fetches stuff. Oh, another thing I wanna show which I didn't show in the other thing, in the Leiningen one, is on Maven Central, let's say I do org.clojure/clojure.
Okay, I'm gonna go to the latest version. Now look at this, this is the dependency information on this file. So here they're showing you the POM, it's not very easy to read, it's not very interesting. But let's look over here. Here's the Maven XML that goes in the POM for your project that depends on Clojure. But then there's all these other build systems that have their own format and syntax for all that stuff. And that's cool, it gives it to you all there. Even Scala, you can bring it in right there.
But look, Maven Central gives you the Leiningen one, which is also compatible with Boot. So I just think that that's really cool that Maven Central is actually recognizing that Clojure is a thing and has its own build syntax. And I don't know, I'm just amazed that Clojure is growing so much that this could actually be in here nowadays. So that's really cool. Scala, of course, is really big. I'm a little surprised but not that surprised. But Leiningen, come on, that's awesome.