Почему Лейнинген не может правильно использовать my: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
, который (согласно документации) должен работать:
Это будет 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 ответ
Согласился с @Mars, проблема в том, что lein run
не AOT example.core
Пространство имен. Шаблон Leiningen по умолчанию сделал example.core
не AOT:
(defproject example "0.1.0-SNAPSHOT"
...
:main ^:skip-aot example.core
...)
Я думаю, вы можете определить свое приложение, используя defrecord
и использовать это как класс вместо пространства имен.