views:

143

answers:

3

Here I check the environment variable CLASSPATH
daniel@daniel-laptop:~/ps/clojure/projects/ring-tutorial$ echo $CLASSPATH
/home/daniel/ps/clojure/projects/ring-tutorial/src

Here I check what java thinks it is.
daniel@daniel-laptop:~/ps/clojure/projects/ring-tutorial$ lein repl
Clojure 1.1.0 user=> (System/getProperty "java.class.path")
"src/:classes/:/home/daniel/.m2/repository/leiningen/leiningen/1.1.0/leiningen-1.1.0-standalone.jar:lib/clojure-1.1.0.jar:lib/servlet-api-2.5-6.1.14.jar:lib/commons-io-1.4.jar:lib/clj-stacktrace-0.1.0.jar:lib/clojure-contrib-1.1.0.jar:lib/ring-devel-0.2.0.jar:lib/jetty-util-6.1.14.jar:lib/clj-html-0.1.0.jar:lib/ring-jetty-adapter-0.2.0.jar:lib/jetty-6.1.14.jar:lib/ring-core-0.2.0.jar:lib/commons-fileupload-1.2.1.jar:lib/ring-servlet-0.2.0.jar:lib/commons-codec-1.4.jar:"

As you can see, the two responses are completely different. I'm pretty sure that I must just be misunderstanding where I ought to be editing the CLASSPATH variable for java to "get it," except that everything I've found says that this should work. So what's the deal? Does leiningen spawn its own weird renegade instance of clojure? Am I editing a completely irrelevant variable? Any help much appreciated.

+5  A: 

$CLASSPATH is indeed completely irrelevant here. It is what java-the-JVM-launcher-programme would use if no classpath information was provided to it on the command line; Leiningen provides the JVM with a classpath appropriate to whichever project you're working on.

In this particular case, "/home/.../ring-tutorial/src" would not be a very useful classpath for the Ring tutorial, since it only includes the Ring tutorial's source and does not include the Clojure jar (which is necessary for running Clojure code), the Ring jars (Ring is a multi-module project) or any of the other jars Ring depends on. The classpath produced by Leiningen might seem pretty long, but all of its components really need to be there.

Incidentally, if you're just starting out with Clojure, I'd recommend you stick to your toolchain's classpath management facilities (that might mean Emacs + lein swank or some IDE + the Clojure plugin) if at all possible. Otherwise, there's a lot of questions on Clojure classpath issues here on SO, plus a multitude of other resources on the topic you can google for... but now that tool support is pretty robust and you don't normally need to touch classpath by hand, it's just pain best avoided in the beginning.

Michał Marczyk
+1  A: 

The problem with using the CLASSPATH variable to manage your dependencies is that all Java and other JVM languages would need to manipulate it for their purposes. It does not take long before you have painted yourself in corner.

It kind of works when you start a server which only launches a server. It completely breaks down on a PC of a Java developer, who has 10's of programs and projects all needing different dependencies and is then spending more time debugging bash scripts to manipulate the CLASSPATH variable that writing source code.

Hence this way to manage the classpath has gotten into disuse, prefering other classloading techniques, or when using the CLASSPATH, only using it very locally.

Peter Tillemans
+1  A: 

The Clojure classpath is the Java classpath.

$CLASSPATH is ignored when the java executable is invoked with the -cp argument, which Leiningen (and most other Clojure build scripts) do.

If you're using a build tool such as Leiningen, you must use it to manage the classpath.

Stuart Sierra