16

I'm feeling slightly silly here, but I can't get Clojure Hello World to compile.

Directory structure:

hello-world/
  clojure-1.1.0.jar
  build/
    classes/
  src/
    test/
      hello.clj

hello.clj:

(ns test.hello
  (:gen-class))

(defn -main [& args]
  (println "Hello" (nth args 0)))

Interaction:

$ cd hello-world
[hello-world]$ java -cp ./clojure-1.1.0.jar:./build/classes:./src clojure.main
Clojure 1.1.0
user=> (require 'test.hello)
nil
user=> (test.hello/-main "there")
Hello there
nil
user=> (compile 'test.hello)
java.io.IOException: No such file or directory (hello.clj:2)
user=> *compile-path*
"classes"
user=> (doseq [p (.split (System/getProperty "java.class.path") ":")] (println p))
./clojure-1.1.0.jar
./build/classes
./src
nil

So I can load and call the file from the REPL, but it doesn't compile.

According to clojure.org, compilation needs

  • namespace must match classpath-relative file path - check
  • *compile-path* must be on the classpath - check
  • :gen-class argument to the ns form - check

I found this post from a year back, as far as I can tell I'm doing exactly the same, but it doesn't work.

What am I missing?

System: OS X 10.6, Java 1.6.0, Clojure 1.1

2
  • Looks like I can't accept my own answer, so I'll have to leave the question open until someone else chimes in. Commented Jun 26, 2010 at 11:29
  • It's also relevant to note that you rarely need to AOT compile Clojure code. Clojure code will run just fine without being compiled, and that is the way you should run it. Some specific Clojure Java interop features actually require that your code be AOT compiled, but if you aren't using those features, don't bother compiling your code. If you want an executable jar, you can just AOT compile a main file with just a -main function to run the application. However, assembla.com/spaces/clojure/tickets/… Commented Jul 6, 2010 at 12:32

3 Answers 3

22

Got it, there's a fourth requirement:

  • *compile-path* is resolved relative to the JVMs working directory, normally the directory where java is started. Or by REPL: (System/getProperty "user.dir"),

So this works:

user=> (set! *compile-path* "build/classes")     
"build/classes"
user=> (compile 'test.hello)
test.hello
Sign up to request clarification or add additional context in comments.

2 Comments

Modified the explanation, the first one was wrong. The fix is the same.
For me, (set! compile-path ".") is necessary to compile CLJs in the current directory.
11

Why you don't use Leiningen? It's much easier to use it, than compile code manually. You can use my article about it as introduction...

4 Comments

I've used it briefly to download dependencies for external projects, but so far not looked into how to use it as a build tool. Thanks for the link, I'll check it out.
Nice overview, thanks for the article. Probably about time I start using a build tool anyway :)
Leiningen doesn't help me: $ lein test Couldn't find project.clj, which is needed for test
@mcandre read the linked-to article, it explains the process. A sample project can be downloaded (or git-cloned) from github.com/alexott/lein-simple-project/
1

To run clojure file

clojure filename.clj

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.