简体   繁体   English

在gradle中删除传递类路径依赖项

[英]Remove transitive classpath dependency in gradle

we're running a spring-boot app with gradle. 我们正在用gradle运行一个spring-boot应用程序。

In order to include the spring-boot plugin we add it as dependency: 为了包含spring-boot插件,我们将其添加为依赖项:

buildscript {
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE") 
    }
}

Unfortunately this plugin ships with a dependency to org.apache.logging.log4j:log4j-slf4j-impl:2.4.1 不幸的是,这个插件附带了对org.apache.logging.log4j:log4j-slf4j-impl:2.4.1的依赖org.apache.logging.log4j:log4j-slf4j-impl:2.4.1

Which I'd like to exclude. 我想排除。

Already tried that by adding: 已经尝试过添加:

  dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE") {
            exclude group: 'org.apache.logging.log4j'
        }
    }

Which doesn't work. 哪个不起作用。

Also adding: 还添加:

configurations {
    classpath.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
}

Doesn't have any effect. 没有任何影响。

Any hint is welcome. 任何提示都是受欢迎的。

If you're trying to exclude 如果你想排除

org.apache.logging.log4j:log4j-slf4j-impl:2.4.1

Try 尝试

dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE") {
        exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
    }
}

I usually fallback to this when i want to make sure that a dependency never added to a project. 当我想确保从未添加到项目中的依赖项时,我通常会回退到此。

configurations {
    all*.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl', version '2.4.1'
}

But are you sure you need to exclude the dependency. 但是你确定你需要排除依赖。 It should not be part of the build jar/war. 它不应该是构建jar / war的一部分。 You can check all dependencies using "gradlew dependencies". 您可以使用“gradlew dependencies”检查所有依赖项。

Two steps, chase down the transitive dependency then exclude it from the library responsible. 两个步骤,追逐传递依赖,然后将其从负责的库中排除。

gradle dependencies gives you the full list including the transitive. gradle dependencies为您提供包含传递的完整列表。 If your project is small that can be helpful but for large enterprise builds... its too much info. 如果您的项目很小,可能会有所帮助,但对于大型企业版本......它的信息太多了。 Feel free to search through it but we get more to the point information from dependencyInsight . 随意搜索它,但我们从dependencyInsight得到更多的点信息。

gradle dependencyInsight --dependency someDependency finds all the places the dependency could come into the build. gradle dependencyInsight --dependency someDependency查找依赖项可能进入构建的所有位置。 If you have multiple versions this will help make it apparent where the versions originate. 如果您有多个版本,这将有助于明确版本的来源。

In my usecase logging is explicitly declared as a compile time dependency so it shows as below. 在我的用例中,日志记录显式声明为编译时依赖项,因此它显示如下。 If log4j was anywhere else you would see the offending library as well as the compile time declaration for v 2.5 . 如果log4j在其他任何地方,您将看到违规库以及v 2.5的编译时声明。

I had to run this explicitly on each sub module. 我必须在每个子模块上明确地运行它。

$ gradle util:dependencyInsight --dependency org.apache.logging.log4j
Configuration on demand is an incubating feature.
:util:dependencyInsight
org.apache.logging.log4j:log4j-api:2.5
+--- compile
\--- org.apache.logging.log4j:log4j-core:2.5
     \--- compile

org.apache.logging.log4j:log4j-core:2.5
\--- compile

(*) - dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 0.933 secs

Now once you know where to exclude the dependency from just do like before to remove it. 现在,一旦你知道从哪里排除依赖,就像之前一样去除它。 You can confirm by running the dependencyInsights again 您可以通过再次运行dependencyInsights进行确认

dependencies {
    // found through `gradle dependencyInsight --dependency org.apache.logging.log4j`
    classpath("someOtherGroup:someOtherArtifactId:1.0") {
        exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
    }
}

Another solution could be overriding the dependency resolver and force the version to 2.5 另一个解决方案可能是覆盖依赖项解析器并强制版本为2.5

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == "org.apache.logging.log4j") {
            println "Updating version for: $details.requested.group:$details.requested.name:$details.requested.version --> 2.5"
            details.useVersion '2.5'
        }
    }
}

My opinion, I probably don't want to keep adding checks in the resolutionStrategy all the time so probably better to just track it down in the dependencyInsights . 我的意见是,我可能不想一直在resolutionStrategy添加检查,所以最好在dependencyInsights跟踪它。 Also this means updating the version in two places and if another developer isn't aware of how gradle's resolutionStrategy works then they will have "weird" behavior... eg. 这也意味着在两个地方更新版本,如果另一个开发人员不知道gradle的resolutionStrategy如何工作,那么他们将有“怪异”的行为......例如。 I updated log4j to 2.7 but it still builds with 2.5 ?!?! 我将log4j更新为2.7但它仍然以2.5建立?!?!

But both are valid approaches 但两者都是有效的方法

Somehow the issue was that I declared log4j as runtime dependency: 不知何故问题是我将log4j声明为运行时依赖:

  ext {
       log4jVersion="2.5"
  }
  runtime (
            "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion",
            "org.apache.logging.log4j:log4j-api:$log4jVersion",
            "org.apache.logging.log4j:log4j-core:$log4jVersion"
        )

Which lead to the case that version 2.4.1 was fetched by some editor magic as compile dependency. 这导致版本2.4.1被某些编辑魔术作为编译依赖项提取。

Therfore I had then 2.4.1 and 2.5 on the classpath. 因此,我在类路径上有2.4.1和2.5。

As soon as I declared log4j as compile dependency 2.4.1 is gone... 一旦我将log4j声明为编译依赖性2.4.1就消失了......

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

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