如何在 Gradle 中定义编译时 *only* 类路径?

Posted

技术标签:

【中文标题】如何在 Gradle 中定义编译时 *only* 类路径?【英文标题】:How do I define a compile-time *only* classpath in Gradle? 【发布时间】:2012-05-11 11:14:15 【问题描述】:

谁能给我一个简单的 build.gradle 示例,说明如何指定不包含在运行时部署 (war) 中的仅编译时类。

Gradle 似乎搞错了,因为 'runtime' 继承自 'compile'。我无法想象在运行时我想要在编译时不想要的类的情况。但是,在许多情况下,我需要类在编译时生成我不希望在运行时部署的代码!

我浏览了臃肿的 gradle 文档,但找不到任何明确的说明或示例。我怀疑这可以通过定义“配置”并将其设置为 CompileJava 插件的类路径来实现 - 但文档不足以解释如何实现这一点。

【问题讨论】:

我认为当前最新的正确答案是 xsveda 使用 compileOnly 配置。 【参考方案1】:

关于这个话题已经有很多讨论了,主要是here,但是没有明确的结论。

您走在正确的轨道上:目前最好的解决方案是声明您自己的 provided 配置,这将包括仅编译依赖项并添加到您的编译类路径中:

configurations
  provided


dependencies
  //Add libraries like lombok, findbugs etc
  provided '...'


//Include provided for compilation
sourceSets.main.compileClasspath += [configurations.provided]

// optional: if using 'idea' plugin
idea 
  module
    scopes.PROVIDED.plus += [configurations.provided]
  


// optional: if using 'eclipse' plugin
eclipse 
  classpath 
    plusConfigurations += [configurations.provided]
  

通常这很有效。

【讨论】:

有没有人让它与 android Studio 和 gradle 1.9 一起工作? 您可以在多个站点上找到提供的范围定义。但是 ide 插件部分对我帮助很大! 我对 Gradle 还是很陌生,我在我的 Android Studio 项目中使用它。当我尝试添加上述内容(关于想法 ... 子句的所有内容)时,我收到一条错误消息,提示“在 SourceSet 容器上找不到属性 main”。我还有什么需要做的吗? 对于 Gradle 2.0,您必须写:idea module scopes.PROVIDED.plus += [configurations.provided] 更多详细信息请参阅forums.gradle.org/gradle/topics/… Gradle3: sourceSets.main.compileClasspath += configurations.provided【参考方案2】:

如果您使用 war 插件,providedCompile 应该可以解决问题。 但是,如果您需要排除在 jar 中包含的依赖项,则必须扩展 jar 任务。 下面是一个构建“fat jar”或“uber jar”的示例(一个包含其依赖项的所有类的单个 jar),不包括标记为 provided 的依赖项:

configurations 
    provided
    compile.extendsFrom provided


dependencies 
    provided "group.artifact:version"
    compile "group.artifact:version"


jar 
    dependsOn configurations.runtime
    from 
        (configurations.runtime - configurations.provided).collect 
            it.isDirectory() ? it : zipTree(it)
        
     

信用:http://kennethjorgensen.com/blog/2014/fat-jars-with-excluded-dependencies-in-gradle/

更新:

Gradle 2.12 开始,定义仅编译依赖项的问题终于通过新的“copmpileOnly”配置以简单自然的方式解决了:

dependencies 
    compileOnly 'javax.servlet:servlet-api:2.5'

【讨论】:

这是迄今为止最好的通用/非安卓答案。对于在编译时需要依赖但需要从 jar 中排除的 hadoop 和 Storm 库非常有用。【参考方案3】:

我为我的项目设置解决了这个问题。 我使用带有 gradle 插件 0.9.+ 和 gradle 1.11 的 Android Studio 主要项目使用亚马逊广告和亚马逊应用内购买。 它依赖于使用亚马逊设备消息(ADM)的库项目。

我的主要问题是出现“RuntimeException:Stub!”的 ADM。错误。

1.) 图书馆项目: 正如他所说,Lukas 提出的“提供的配置”不起作用,所以我使用了 Richards 的方法,但是开箱即用的效果并不好。由于在 aar 文件的 ext_libs 文件夹中找不到该库,因此我不得不对其进行一些更改。 Gradle 似乎将所有库打包在最终 aar 文件中的 libs 文件夹中。

android.libraryVariants.all  variant ->
variant.packageLibrary.exclude( 'libs/amazon-device-messaging-1.0.1.jar' )

2.) 应用项目: 在这里,“提供的配置”的方法奏效了。

configurations
    provided
 
dependencies 
    compile 'fr.avianey:facebook-android-api:+@aar'
    compile files('ext_libs/amazon-ads-5.3.22.jar')
    compile files('ext_libs/in-app-purchasing-1.0.3.jar' )
    provided files('ext_libs/amazon-device-messaging-1.0.1.jar')


android.applicationVariants.all 
    variant -> variant.javaCompile.classpath += configurations.provided

【讨论】:

我可以确认排除库的解决方案适用于应用插件:'com.android.library',诀窍是将它从'libs'中排除,即使你有任何其他的库文件夹,如上所述 gradle 将其全部放入 libs 文件夹中。非常感谢迈克。【参考方案4】:

运行时依赖不是编译时依赖是很常见的。另一种方式是一种相当特殊的情况,因此需要在 Gradle 中进行几行配置。我建议在Gradle forum 中搜索provided

