2012-06-13 12 views
13

Me gustaría tener dos clases principales (o más) con leiningen, y luego poder elegir cuál en la línea de comando de java. Por ejemplo tengo:leiningen con múltiples clases principales

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

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

Con un project.clj tener:

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

Entonces construyo con lein uberjar, y corro:

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

lo entiendo que cuando he especificado :main abc en el proyecto.clj lo llamaba como la clase principal en el manifiesto, pero no pude hacerlo funcionar sin poner algo. Pero de cualquier manera cuando trato de ejecutar el 'def' principal, tengo una clase que no se encuentra:

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

¿por qué no utilizar clojure cli https://github.com/clojure/tools.cli y pasar un argumento de línea de cmd para llamar a cada una de las diferentes opciones? – locojay

+0

En última instancia, era una situación temporal tener múltiples líneas principales (desarrollo/pruebas rápidas). Pero no estaba al tanto de las herramientas. Así que, gracias por el enlace. Estoy seguro de que lo usaré en el futuro. – Kevin

Respuesta

9

he añadido a la :aot [abc def] project.clj para generar el código compilado y funcionó.

+1

¿Dónde lo agregaste? – Jackson

12

Esto funciona, al menos, 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"]}) 

continuación, puede ejecutar cada principal de este modo:

lein main-a 
lein main-b 

que se expande a esto:

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

estoy usar esto en uno de mis proyectos y funciona perfectamente.

+1

Gracias por la gran respuesta. Una pequeña sugerencia: IMO, es más claro haber "ejecutado" en el nombre de alias; p.ej. 'lein run-main-a'. (Digo esto porque 'lein run' se proporciona por defecto.) –

1

lo que funcionó para mí en la tarea de marcha tanto de Lein 2.7.0, así como de la uberjar resultante es la siguiente ...

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

Para la fuente como ...

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

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

Esto permite Lein trabajo ejecutar como ...

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

Desde la línea de comandos, '-' en muchas líneas necesita convertirse en '_', lo que lo convierte en un nombre de clase Java legal.

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

Parece que ha habido algunos cambios en el comportamiento entre Lein 2.7.0 y antes de todo el efecto de: cero principal en el MANIFIEST.MF. Lo que tengo aquí funciona como un campeón en Lein 2.7.0. La fuente completa está en https://github.com/robertkuhar/many-mains

Cuestiones relacionadas