Leiningen为什么不能一直使用我的:gen-class?

时间:2015-09-19 03:46:18

标签: clojure leiningen gen-class

假设我创建了一个新的Leiningen项目(lein new app example)并在example/src/example/core.clj中添加了一些使用:gen-class的代码:

(ns example.core
  (:gen-class :extends javafx.application.Application))

(defn -start [this stage]
  (.show stage))

(defn -main [& args]
  (javafx.application.Application/launch example.core args))

如果我然后创建一个JAR(lein uberjar)并运行它,一切正常。但是,如果我尝试直接运行我的应用程序(lein run),我会得到ClassNotFoundException。另外,如果我打开一个REPL(lein repl),我首先会得到与以前相同的错误,但在运行此代码之后:

(compile 'example.core)

错误不再出现在lein run lein repl中。

有人可以向我解释这里究竟发生了什么,以及如何直接运行我的应用程序而无需从REPL手动编译我的代码?

编辑:在多了一点之后,我发现解决这个问题的方法是添加

:aot [example.core]

project.clj。 (感谢@Mars!)我仍然感到困惑,因为我以前只是尝试删除^:skip-aot,(根据the docs)应该有效:

  

这将是AOT默认编译;要禁用它,请附加   名称空间符号的^:skip-aot元数据。

但事实并非如此。为什么呢?

另一个编辑(如果我将其中任何一个分成一个单独的问题,请告诉我,我会这样做):我一直在玩连字符(lein new app my-example) ,奇怪的东西一直在发生。这不起作用:

(ns my-example.core
  (:gen-class :extends javafx.application.Application))
;; ...
(defn -main [& args]
  (javafx.application.Application/launch my-example.core args))

但这样做:

(ns my-example.core
  (:gen-class
    :name my-example.Core
    :extends javafx.application.Application))
;; ...
(defn -main [& args]
  (javafx.application.Application/launch my-example.Core args))

所以我的班级名字可以用小写字母(example.core)开头,或者包含连字符(my-example.Core),但不能同时包含两个?我真的不知道它

最后,lein uberjar在最后一个示例(使用显式:name)失败,因为

Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method.

据我所知,解决这个问题的唯一方法是将Application子类拆分为单独的命名空间。还有另一种方式吗?

1 个答案:

答案 0 :(得分:3)

同意@Mars,问题是lein run没有AOT example.core命名空间。默认的Leiningen模板使example.core非AOT:

(defproject example "0.1.0-SNAPSHOT"
  ...
  :main ^:skip-aot example.core
  ...)

我最好的猜测是您可以使用defrecord定义您的应用,并将其用作类而不是命名空间。