interstar
interstar

Reputation: 27186

How do I create a Clojure application with lein uberjar if I have a dependency in checkouts?

I have a Clojure application that is using a library which is symlinked from inside the "checkouts" directory.

This lets me work on both the app and the library at the same time. And lein knows how to compile and run the program without any problems.

But I want to make a standalone with lein uberjar, and it's complaining

Caused by: java.io.FileNotFoundException: Could not locate mylib/core__init.class, mylib/core.clj or mylib/core.cljc on classpath.

I assume that that is because mylib isn't mentioned in my project.clj file. It isn't, precisely because I want to use the version of mylib symlinked inside "checkouts".

But the uberjar command doesn't seem to be able to see it.

How can I solve this?

Upvotes: 2

Views: 1393

Answers (2)

user2609980
user2609980

Reputation: 10474

You can accomplish this by installing mylib in your local repository (~/.m2/repository).

  1. Run lein install in the dependent project to install it in your local repository.
  2. Add the project to :dependencies: in project.clj:

    [mylib "version"]

  3. Run lein uberjar in the main project.

The project will find the jar in your local repository.

/Edit

If you want to develop two libraries at the same time you can use a checkouts folder where checkouts contains a symlink to the dependent library.

mkdir checkouts
ln -nfs full-path-other-lib-dir full-path-checkouts-dir

Now changes in other-lib are immediately available in the main project.

See [https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies](the Leiningen checkouts documentation).

Upvotes: 1

Alan Thompson
Alan Thompson

Reputation: 29958

OK, it appears that the "checkouts" feature of lein works with lein test and lein run but not with lein uberjar.

I added the following to the local source code of a lib tupelo.core:

(def dummy-sample-data "Bogus!")

In the consuming project demo.core we can access the new Var:

(ns demo.core
  (:use tupelo.core tupelo.test))

(defn -main [& args]
  (println :foo-enter)
  (spyx dummy-sample-data)
  (println :foo-leave))

lein run produces:

:foo-enter
dummy-sample-data => "Bogus!"
:foo-leave

project.clj remains unchanged:

(defproject demo "0.1.0-SNAPSHOT"
  :license {:name "Eclipse Public License"
            :url  "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
     [criterium "0.4.5"]
     [org.clojure/math.combinatorics "0.1.6"]
     [org.clojure/clojure "1.10.1"]
     [prismatic/schema "1.1.12"]
     [tupelo "0.9.201"]
   <snip>

where "0.9.201" is the latest version of tupelo on Clojars. Checkouts looks like:

~/expr/demo > ls -ldF checkouts/*
lrwxrwxrwx 1 alan alan 17 May 12 13:57 checkouts/tupelo -> /home/alan/tupelo/

but uberjar fails:

~/expr/demo > lein clean ; lein uberjar
Compiling demo.core
Syntax error compiling at (demo/core.clj:6:3).
Syntax error compiling at (demo/core.clj:6:3).
Unable to resolve symbol: dummy-sample-data in this context

Full report at:
/tmp/clojure-10416346559924917196.edn
Compilation failed: Subprocess failed

Options

If you are wanting to deploy an application, you have 2 options:

  1. If the lib exists on Clojars or Maven, you should probably deploy a release there before making a uberjar. If the lib is not ready for Clojars or Maven, maybe you aren't ready to use it in a uberjar...?

  2. Simply copy the source tree of mylib (or use a symlink!) under the ./src dir in your project. You'll also have to copy in the dependencies into myproj/project.clj. You are effectively merging myproj and mylib, at least temporarily with this approach. If the are coupled tightly enough to require co-development, perhaps it should be a permanent merge?

Upvotes: 0

Related Questions