Search code examples
clojurecompilationleiningen

When and how many times can a clojure file be evaluated with leiningen?


I found while adding warnings to code that writes macros that the body of a file was being executed twice during compilation. Is there a reason for this? Is this specific to leiningen? I can not reproduce this with (compile ...).

Simplified version:

(ns foo.core
    (:require foo.bar))

;; empty

(ns foo.bar)

(println "hello")

$ lein compile :all

Compiling foo.core

hello

Compiling foo.bar

hello

Further testing shows that the namespace is reloaded on top of itself during compile:

(ns foo.bar)

(declare wasd)
(println wasd)
(def wasd 2)

$ lein clean

$ lein compile :all

Compiling foo.core

#<Unbound Unbound: #'foo.bar/wasd>

Compiling foo.bar

2

In a more complicated case I have this happening during compile, and then once every time when run or started a repl from lein. I am not sure why. This is all with clojure 1.6 and leiningen 2.5.0.


Solution

  • Leiningen knows nothing about the structure of your project in terms of how namespaces relate to each-other. Consequently, when compiling a project, lein simply boots a JVM and forces each namespace to be loaded one at a time. This means that, as you noticed, namespaces will be reloaded causing the double evaluation behaviour you are noticing.

    In comparison, (clojure.core/compile) simply loads the targeted resource with clojure.core/*compile-files* bound. This will cause the targeted resource and all the resources it requires to be loaded and compiled to class-files. However, it will not traverse your entire project structure compiling all resources as Leiningen's compile operation does.