首页 文章

拆分Gradle中的所有输出目录

提问于
浏览
29

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

现在我收到以下警告:

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

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


我试过的事情:

  • gradle clean 后跟 gradle build

  • 删除构建目录,然后运行 gradle build .

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


相关GitHub issue


Gradle插件:

  • java

  • 日食

  • 想法

  • org.springframework.boot

3 回答

  • 15

    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() ,您会收到此警告 .

    Officially recommended way to get rid of this warning is

    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://docs.gradle.org/current/javadoc/org/gradle/api/tasks/SourceSetOutput.html#getClassesDir()标记 getClassesDir() as deprecated .

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

    另一个问题是测试文件 . If you don't like to have different hierarchy layoutbuild/classes/mainbuild/classes/java/test )你也应该调整测试路径:

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

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

    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 .

  • -1

    这是由于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

  • 5

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

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

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

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

相关问题