假设我创建了一个新的 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
,(根据文档)应该可以工作:
这将默认为 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
子类拆分为单独的命名空间。还有其他方法吗?