听起来你真正想要的是为你的 build 声明依赖项,而不是为编译类路径声明依赖项。这是如何完成的取决于如何调用所需的功能(Ant 任务、Gradle 任务/插件、构建脚本中的临时使用)。如果您提供有关您要做什么的更详细信息,我可以提供更具体的答案。

以下是 Gradle 用户指南中相关信息的一些链接:

External dependencies for the build script Declaring the class path for a custom Ant task

【讨论】:

【参考方案5】:

如果你使用 WAR 插件,你可以使用providedCompile,就像这个example一样

dependencies 
    compile module(":compile:1.0") 
        dependency ":compile-transitive-1.0@jar"
        dependency ":providedCompile-transitive:1.0@jar"
    
    providedCompile "javax.servlet:servlet-api:2.5"
    providedCompile module(":providedCompile:1.0") 
        dependency ":providedCompile-transitive:1.0@jar"
    
    runtime ":runtime:1.0"
    providedRuntime ":providedRuntime:1.0@jar"
    testCompile "junit:junit:4.11"
    moreLibs ":otherLib:1.0"

【讨论】:

【参考方案6】:

在 Gradle 2.12 中引入了 compileOnly 配置。可以在此处找到介绍此功能的博客文章:

Gradle latest feature: Compile only dependencies

请注意一个重要的副作用:

由于添加了“compileOnly”配置,“compile”配置不再代表所有编译时依赖项的完整图景。当需要在构建脚本或自定义插件中引用编译类路径时,应使用适当的源集的 compileClasspath 属性。

【讨论】:

【参考方案7】:

事实证明,他们在 gradle android 插件 0.8.0 中添加了一个“提供的”配置,但它并不完全有效。它会自动将提供的库添加到编译路径中,但也会将它们包含在最终的 aar/apk 中。

对我有用的是@lukas-hanaceck 提供的解决方案,但将名称从“提供”更改为任何其他自定义名称。就我而言,这是一个库项目,它是我最终的 android 应用程序项目的依赖项。以下是对我有用的要点。

configurations 
   providedlibs


dependencies 
   providedlibs files('provided/library.jar')


libraryVariants.all 
    variant -> variant.javaCompile.classpath += configurations.providedlibs

它可以完美编译,并且提供的/library.jar 不包含在最终的 apk 中。我遇到的唯一问题是通知 Android 工作室 library.jar 的存在。这个想法插件似乎不适用于 Android 工作室。我猜他们有另一个自定义插件,用于将 gradle 与 studio 同步。

【讨论】:

我确认股票providedAndroid Gradle 1.0.1 配置确实正确地出现在编译类路径中,但随后又强制进入 APK,这违背了目的。其中许多答案非常相似。我用这个作为模板,它对我来说很好用。它适用于 jar(远程和本地)依赖项,但不适用于 AAR。作为一种解决方法,我最终将 classes.jar 从 AAR 中分离出来。【参考方案8】:

我没有找到适用于 Android Studio 的解决方案,但这是我尝试过的:

在 android studio 中我必须更新到版本 0.5.+

在 gradle/gradle-wrapper.properties 中替换

distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-rc-3-bin.zip

通过

distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip

在我所有的 build.gradle 中替换

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath 'com.android.tools.build:gradle:0.7.+'
    

通过

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath 'com.android.tools.build:gradle:0.9.+'
    

在我想使用的库中提供

configurations 
    provided


//put applicationVariants in case it is apply plugin: 'android' and not apply plugin: 'android-library'
android.libraryVariants.all 
    variant -> variant.javaCompile.classpath += configurations.provided


dependencies 
    provided files('ext_libs/amazon-device-messaging-1.0.1.jar')

最后它不起作用,它似乎适用于 jar 但不适用于 aar 或 apk,如此处所述https://groups.google.com/forum/#!topic/adt-dev/WIjtHjgoGwA

【讨论】:

【参考方案9】:

在 Android Studio 1.0 中这样做:

android.libraryVariants.all  variant ->
    variant.outputs.each  output ->
        output.packageLibrary.exclude('libs/someLib.jar')
    

【讨论】:

【参考方案10】:

我们不需要“提供”,尝试添加这个:

android.libraryVariants.all  variant ->
    variant.packageLibrary.exclude( 'ext_libs/amazon-device-messaging-1.0.1.jar' )

享受吧!

【讨论】:

【参考方案11】:

OP 显然没有寻找 Android 答案,但有些答案是针对 Android 的。所以我建议你看看这个页面:http://tools.android.com/tech-docs/new-build-system

0.9.0 版引入了提供的范围。所以,只需使用

dependencies 
    provided "groupId:artifcatId:version"

【讨论】:

以上是关于如何在 Gradle 中定义编译时 *only* 类路径?的主要内容,如果未能解决你的问题,请参考以下文章

gradle编译时注解增量教程

如何使用 monotouch 编译库(出现错误:尝试使用 --aot-only 进行 JIT 编译)

将eclipse导入android studio时如何修复错误?(作为build.gradle的编译时依赖项)

打通Android Gradle编译过程的任督二脉

查找在gradle中运行编译器的JDK的位置

在 buildSrc 中定义的 Gradle Kotlin DSL 未解析的引用