I'm creating an uberjar with
build=> (b/uber {:class-dir class-dir
:uber-file "uberjar.jar"
:basis basis})
This throws an error
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=>
This error is actually thrown from two libs on our classpath:
- .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
Each of these has an entry license/LICENSE
. The problem seems to arise that I am on osx which uses a case insensitive but case-preserving filesystem and there is already a top-level LICENSE
file from another jar. So it cannot create a license/LICENSE
entry in addition to a LICENSE
file that already exists.
I repod this with the following code that creates a few jars:
(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})
But the basic error happens when trying to explode the jars and creating a folder license
when a file LICENSE
already exists.
EDIT
Sean mentioned that depstar has an api-compatible uber
function and that has worked for me. Since the contents of the jars never hit the filesystem this constraint is avoided.