为什么莱宁根总是不能正确使用我的:gen类? [英] Why can't Leiningen always use my :gen-class properly?
问题描述
假设我创建了一个新的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
,(根据解决方案
同意@Mars,问题是lein run
不会AOT example.core
名称空间.默认的Leiningen模板使example.core
非AOT:
(defproject example "0.1.0-SNAPSHOT"
...
:main ^:skip-aot example.core
...)
我的最佳猜测是,您可以使用defrecord
定义您的应用程序,并将其用作类而不是名称空间.
Let's say I create a new Leiningen project (lein new app example
) and add some code in example/src/example/core.clj
that makes use of :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))
If I then create a JAR (lein uberjar
) and run it, everything works fine. However, if I instead try to run my app directly (lein run
), I get a ClassNotFoundException
. In addition, if I open a REPL (lein repl
), I first get the same error as before, but after running this code:
(compile 'example.core)
the error no longer appears in lein run
or lein repl
.
Could someone please explain to me what exactly is going on here, and how I can run my app directly without needing to manually compile my code from a REPL?
Edit: After fooling around a bit more, I found that the solution to this problem is to add
:aot [example.core]
to project.clj
. (Thanks @Mars!) I'm still confused, though, because I had previously tried simply removing ^:skip-aot
, which (according to the docs) should work:
This will be AOT compiled by default; to disable this, attach
^:skip-aot
metadata to the namespace symbol.
But it doesn't. Why?
Another edit (if I should split any of this into a separate question, let me know and I'll do so): I've been playing with hyphens (lein new app my-example
), and weird stuff has been happening. This doesn't work:
(ns my-example.core
(:gen-class :extends javafx.application.Application))
;; ...
(defn -main [& args]
(javafx.application.Application/launch my-example.core args))
But this does:
(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))
So my class name can either start with a lowercase letter (example.core
) or contain a hyphen (my-example.Core
), but not both? I really don't get it.
And finally, lein uberjar
fails on that final example (with the explicit :name
), because
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.
As far as I can tell, the only way to fix that is to split the Application
subclass into a separate namespace. Is there another way?
Agreed with @Mars, the problem is that lein run
does not AOT the example.core
namespace. The default Leiningen template made the example.core
non AOT:
(defproject example "0.1.0-SNAPSHOT"
...
:main ^:skip-aot example.core
...)
My best guess is that you could define your app using defrecord
and use that as a class instead of the namespace.
这篇关于为什么莱宁根总是不能正确使用我的:gen类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!