孤立的Clojure应用程序

18

我是Clojure的初学者,昨天才开始接触。

我了解到使用Leiningen lein new foo 是创建独立应用程序的简单方法。

我试图使用Leiningen创建一个hello world测试项目。我在project.clj中添加了:main和:aot指令,在core.clj文件中添加了:gen-class,并尝试运行lein run,但是我收到了有关找不到类定义的错误。

Exception in thread "main" java.lang.NoClassDefFoundError: 
Caused by: java.lang.ClassNotFoundException: 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)

core.clj文件

(ns test.core
  (:gen-class))
(defn -main [& args] (println "Hello main"))

还有project.clj文件

(defproject test "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :main test.core
  :aot [test.core]
  :dependencies [[org.clojure/clojure "1.2.1"]])

编辑: 经过进一步的测试,似乎将项目复制到我的桌面上可以正常工作,我认为这表明我的笔记本电脑上的环境出了问题,但我不知道原因。

桌面上的环境来自存储库的clojure和AUR的leiningen。 在笔记本电脑上,clojure来自clojure.org,而leiningen来自github。


@deong 我的 $HOME/bin/clj 文件中有 "CLASSPATH=.:$CLASSPATH"。 - Masse
如果你在shell中只执行"export CLASSPATH= .:$CLASSPATH",然后运行'lein run',会发生什么?我不认为leiningen调用clj shell脚本来运行程序。我认为它直接使用clojure jar文件作为参数调用Java。 - deong
@deong 依然如故。甚至无法创建jar文件。lein编译会产生相同的错误。 - Masse
嗯...我现在脑子一片空白。Clojure 代码看起来对我来说没问题。 - deong
有足够积分的人能否为这个问题创建一个新标签 - leiningen-v1会起作用。在lein2中,问题和答案都没有意义。lein new已更改,其他部分都是默认使用lein new app创建的。 - Jacek Laskowski
显示剩余5条评论
4个回答

35

[2013年4月更新]

Leiningen 2已经正式发布一段时间,其中包括项目模板的概念。默认情况下,Leiningen提供了一个app模板,可直接使用。尝试以下命令:

lein new app my-project

您会发现Leiningen创建了熟悉的项目模板,同时包含以下内容:

  • my-project.core作为project.clj文件中:main条目的默认命名空间
  • my-project.core命名空间声明中的:gen-class表单
  • my-project.core命名空间中的默认-main函数

对于那些还无法使用Leiningen 2的人,lein-newnew插件在Leiningen 1下提供类似的体验。

[/UPDATE]

要构建一个运行时打印“Hello World!”的项目,您可以按照以下步骤进行(根据您上面的过程进行修订):

设置

lein new my-project
cd my-project
lein deps

现在您应该有一个基本的架构,并在您的lib文件夹中安装了Clojure jar。

编写一个函数

现在使用您选择的编辑器编辑src/my_project/core.clj文件,在(ns ...)表单下方添加以下内容:

(defn -main []
  (println "Hello World!"))

这个函数在你的my-project.core命名空间中。为确保其作为主函数运行,让我们在顶部的命名空间定义中添加一个gen-class参数,使得它现在在core.clj文件的顶部看起来像这样:

```clojure (ns my-project.core (:gen-class)) ```
(ns my-project.core
  (:gen-class :main true))

所以总体来说,您的 core.clj 文件应该像这样:

(ns my-project.core
  (:gen-class :main true))

(defn -main []
  (println "Hello World!"))

将其配置为主函数

一旦您按上述方式编辑了src/my_project/core.clj,您需要告诉构建工具Leiningen该项目的"main"函数在哪里。以下是一个示例defproject表单:

(defproject my-project "1.0.0-SNAPSHOT"
  :description "My Project"
  :dependencies [[org.clojure/clojure "1.2.1"]]
  :main my-project.core)

现在,my-project.core 内部的 -main 函数成为你程序的入口点。

运行

你现在有两种运行该项目的选项:

  • my-project 项目根目录下使用命令行运行 lein run
  • 通过运行 lein uberjar 创建一个独立的 jar 文件。然后通过运行 java -jar my-project-1.0.0-SNAPSHOT-standalone.jar 来运行结果的 jar 文件。

1
正如我的编辑所说,我认为错误出在我的笔记本电脑环境上,因为当直接复制到桌面时,该项目可以编译通过。不过这是一篇很棒的帖子,所以我会点赞的。 - Masse

1
搞定了。我从git上获取了最新的leiningen,但它出了点问题。我切换到1.6.1标签并运行self-install,现在它可以正常工作了。

我已经从Ubuntu的存储库中安装了git,但我仍然遇到同样的问题。我应该使用git的版本吗? - Christophe De Troyer

0

我错过了,你把项目命名为test,这样是不行的,你需要把它改成其他的名称才能正常工作。


-1

你上面说

lein new foo

你的意思是什么?
lein new test

啊,我明白你为什么那样想了,但是我确实使用了 lein new test。 - Masse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接