Почему Лейнинген не может правильно использовать 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 и использовать это как класс вместо пространства имен.

Другие вопросы по тегам