在 Clojure 中创建 Uberjar 的问题

Problems creating Uberjar in Clojure

我正在使用 Clojure 的 java-time 库,它是 java.time [1].

的包装器

我的程序在调用 lein run 或通过 repl 调用函数时运行。另一方面,当我尝试执行 lein uberjar 时,出现以下涉及 类 的错误:

$ lein uberjar
Compiling foo.cli
Compiling foo.core
Compiling foo.holidays
nil
Syntax error (ClassCastException) compiling at (/tmp/form-init8528909580728167374.clj:1:73).
class java_time.graph.Types cannot be cast to class java_time.graph.Types (java_time.graph.Types is in unnamed module of loader 'app'; java_time.graph.Types is in unnamed module of loader clojure.lang.DynamicClassLoader @141c66db)

Full report at:
/tmp/clojure-6795557396101417445.edn
Compilation failed: Subprocess failed

我已经找出是哪个表达式导致了这个问题,恰好是:

(java-time/minus  (java-time/local-date) (java-time/period 2 :days))

我不确定它为什么会失败,而且错误非常神秘。我敢打赌编译器在生成 uberjar 时会混淆转换一些 类 但令我惊讶的是 repl 工作正常。它与用于 uberjar 创建的 :aot 有关吗?

这是 project.clj 文件的一个片段,内容涉及:

(defproject foo
  ...
  :main ^:skip-aot foo.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

[1] https://github.com/dm3/clojure.java-time

看来您的环境有问题。一个示例程序对我来说很好用:

    (ns demo.core
      (:use tupelo.core)
      (:require [java-time :as jt])
      (:gen-class))
    
    (defn -main [& args]
      (print-versions)
      (let [result (java-time/minus
                     (java-time/local-date)
                     (java-time/period 2 :days))]
        (println :result result)))

结果:

    ~/expr/demo > lein clean ; lein run
    
    --------------------------------------
       Clojure 1.10.2-alpha1    Java 15
    --------------------------------------
    :result #object[java.time.LocalDate 0x61a309fe 2020-10-05]
    
    
    ~/expr/demo > lein clean ; lein uberjar 
    Compiling demo.core
    Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT.jar
    Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar

为了完整起见,这里是 project.clj:

(defproject demo "0.1.0-SNAPSHOT"
  :license {:name "Eclipse Public License"
            :url  "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
                 [clojure.java-time "0.3.2"]
                 [org.clojure/clojure "1.10.2-alpha1"]
                 [prismatic/schema "1.1.12"]
                 [tupelo "20.08.27"]
                 ]
  :plugins [
            [com.jakemccrary/lein-test-refresh "0.24.1"]
            [lein-ancient "0.6.15"]
            [lein-codox "0.10.7"]
            ]

  :profiles {:dev     {:dependencies []}
             :uberjar {:aot :all}}

  :global-vars {*warn-on-reflection* false}
  :main ^:skip-aot demo.core

  :source-paths ["src/clj"]
  :java-source-paths ["src/java"]
  :test-paths ["test/clj"]
  :target-path "target/%s"
  :compile-path "%s/class-files"
  :clean-targets [:target-path]

  :jvm-opts ["-Xms500m" "-Xmx4g"]
  )