Leiningen 101 part II

Leiningen 101 part II

- 7 mins

In the last tutorial, we made our first steps with leiningen. In this chapter we will cover two important topics: project.clj structure and dependency management with this file.

project.clj file

When we create a project using lein, one of the files added by default is project.clj. This file is one of the most important because it could contain some relevant configurations. Going a little more beyond the basics, this file contains the call of a macro named defproject or a def with a project map defined. The source code for this macro can be found here.

Structure and most used parts

As we just mentioned, project.clj contains the macro defproject. This macro initially takes two arguments: the project groupId and the name using the format “<groupId/projectName>”. After these two parameters, we can include other :key value pairs for specific configurations, so we will mention some of them(most used):

Dependency Management

When I started this chain of posts, I mentioned one of the tasks that Leiningen performs is the Dependency Management.

Dependency Management is important because in almost all cases our projects will need other projects to add certain features otherwise, we would have to reinvent the wheel every time or copy and paste code in our project.

On the other hand, this part of the development life cycle can help us to make segmentation of certain dependency groups required for different environments, e.g. development, test. production, etc.

Tip here: We can use lein search $TERM to look for dependencies associated with $TERM in central repositories and clojar by default.

The fundamental keys used for dependency management in the project.clj file are: :dependencies, :plugins, :repositories, :plugin-repositories, :mirrors and :profiles. I will explain each of these keys below:

As we can see the structure is a vector of vectors and vectors are listed as [group-id/name version]. We can find internal keys like :exclusions to ignore from being included in our project’s classpath. Lein resolves dependencies transitively, for this reason, it is possible to find unwanted dependencies. These keywords are supported by Pomegranate, a library that works as Maven-resolver.

:repositories [["java.net" "https://download.java.net/maven/2"]
	["sonatype" "https://oss.sonatype.org/content/repositories/releases"]
	[...]]

Every subvector has a “common” pattern, [“repository name” “url”] but it can be changed by other pair [“repository name” {map of settings}]. This map of settings contains keywords such as :url, :snapshots, :sign-releases, :checksum, :update, :releases, etc. These settings provide specific information to Leiningen about the repositories registered.

:profiles {:debug {:debug true}
	:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
	:repl {:plugins [[cider/cider-nrepl "0.7.1"]]}
	{...}}

In this example we have three profiles: :debug, :1.9(Yes we can use version numbers as keywords) and :repl. The :debug profile has the :debug option enabled, to behavior related with :debug true will happens. the :1.9 profile contains the specific dependency of clojure 1.9 and :repl profile contains the cider-nrepl plugin.

Tip here: we can use any of these profiles with higher-order tasks using with-profiles.

Conclusion

The purpose of this post was to provide a guide about the structure of the main Leiningen configuration file a.k.a project.clj and take the opportunity to give some explanation about dependency management with Leiningen.

For more specific information about these topics please refer to sample.project.clj and leiningen oficial tutorial.

I hope you enjoyed the reading and please contact me for any comment.

Happy hacking!

Enyert Viñas

Enyert Viñas

Running to a world without side effects! Software developer. FP Enthusiast

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora