Error de compilación de Leiningen con archivos Java que hacen referencia a clases generadas a partir de archivos Clojure
-
27-10-2019 - |
Pregunta
Tengo un proyecto de Leiningen que está compilando archivos Java y Clojure.Los archivos Java importan algunas de las clases que se generan a partir de los archivos Clojure (con gen-class).
Cuando hago la compilación de lein, obtengo errores de compilación en las importaciones en los archivos de Java (diciendo que no puede encontrar las clases).Si elimino los archivos Java del proyecto, hago la compilación de lein, vuelvo a agregar los archivos de Java y vuelvo a compilar lein, todo funciona bien.
Entonces, es como si los archivos de Clojure tuvieran que compilarse antes que los archivos de Java.
Por cierto, estoy incluyendo los archivos Clojure que generan clases en la lista: aot.
¿Qué va mal aquí?
Solución
(El código de esta respuesta no está probado, aunque es de esperar que funcione con Leiningen 1.x (para valores recientes de x).)
La tarea compile
de Leiningen ejecuta la tarea javac
automáticamente si su project.clj
especifica un :java-source-path
. Lo hace antes de compilar las fuentes de Clojure, porque supongo que esa es la dirección habitual de la dependencia.
Para evitar esto, puede usar un gancho:
;;; in leiningen.hooks.clj_first.clj
(ns leiningen.hooks.clj-first
(:require [leiningen.compile :as leinc]
[leiningen.javac :as javac]))
(defn compile-clj-first-hook [compile-task project & args]
(apply compile-task
(dissoc project :java-source-path)
args))
(javac/javac project))
(add-hook #'leiningen.compile/compile compile-clj-first-hook)
Coloque esto en algún lugar de su ruta de clases en tiempo de compilación y agregue
:hooks [clj-first-hook]
al mapa de su proyecto.
Tenga en cuenta que javac
, cuando se llama directamente, todavía no llamará compile
. También puede hacerlo equivalente a compile
, p. Ej. enganchándolo con la siguiente función:
(defn javac-hook [javac-task project]
(if (project ::clj-compiled?)
(javac/javac project)
(leinc/compile project)))
La última forma de compile-clj-first-hook
debería ser
(javac/javac (assoc project ::clj-compiled? true))
(Hacer compile
no llamar a javac
en absoluto probablemente rompería jar
/ uberjar
.)