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

Community
  • 1
  • 1
j-g-faustus
  • 8,801
  • 4
  • 32
  • 42
  • Looks like I can't accept my own answer, so I'll have to leave the question open until someone else chimes in. – j-g-faustus Jun 26 '10 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, http://www.assembla.com/spaces/clojure/tickets/315-add-support-for-running--main-namespace-from-clojure-main-without-aot – Rayne Jul 06 '10 at 12:32

3 Answers3

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
j-g-faustus
  • 8,801
  • 4
  • 32
  • 42
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...

Alex Ott
  • 80,552
  • 8
  • 87
  • 132
  • 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. – j-g-faustus Jun 27 '10 at 11:02
  • Nice overview, thanks for the article. Probably about time I start using a build tool anyway :) – j-g-faustus Jun 27 '10 at 19:27
  • Leiningen doesn't help me: $ lein test Couldn't find project.clj, which is needed for test – mcandre Mar 07 '11 at 21:00
  • @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/ – michael May 04 '12 at 06:45
1

To run clojure file

clojure filename.clj
groot
  • 420
  • 1
  • 7
  • 15