leiningen с несколькими основными классами

Я хотел бы иметь два основных класса (или более) с leiningen, а затем иметь возможность выбирать, какой из них в командной строке java. Например, у меня есть:

(ns abc (:gen-class))
(defn -main [] (println "abc"))

(ns def (:gen-class))
(defn -main [] (println "def"))

С проектом.clj, имеющим:

(defproject my-jar "0.0.1"
 :description "test"
 :dependencies [
 ]
 :main abc)

Затем я строю с lein uberjar и запускаю:

java -cp my-jar-0.0.1-standalone.jar abc
java -cp my-jar-0.0.1-standalone.jar def

Я понимаю, что когда я указал :main abc в project.clj, он вызывал это как основной класс в манифесте, но я не мог заставить его работать, не добавляя что-то. Но в любом случае, когда я пытаюсь запустить main 'def', я получаю не найденный класс:

Exception in thread "main" java.lang.NoClassDefFoundError: def

person Kevin    schedule 13.06.2012    source источник
comment
почему бы не использовать clojure cli github.com/clojure/tools.cli и передать аргумент строки cmd для вызова каждого из различных вариантов?   -  person locojay    schedule 14.06.2012
comment
В конечном счете, это была временная ситуация с несколькими сетями (быстрая разработка/тестирование). Но я не знал об tools.cli, поэтому спасибо за ссылку. Я уверен, что буду использовать его в будущем.   -  person Kevin    schedule 17.06.2012


Ответы (3)


Это работает по крайней мере с leiningen 2.0+

(defproject my-jar "0.0.1"
 :description "test"
 :dependencies [
 ]
 :profiles {:main-a {:main abc}
           {:main-b {:main def}}
 :aliases {"main-a" ["with-profile" "main-a" "run"]
           "main-b" ["with-profile" "main-b" "run"]})

Затем вы можете запустить каждый основной файл следующим образом:

lein main-a
lein main-b

Что расширяется до этого:

lein with-profile main-a run
lein with-profile main-b run

Я использую это в одном из своих проектов, и он отлично работает.

person Michael    schedule 24.09.2013
comment
Спасибо за отличный ответ. Небольшое предложение: ИМО, понятнее использовать псевдоним; например lein run-main-a. (Я говорю это, потому что lein run предоставляется по умолчанию.) - person David J.; 10.12.2013

Я добавил :aot [abc def] в project.clj для создания скомпилированного кода, и это сработало.

person Kevin    schedule 13.06.2012
comment
Где ты его добавил? - person Jackson; 06.07.2015

Что сработало для меня как в задаче запуска lein 2.7.0, так и в полученном uberjar, выглядит следующим образом...

проект.clj:

(defproject many-mains "0.1.0-SNAPSHOT"
  :description "Project containing multiple main methods"
  :dependencies [[org.clojure/clojure "1.8.0"]]
  :main nil
  :target-path "target/%s"
  :profiles {:main-abc {:main many-mains.abc}
             :main-def {:main many-mains.def}
             :main-ghi {:main org.rekdev.mm.ghi}
             :core {:main many-mains.core}
             :uberjar {:aot :all}})

Для источника вроде...

$ cat src/many_mains/abc.clj
(ns many-mains.abc
  (:gen-class))

(defn -main
  ""
  [& args]
  (println "Hello, from many-mains.abc!"))

Это позволяет lein работать как...

$ lein with-profile main-abc run
Hello, from many-mains.abc!

В командной строке '-' во множестве сетей должен стать '_', что делает его допустимым именем класса Java.

$ java -cp target/uberjar/many-mains-0.1.0-SNAPSHOT-standalone.jar many_mains.abc
Hello, from many-mains.abc!

Похоже, между Lein 2.7.0 и более ранними версиями произошли некоторые изменения в поведении, связанные с влиянием :main nil на MANIFEST.MF. То, что у меня есть, отлично работает в Lein 2.7.0. Полный исходный код находится по адресу https://github.com/robertkuhar/many-mains.

person Bob Kuhar    schedule 29.08.2016