【问题标题】:How to specify output.classesDir for custom sourceSet in Gradle?如何在 Gradle 中为自定义 sourceSet 指定 output.classesDir?
【发布时间】:2016-09-16 21:59:42
【问题描述】:

我的构建使用来自两个项目的源代码:ProjectA 和 ProjectB,并使用来自 ProjectB 的类和资源生成 JAR。我定义了自定义 sourceSet mainProjectB 应该在单独的目录中输出:

sourceSets {
    mainProjectB {
        output.classesDir = "$buildDir/build/classes/projectB"
        output.resourcesDir = "$buildDir/build/resources/projectB"
        java { srcDirs = ['src/main/java']}
        resources { srcDirs = ['src/main/resources']}
    }
    mainProjectA {
        java { srcDirs = [
                '../projectA/src/main/java'
            ]}
        resources { srcDirs = [
                '../projectA/src/main/resources'
            ]}
    }
    test {
        java {
            srcDirs = [
                '../projectA/src/test/java',
                'src/test/java'
            ]}
        resources {
            srcDirs = [
                '../projectA/src/test/resources',
                'src/test/resources'
            ]}
    }
}

compileJava {
    source sourceSets.mainProjectB.allJava
    source sourceSets.mainProjectA.allJava
}

processResources {
    from sourceSets.mainProjectB.resources
    from sourceSets.mainProjectA.resources
}

jar {
    from sourceSets.mainProjectB.output.classesDir
    from sourceSets.mainProjectB.output.resourcesDir
}

问题:自定义 sourceSet mainProjectB 输入指定的输出目录。 没有创建目录“$buildDir/build/classes/projectB”和“$buildDir/build/resources/projectB”,因此,JAR 包含来自两个项目(而不是 ProjectB)的文件。

更新:
项目 A 和 B 具有循环依赖关系。这就是他们必须共享源代码的原因。

【问题讨论】:

  • 你是在做一个合并projectA和projectB内容的jar吗?
  • 否:带有来自 ProjectB 的类和资源的 JAR

标签: gradle jar


【解决方案1】:

我会考虑使用子项目和项目来实现您的目标 - gradel docs 。使用以下方法,您可以获得任何类型的 jar 文件,具体取决于您的构建:

group 'CoreProject'
version '1.0-SNAPSHOT'
subprojects {
    apply plugin: 'java'
    repositories {
        mavenCentral()
    }
}

project (':projectA') {

}

project (':projectB') {
    def generatedResources = "$buildDir"
    //in case you want resources and classes to be written to custom location where 
    //redefined paths are relative to projectB root folder 
    sourceSets {
        main {
            output.classesDir = 'build/classes/projectB'
            output.resourcesDir = 'build/resources/projectB'
        }
    }
    dependencies {
        compile project(':projectA')
    }
    jar {
        manifest.mainAttributes(
                'Main-Class': "ProjectBClass"
        )
    }

    //To create fat Jar that will contain classes and resources from all dependencies
    task fatJar(type: Jar) {
        manifest.from jar.manifest
        classifier = 'all'
        from {
            configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
        } {
            exclude "ProjectAResource" //if want to exclude resources from projectA
            exclude "META-INF/*.SF"
            exclude "META-INF/*.DSA"
            exclude "META-INF/*.RSA"
        }
        with jar
    }
}

如果您运行 projectB 的 jar 任务,将创建​​以下 jar,每个 jar 仅包含其自己的类和资源:projectA/build/libs/projectA.jar,projectB/build/libs/projectB.jar('JAR 包含 ProjectB 中的类和资源',正如您在评论中所问的那样)

如果您运行 projectB 的 farJar 任务,将创建​​以下 jar 文件,其中包含来自两个项目的类和资源,您可以从 projectA 和 projectB 项目中排除任何文件模式以创建您的任何最终 jar比如:projectB/build/libs/projectB-all.jar

这是我为模仿您的场景而创建的项目文件夹结构的屏幕截图(据我了解):

附:还要确保没有任何文件夹 projectB/build 和 projectA/build 被任何进程锁定,如果有的话,删除这些句柄,否则 Gradle 将无法运行。

【讨论】:

  • 项目 A 和 B 具有循环依赖关系。这就是他们必须共享源代码的原因,因此您的方法不适用于我的用例。
  • 不适用于 Gradle 5,classesDir 已被弃用
猜你喜欢
  • 1970-01-01
  • 2013-08-11
  • 2023-03-17
  • 2011-03-12
  • 2015-11-14
  • 1970-01-01
  • 2012-07-13
  • 2019-01-18
  • 1970-01-01
相关资源
最近更新 更多