Leiningen打包uberjar时无法排除指定命名空间的问题如何解决?
错误根因说明
- 第一个编译报错:
:uberjar-exclusions仅作用于最终打包的文件过滤规则,不会跳过编译阶段的源码扫描。配置:aot :all时Leiningen会遍历所有src下的Clojure文件做提前编译,自然会加载到依赖缺失的远程专属代码触发报错。 - 第二个运行报错:你执行的
app-0.1.0-SNAPSHOT.jar是不含任何依赖的项目编译产物包,本身就不包含Clojure核心类库,只有带standalone后缀的uberjar才会把所有依赖打进包里。
解决方案1:调整编译规则+正确运行
仅需修改配置并调整运行命令即可解决,无需改动目录结构:
- 确认
app.core中完全没有引用sandbox目录下的任何命名空间 - 使用如下
project.clj配置:
(defproject app "0.1.0-SNAPSHOT" :dependencies [[org.clojure/clojure "1.10.1"]] :main app.core :profiles {:uberjar {:aot [app.core] :uberjar-exclusions [#".*sandbox.*"]} :remote {:init-ns app.sandbox.remote-only :dependencies [[uncomplicate/neanderthal "0.43.1"]]}} :repl-options {:init-ns app.core})
- 打包后运行带standalone后缀的uberjar:
lein uberjar java -jar target/app-0.1.0-SNAPSHOT-standalone.jar
解决方案2:源码目录隔离(更稳妥)
如果后续远程专属代码会持续迭代,建议做物理目录隔离从根本上避免误加载:
- 调整目录结构,把远程专属代码移出默认src目录:
src/app/core.clj <- 通用代码 src-remote/app/sandbox/remote_only.clj <- 远程专属代码单独存放
- 使用如下
project.clj配置,仅在remoteprofile下加载远程专属源码和依赖:
(defproject app "0.1.0-SNAPSHOT" :dependencies [[org.clojure/clojure "1.10.1"]] :source-paths ["src"] :main app.core :profiles {:uberjar {:aot :all} ;; 可安全使用全量aot :remote {:source-paths ["src" "src-remote"] :init-ns app.sandbox.remote-only :dependencies [[uncomplicate/neanderthal "0.43.1"]]}} :repl-options {:init-ns app.core})
这种方案下本地和uberjar打包环境的源码路径中完全不存在远程专属代码,不会出现误扫描、误编译的问题。
内容的提问来源于stack exchange,提问作者Logister
相关产品推荐
相关产品推荐

