拆分Gradle中的所有输出目录

Gradle 4.0昨天问世了,我为它更新了我的项目。

现在我收到以下警告:

Gradle现在为每种JVM语言使用单独的输出目录,但是此构建假定源集中的所有类都有一个目录。 此行为已被弃用,计划在Gradle 5.0中删除

我想为每种语言使用单独的输出目录。 为了实现这一目标,我需要做些什么改变?


我试过的事情:

  • gradle clean然后gradle build
  • 删除构建目录然后运行gradle build
  • 删除gradle和build目录然后运行gradle

相关的GitHub 问题


Gradle插件:

  • java的
  • 日食
  • 理念
  • org.springframework.boot

Gradle 4.0为每个JVM语言引入了多个sourceSet,以便启用远程构建缓存。 使用java插件,你的build/classes/main应该变成build/classes/java/mainbuild/classes/test应该变成build/classes/java/test等。

该警告的定义如下:

https://github.com/gradle/gradle/blob/bb0ed850aa4061931a62133091d66c56551cf5e0/subprojects/plugins/src/main/java/org/gradle/api/internal/tasks/DefaultSourceSetOutput.java#L79

 @Override public File getClassesDir() { if (isLegacyLayout()) { return fileResolver.resolve(classesDir); } SingleMessageLogger.nagUserOfDeprecatedBehaviour("Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set"); Object firstClassesDir = CollectionUtils.findFirst(classesDirs.getFrom(), Specs.SATISFIES_ALL); if (firstClassesDir!=null) { return fileResolver.resolve(firstClassesDir); } return null; } 

因此,如果项目中的任何插件或build.gradle调用DefaultSourceSetOutput.getClassesDir()则会收到此警告。

正式推荐的摆脱这种警告的方法是

 sourceSets.main.output.classesDir = new File(buildDir, "classes/main") 

对应于:

 @Override public boolean isLegacyLayout() { return classesDir!=null; } @Override public void setClassesDir(File classesDir) { setClassesDir((Object)classesDir); } @Override public void setClassesDir(Object classesDir) { this.classesDir = classesDir; this.classesDirs.setFrom(classesDir); } 

请注意, https: getClassesDir() getClassesDir()标记为已弃用

因此,在项目中所有使用过的插件获得对Gradle 4.0的支持之前,您应该坚持使用变通方法并忽略Gradle源代码构建脚本中的弃用。

另一个问题是测试文件。 如果你不喜欢有不同的层次结构布局build/classes/mainbuild/classes/java/test ),你也应该调整测试路径:

 sourceSets.main.output.classesDir = new File(buildDir, "classes/main") sourceSets.test.output.classesDir = new File(buildDir, "classes/test") 

更新 IDEA的用户可能会注意到IDE开始使用单独的目录来构建它检测到Gradle 4.x. 如果您在IDEA之外运行应用程序,这将导致无法重新加载应用程序。 要修复添加和重新导入:

 subprojects { apply plugin: 'idea' // Due to Gradle 4.x changes (separate output directories per JVM language) // Idea developers refuse to reuse Gradle classpath and use own 'out/' directory. // Revert to old behavior to allow Spring Devtool to work with using fast Idea compiler. // https://youtrack.jetbrains.com/issue/IDEA-175172 // Alternatively use native Gradle builds or bootRun.addResources = true // To use this feature push Ctrl+Shift+F9 to recompile! // Be aware that Idea put resources into classes/ directory!! idea.module.inheritOutputDirs = false idea.module.outputDir = sourceSets.main.output.classesDir idea.module.testOutputDir = sourceSets.test.output.classesDir } 

请注意,IDEA将资源放在与.class文件相同的目录中,这样您的Gradle类路径就会被破坏。 只需对使用IDEA内置构建命令(Ctrl + Shift + F10等)的模块进行gradle clean

这是由于Gradle 4.0中引入的更改:如果有多个语言源,它现在使用单独的输出目录。

要返回旧行为并删除警告,请将其插入build.gradle:

// Change the output directory for the main source set back to the old path sourceSets.main.output.classesDir = new File(buildDir, "classes/main")

参考: https : //docs.gradle.org/4.0/release-notes.html#multiple-class-directories-for-a-single-source-set

例如,如果混合Java,Kotlin和Groovy项目结构应如下所示:

 root/ src/ main/ java/ kotlin/ groovy/ test/ java/ kotlin/ groovy/ 

build.gradle中,您必须指定特定语言所需的插件。

 apply plugin: 'java' apply plugin: 'groovy' apply plugin: 'kotlin'