Leiningen 不会从 uberjar 中排除命名空间
Posted
技术标签:
【中文标题】Leiningen 不会从 uberjar 中排除命名空间【英文标题】:Leiningen wont exclude namespaces from uberjar 【发布时间】:2021-12-20 22:33:27 【问题描述】:我有一个项目,我希望代码的某些部分能够在本地环境中运行,而其他部分依赖于仅在远程环境中运行的库。例如
src/app/core.clj <- can run anywhere
src/app/sandbox/remote_only.clj <- depnds on libs that only function in remote environ
src/app/core.clj
在哪里
(ns app.core
(:gen-class))
(defn -main [] (println "Hello, World!"))
而src/app/sandbox/remote_only.clj
是
(ns app.sandbox.remote-only
(:require
[uncomplicate.commons.core :refer [with-release]]
[uncomplicate.neanderthal
[native :refer [dv dge]]
[core :refer [mv mv!]]]))
我希望能够uberjar
并在我的本地计算机上运行位于core.clj
中的代码,而不需要拉入remote_only.clj
,这将导致程序在本地失败。根据文档,Leiningen 应该能够使用配置文件和 uberjar 排除来完成此操作,例如:
(defproject app "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.10.1"]]
:profiles :uberjar :main app.core
:init-ns app.core
:aot :all
:remote :init-ns app.sandbox.remote_only
:dependencies [[uncomplicate/neanderthal "0.43.1"]] ; these deps will fail locally
:uberjar-exclusions [#".*sandbox.*"]
:repl-options :init-ns app.core)
在这里编译 uberjar 会导致:
❯ lein uberjar
Compiling app.core
Compiling app.sandbox.remote-only
Syntax error macroexpanding at (remote_only.clj:1:1).
Execution error (FileNotFoundException) at app.sandbox.remote-only/loading (remote_only.clj:1).
Could not locate uncomplicate/commons/core__init.class, uncomplicate/commons/core.clj or uncomplicate/commons/core.cljc on classpath.
因此,它明确地试图编译被明确排除的类。
我认为可以通过从:aot
编译中删除:all
标记来避免此类问题。例如:
(defproject app "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.10.1"]]
:profiles :uberjar :main app.core
:init-ns app.core
:aot [app.core]
:remote :init-ns app.sandbox.remote_only
:dependencies [[uncomplicate/neanderthal "0.43.1"]] ; these deps will fail locally
:uberjar-exclusions [#".*sandbox.*"]
:repl-options :init-ns app.core)
导致其他问题:
❯ lein uberjar
Compiling app.core
Created /Users/warrenronsiek/Projects/app/target/app-0.1.0-SNAPSHOT.jar
Created /Users/warrenronsiek/Projects/app/target/app-0.1.0-SNAPSHOT-standalone.jar
~/Projects/app 5s 15:47:37
❯ java -jar ./target/app-0.1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
我尝试过各种:exclusions
、:jar-exclusions
和正则表达式。这个问题的变体已被多次询问(1,2)没有任何效果。
如何让 Leiningen 编译 uberjars 并忽略指定的文件?
【问题讨论】:
【参考方案1】:我还没有尝试过这种带有“排除”功能的特殊设置。
一种解决方法是为应用的“本地”和“远程”部分创建子项目,然后可以由更高级别的“总”项目使用。
app
app-local
app-remote
这 3 个中的每一个都是一个单独的 Lein 项目。 app-local
和 app-remote
可以单独开发。然后使用的***app
项目将两个子项目作为依赖项(因此仅适用于远程/完整环境)。
Lein 功能checkouts 允许您同时开发所有 3 个 repos,这是一个巨大的帮助。它比使用lein install
的替代方法快得多,后者速度慢、需要手动操作、重复且容易出错。
附:您是否尝试过使用lein jar
而不是lein uberjar
?
【讨论】:
【参考方案2】:您将:aot :all
更改为:aot [app.core]
是正确的,但是当您尝试运行JAR 时,您运行的是库 版本而不是整个应用程序版本:
java -jar ./target/app-0.1.0-SNAPSHOT.jar
这不包括 Clojure 或任何依赖项。你想要:
java -jar ./target/app-0.1.0-SNAPSHOT-standalone.jar
【讨论】:
以上是关于Leiningen 不会从 uberjar 中排除命名空间的主要内容,如果未能解决你的问题,请参考以下文章
使用 ProGuard 混淆 clojure uberjars
如何排除打包为应用程序的 uber jar 的 jar 文件