ninjudd / cake

A tasty build tool for Clojure.
clojure-cake.org
Eclipse Public License 1.0
171 stars 12 forks source link

Config not being read #106

Closed samaaron closed 13 years ago

samaaron commented 13 years ago

I don't seem to be able to get cake to use either the global or project config.

For example, if I add the line:

project.classpath = /Users/sam/Development/improcess/lib/monome-serial/src

in PROJECT/.cake/config

and fire up a REPL, the classpath doesn't appear to contain my added path. Likewise for ~/.cake/config

ninjudd commented 13 years ago

How are you determining it is not in the classpath? Cake runs your project in a separate classloader, so looking at the system property is not adequate. You need to get the classloader like this:

(.getClassloader clojure.lang.RT)

And then iterate through the urls.

samaaron commented 13 years ago

I'm using the following fn:

(defn print-classpath []
  (let [paths (map (memfn getPath)
                   (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))]
    (pprint/pprint (sort paths))))

Also, I couldn't see the path in the classpath when I grepped the jvm process.

Here's the output of print-classpath (which doesn't contain the project.classpath var:

("/Users/sam/.cake/lib/dev/swank-clojure-1.2.1.jar"
 "/Users/sam/.m2/repository/cake/cake/0.6.2/bake.jar"
 "/Users/sam/.m2/repository/cake/cake/0.6.2/cake-0.6.2.jar"
 "/Users/sam/.m2/repository/org/clojure/clojure/1.2.0/clojure-1.2.0.jar"
 "/Users/sam/Development/improcess/apps/beatbox/lib/dev/*"
 "/Users/sam/Development/improcess/apps/beatbox/src/"
 "/Users/sam/Development/improcess/apps/beatbox/src/clj")
ninjudd commented 13 years ago

That is printing cake's classpath, not your project's classpath. Try this:

(defn print-classpath []
  (let [paths (map (memfn getPath)
                   (seq (.getURLs (.getClassLoader clojure.lang.RT))))]
    (pprint/pprint (sort paths))))
samaaron commented 13 years ago

Ah, ok, that's confusing - with your version of print-classpath, I see the path I wanted to add. Thanks for your help.

So, as a quick aside, what is the expected behaviour when I add foo to my project.clj and also to the classpath such that I have a jar in lib and also the src on the classpath? I would like that the src overrides the jar - is this the case?

ninjudd commented 13 years ago

Whichever shows up first in the classpath should be used. I put project.classpath from config before lib/ for this reason.

However, it is slightly more complicated with AOT-compiled namespaces. I believe Clojure will use the .class file if it is newer than the corresponding .clj file.

samaaron commented 13 years ago

Ok, cool, I wasn't able to see that behaviour (src overriding jars) but I'll try again.

Would you be able to spare a moment to explain the multiple classloader business?

If I were to use lein, would (.getClassLoader clojure.lang.RT) be the same as (java.lang.ClassLoader/getSystemClassLoader)? How many classloaders can you have and how do you manage it all?

ninjudd commented 13 years ago

The multiple classloaders are handled by https://github.com/ninjudd/classlojure. In theory, you could have as many classloaders as you want, but we only use two in cake.

Lein launches a separate JVM for you project (using Ant), which is why your print-classpath method would work in lein but not in cake. However, (.getClassLoader clojure.lang.RT) should work in both cake and lein.

For the overriding, behavior, verify that your src dir does show up before the jar. If it still doesn't work, I'd be happy to help debug if you can provide a simple example that reproduces the problem.

samaaron commented 13 years ago

Thanks for all your help so far :-)

I'm off out for a Ruby meet now, but I'll get back to it tomorrow. Oh, and I must say thanks for cake - it really is making my life better - particularly the native stuff which is sublime!

samaaron commented 13 years ago

I've figured out where I was going wrong. I was attempting to add multiple paths to my classpath with multiple statements:

project.classpath = /Users/sam/Development/improcess/lib/overtone/src
project.classpath = /Users/sam/Development/improcess/lib/polynome/src
project.classpath = /Users/sam/Development/improcess/lib/monome-serial/src

Clearly the third just clobbers the first two statements.

Perhaps it might be useful to add a quick pointer in the README for adding multiple paths, i.e. you have to separate them with a colon:

project.classpath = /Users/sam/Development/improcess/lib/overtone/src:/Users/sam/Development/improcess/lib/polynome/src:/Users/sam/Development/improcess/lib/monome-serial/src

Thanks once again for your help.