简体   繁体   English

Leiningen 不会从 uberjar 中排除命名空间

[英]Leiningen wont exclude namespaces from uberjar

I have a project where I want certain parts of the code to be able to run on a local environment, and other parts which depend on libraries that only run on a remote environment.我有一个项目,我希望代码的某些部分能够在本地环境中运行,而其他部分则依赖于仅在远程环境中运行的库。 Eg例如

src/app/core.clj <- can run anywhere
src/app/sandbox/remote_only.clj <- depnds on libs that only function in remote environ

where src/app/core.clj is src/app/core.clj在哪里

(ns app.core
  (:gen-class))
(defn -main [] (println "Hello, World!"))

and src/app/sandbox/remote_only.clj issrc/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!]]]))

I want to be able to uberjar and run the code located in core.clj on my local machine without pulling in remote_only.clj which will cause the program to fail locally.我希望能够在本地机器上运行uberjar并运行位于core.clj的代码,而不会拉入remote_only.clj ,这会导致程序在本地失败。 According to the docs, Leiningen should be able to accomplish this using profiles and uberjar exclusions eg:根据文档,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})

compiling the uberjar here will result in:在此处编译 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.

So, explicitly its trying to compile the class that was specifically excluded.因此,明确地尝试编译被明确排除的类。

I thought that this kind of problem could be avoided by removing the :all tag from :aot compilation.我认为可以通过从:aot编译中删除:all标签来避免这种问题。 Eg:例如:

(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})

which causes other problems:这会导致其他问题:

❯ 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

I've tried playing around with all kinds of :exclusions , :jar-exclusions and regexes.我尝试过各种:exclusions:jar-exclusions和正则表达式。 Variations of this question have been asked multiple times ( 1 , 2 ) Nothing works.此问题的变体已被多次询问 ( 1 , 2 ) 没有任何效果。

How do I get Leiningen to compile uberjars and ignore the specified file(s)?如何让 Leiningen 编译 uberjars 并忽略指定的文件?

You are on the right track with changing :aot :all to :aot [app.core] but when you tried to run the JAR, you are running the library version instead of the whole application version:您将:aot :all更改为:aot [app.core]但是当您尝试运行 JAR 时,您运行的是版本而不是整个应用程序版本:

java -jar ./target/app-0.1.0-SNAPSHOT.jar 

That doesn't include Clojure or any dependencies.这不包括 Clojure 或任何依赖项。 You want:你要:

java -jar ./target/app-0.1.0-SNAPSHOT-standalone.jar 

I haven't tried this particular setup with the "exclusions" features.我还没有尝试过这种带有“排除”功能的特殊设置。

One workaround would be to create sub-projects for the "local" & "remote" parts of your app, which could then be used by a higher-level "total" project.一种解决方法是为应用程序的“本地”和“远程”部分创建子项目,然后可以由更高级别的“总”项目使用。

app
  app-local
  app-remote

where each of the 3 is a separate Lein project.其中 3 个中的每一个都是一个单独的 Lein 项目。 app-local and app-remote could be developed in isolation. app-localapp-remote可以单独开发。 The top-level app project then uses has the 2 sub-projects as dependencies (and therefore only works in the remote/full environment).然后顶级app项目使用 2 个子项目作为依赖项(因此仅适用于远程/完整环境)。

The Lein feature checkouts allows you to develop in all 3 repos simultaneously, which is a huge help. Lein 功能检出允许您同时在所有 3 个存储库中进行开发,这是一个巨大的帮助。 It is much faster than the alternative of using lein install , which is slow, manual, repetitive, and error-prone.它比使用lein install的替代方法lein install ,后者缓慢、手动、重复且容易出错。


PS Did you experiment with using lein jar instead of lein uberjar ? PS 您是否尝试过使用lein jar而不是lein uberjar

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM