我正在创建一个 uberjar,使用以下代码
build=> (b/uber {:class-dir class-dir
:uber-file "uberjar.jar"
:basis basis})
这引发了错误
build=> (b/uber {:class-dir class-dir
:uber-file "uberjar.jar"
:basis basis})
Execution error (FileNotFoundException) at java.io.FileOutputStream/open0 (FileOutputStream.java:-2).
/var/folders/_h/3fpgc8pj4fb2_w3mfqfl59fr0000gn/T/uber8421760143696109740/license/LICENSE (Not a directory)
build=> *e
#error {
:cause "/var/folders/_h/3fpgc8pj4fb2_w3mfqfl59fr0000gn/T/uber8421760143696109740/license/LICENSE (Not a directory)"
:via
[{:type java.io.FileNotFoundException
:message "/var/folders/_h/3fpgc8pj4fb2_w3mfqfl59fr0000gn/T/uber8421760143696109740/license/LICENSE (Not a directory)"
:at [java.io.FileOutputStream open0 "FileOutputStream.java" -2]}]
:trace
[[java.io.FileOutputStream open0 "FileOutputStream.java" -2]
[java.io.FileOutputStream open "FileOutputStream.java" 298]
[java.io.FileOutputStream <init> "FileOutputStream.java" 237]
[java.io.FileOutputStream <init> "FileOutputStream.java" 187]
[clojure.tools.build.tasks.uber$explode invokeStatic "uber.clj" 66]
[clojure.tools.build.tasks.uber$explode invoke "uber.clj" 53]
[clojure.tools.build.tasks.uber$uber$fn__16290 invoke "uber.clj" 114]
[clojure.core$run_BANG_$fn__8813 invoke "core.clj" 7717]
[clojure.core.protocols$naive_seq_reduce invokeStatic "protocols.clj" 62]
[clojure.core.protocols$interface_or_naive_reduce invokeStatic "protocols.clj" 72]
[clojure.core.protocols$fn__8181 invokeStatic "protocols.clj" 169]
[clojure.core.protocols$fn__8181 invoke "protocols.clj" 124]
[clojure.core.protocols$fn__8136$G__8131__8145 invoke "protocols.clj" 19]
[clojure.core.protocols$seq_reduce invokeStatic "protocols.clj" 31]
[clojure.core.protocols$fn__8166 invokeStatic "protocols.clj" 75]
[clojure.core.protocols$fn__8166 invoke "protocols.clj" 75]
[clojure.core.protocols$fn__8110$G__8105__8123 invoke "protocols.clj" 13]
[clojure.core$reduce invokeStatic "core.clj" 6830]
[clojure.core$run_BANG_ invokeStatic "core.clj" 7712]
[clojure.core$run_BANG_ invoke "core.clj" 7712]
[clojure.tools.build.tasks.uber$uber invokeStatic "uber.clj" 114]
[clojure.tools.build.tasks.uber$uber invoke "uber.clj" 104]
[clojure.lang.Var invoke "Var.java" 384]
[clojure.tools.build.api$uber invokeStatic "api.clj" 277]
[clojure.tools.build.api$uber invoke "api.clj" 266]
[build$eval16234 invokeStatic "NO_SOURCE_FILE" 11]
[build$eval16234 invoke "NO_SOURCE_FILE" 11]
[clojure.lang.Compiler eval "Compiler.java" 7181]
[clojure.lang.Compiler eval "Compiler.java" 7136]
[clojure.core$eval invokeStatic "core.clj" 3202]
[clojure.core$eval invoke "core.clj" 3198]
[clojure.main$repl$read_eval_print__9110$fn__9113 invoke "main.clj" 437]
[clojure.main$repl$read_eval_print__9110 invoke "main.clj" 437]
[clojure.main$repl$fn__9119 invoke "main.clj" 458]
[clojure.main$repl invokeStatic "main.clj" 458]
[clojure.core.server$repl invokeStatic "server.clj" 180]
[clojure.core.server$repl invoke "server.clj" 180]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.AFn applyTo "AFn.java" 144]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core.server$accept_connection invokeStatic "server.clj" 73]
[clojure.core.server$start_server$fn__8902$fn__8903$fn__8905 invoke "server.clj" 117]
[clojure.lang.AFn run "AFn.java" 22]
[java.lang.Thread run "Thread.java" 829]]}
build=>
这个错误实际上是由我们的类路径上的两个库抛出的
- .m2/repository/xml-apis/xml-apis/1.4.01/xml-apis-1.4.01.jar
- .m2/repository/xml-apis/xml-apis-ext/1.3.04/xml-apis-ext-1.3.04.jar
这些库中的每一个都有一个条目 license/LICENSE
。问题似乎是在 osx 上我使用的文件系统不区分大小写,但保留大小写,并且已经存在一个来自另一个 jar 的顶级 LICENSE
文件。因此,它无法在已经存在 LICENSE
文件的情况下创建 license/LICENSE
条目。
我用以下创建几个 jar 的代码进行了重现
(ns build
(:require [clojure.tools.build.api :as b]))
;; create a jar with just a single namespace and a license/LICENSE file
(b/write-file {:path "target/liba/a.clj"
:content (symbol "(ns a)")})
(b/write-file {:path "target/liba/license/LICENSE"
:content (symbol "this is the license from a")})
(b/write-file {:path "target/liba/deps.edn"
:content '{:paths ["."]}})
(b/write-pom {:basis (b/create-basis {:project "target/liba/deps.edn"})
:class-dir "target/liba"
:lib 'liba/liba
:version "1.0.0"
:src-dirs ["target/liba"]})
(b/jar {:class-dir "target/liba"
:jar-file "target/jars/liba.jar"})
;; create another jar libb with just a single ns and a license file
(b/write-file {:path "target/libb/b.clj"
:content (symbol "(ns b)")})
(b/write-file {:path "target/libb/license"
:content (symbol "this is the license from b")})
(b/write-file {:path "target/libb/deps.edn"
:content '{:paths ["."]}})
(b/write-pom {:basis (b/create-basis {:project "target/libb/deps.edn"})
:class-dir "target/libb"
:lib 'libb/libb
:version "1.0.0"
:src-dirs ["target/libb"]})
(b/jar {:class-dir "target/libb"
:jar-file "target/jars/libb.jar"})
;; create a consumer of these
(b/write-file {:path "target/libc/license"
:content (symbol "this is the license from c")})
(b/write-file {:path "target/libc/deps.edn"
:content '{:deps {liba/liba {:local/root "../jars/liba.jar"}
libb/libb {:local/root "../jars/libb.jar"}}}})
(def old-project-root b/*project-root*)
(b/set-project-root! "target/libc")
#_(b/set-project-root! old-project-root)
(b/uber {:class-dir "."
:uber-file "uberjar.jar"
:basis (b/create-basis {:project "deps.edn"})
:main 'clojure.main})
但在尝试解压 jar 并创建文件 LICENSE
已经存在时的 license
文件夹时发生基本错误。
编辑
Sean 提到 depstar 有一个 api 兼容的 uber
函数,这对我来说很有效。由于 jar 的内容从未击中文件系统,因此避免了此约束。