假设我创建了一个新的 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
or lein repl
.
有人可以向我解释一下这里到底发生了什么,以及如何直接运行我的应用程序而不需要从 REPL 手动编译我的代码吗?
Edit: 经过一番闲逛,我发现解决这个问题的方法是添加
:aot [example.core]
to project.clj
。 (谢谢@Mars!)不过,我仍然很困惑,因为我之前曾尝试简单地删除^:skip-aot
,其中(根据the docs https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L189-L190) 应该管用:
默认情况下,这将是 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
子类到单独的命名空间中。还有别的办法吗?