2012-06-13 3 views
13

Mi piacerebbe avere due classi principali (o più) con leiningen, e quindi essere in grado di scegliere quale nella riga di comando java. Per esempio io ho:leiningen con più classi principali

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

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

Con una project.clj avere:

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

Poi ho costruire con lein uberjar, ed eseguire:

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

Ho capito che quando ho specificato :main abc nel project.clj lo chiamava come main-class nel manifest, ma non riuscivo a farlo funzionare senza mettere qualcosa. Ma in entrambi i casi, quando si tenta di eseguire il 'def' principale, ottengo una classe non trovato:

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

perché non utilizzare clojure cli https://github.com/clojure/tools.cli e passare un argomento di riga cmd per chiamare ciascuna delle diverse opzioni? – locojay

+0

In definitiva, si trattava di una situazione temporanea per avere più alimentazione (rapido sviluppo/test). Ma non ero a conoscenza di tools.cli così grazie per il link. Sono sicuro che lo userò in futuro. – Kevin

risposta

9

ho aggiunto :aot [abc def] al project.clj per generare il codice compilato e ha funzionato.

+1

Dove l'hai aggiunto? – Jackson

12

Questo funziona almeno con 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"]}) 

Quindi è possibile eseguire ogni principale in questo modo:

lein main-a 
lein main-b 

che si espande a questo:

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

Sono usando questo in uno dei miei progetti e funziona perfettamente.

+1

Grazie per l'ottima risposta. Un piccolo suggerimento: IMO, è più chiaro avere "eseguito" nel nome dell'alias; per esempio. 'lein run-main-a'. (Dico questo perché 'lein run' è fornito di default). –

1

Quello che ha funzionato per me sia Lein 2.7.0 del compito run come pure dalla uberjar risultante è la seguente ...

project.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}}) 

Per source come ...

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

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

Ciò consente Lein lavoro run Like ...

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

Dalla riga di comando il '-' in molti-mains deve diventare un '_' che lo rende un nome di classe Java legale.

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

Sembra che ci sono stati alcuni cambiamenti di comportamento tra Lein 2.7.0 e prima intorno l'effetto di: nil principale sul MANIFEST.MF. Quello che ho qui funziona come un campione in Lein 2.7.0. L'origine completa è https://github.com/robertkuhar/many-mains