【问题标题】:Gradle: package multi-project into a single jarGradle:将多项目打包成一个jar
【发布时间】:2018-07-30 23:25:06
【问题描述】:

我有一个 gradle 多项目,并想创建一个包含我的子项目的所有类和外部依赖项的单个 jar(库)。

我有以下项目结构。每个项目都有自己的第 3 方依赖项。公共依赖项包含在根项目中。两个模块 A 和 B 都依赖于内核。

+ root-project (only build.gradle and settings.gradle)
  - core       (src/main/java, src/main/resources, ..)
  - module-A   (src/main/java, src/main/resources, ..)
  - module-B   (src/main/java, src/main/resources, ..)

为了导出单个 jar,我在根项目的 build.gradle 中添加了以下任务:

apply plugin: "java"

subprojects.each { subproject -> evaluationDependsOn(subproject.path)}

task allJar(type: Jar, dependsOn: subprojects.jar) {
    baseName = 'multiproject-test'
    subprojects.each { subproject ->
        from subproject.configurations.archives.allArtifacts.files.collect {
            zipTree(it)
        }
    }
}

artifacts {
    archives allJar
}

此方法有效,但仅收集项目源文件。忽略第 3 方依赖项。所以我尝试了 Shadow Plugin (http://imperceptiblethoughts.com/shadow/),它也应该包含外部依赖项。

不幸的是,插件根本没有收集任何东西。这很可能是由于缺少根项目与其子项目之间的依赖关系。我如何告诉影子插件,它应该收集子项目的来源?或者有没有更好的方法从多个项目中导出单个库?

使用影子插件完成 build.gradle:

/****************************************
 * instructions for all projects
 ****************************************/
allprojects {
    apply plugin: 'idea'
    apply plugin: 'eclipse'

    group = 'com.test.multi-project'
    version = '1.0'
}

/****************************************
 * instructions for each sub project
 ****************************************/
subprojects {
    apply plugin: "java"

    sourceCompatibility = 1.9
    targetCompatibility = 1.9

    repositories {
        mavenCentral()
    }

    dependencies {
        compile "org.slf4j:slf4j-api:1+"
        compile "ch.qos.logback:logback-core:1+"
        compile "ch.qos.logback:logback-classic:1+"

        testCompile "junit:junit:4+"
    }
}

/****************************************
 * Single jar out of all sub projects
 ****************************************/
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
    }
}

apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'java'

shadowJar {
    baseName = 'multiproject-test'
} 

子模块包含在根项目的settings.gradle中

rootProject.name = 'myproject-root'

// submodules
include ":core"

include ":module-A"
include ":module-B"

感谢您的帮助!

【问题讨论】:

    标签: gradle fatjar


    【解决方案1】:

    如何在自己构建 jar 时获取所有运行时库

    jar {
        archiveName 'Some.jar'
    
        manifest {
            attributes 'Implementation-Title': 'Some',
            'Plugin-Class': 'main'
        }
        from {configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it)}}
    }
    

    【讨论】:

      【解决方案2】:

      我用这里解释的解决方案解决了我的问题:https://discuss.gradle.org/t/how-to-get-gradle-install-to-actually-bundle-all-project-subproject-classes-resources-etc/12070/4

      我的 build.gradle 现在看起来像这样:

      /****************************************
       * instructions for all projects
       ****************************************/
      allprojects {
          apply plugin: 'idea'
          apply plugin: 'java'
      
          repositories {
              mavenCentral()
          }
      
          group = 'com.test.multiproject'
          version = '1.0'
      
          sourceCompatibility = 1.9
          targetCompatibility = 1.9
      }
      
      /****************************************
       * instructions for each sub project
       ****************************************/
      subprojects {
      
          // common dependencies
          dependencies {
              compile "org.slf4j:slf4j-api:1+"
              compile "ch.qos.logback:logback-core:1+"
              compile "ch.qos.logback:logback-classic:1+"
      
              testCompile "junit:junit:4+"
          }
      }
      
      /****************************************
       * Single library jar containing all sub projects and 3rd party dependencies
       ****************************************/
      configurations {
          childJars
      }
      
      dependencies {
          subprojects.each {
              childJars project(it.path)
          }
      }
      
      jar {
          dependsOn configurations.childJars
          from { configurations.childJars.collect { zipTree(it) } }
      }
      

      【讨论】:

        【解决方案3】:

        那么简单的事情呢:

        task fatJar(type: Jar) {
            subprojects.each { subproject ->
                from subproject.configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
            }
        }
        

        【讨论】:

        • 感谢您的回复。我需要添加 doLast { subprojects.each ... } 才能让它工作。但是生成的 jar 只包含清单文件。你看到我做错了吗?我对 gradle 还是很陌生。
        • 如果我直接在根项目的 build.gradle 中添加 fatJar 任务(所有项目{}或子项目{}中没有嵌套),生成的 jar 只包含清单。我还尝试了这里解释的解决方案:discuss.gradle.org/t/…。即使这种方法有效,它也会在每个子文件夹中创建一个补充 jar,因此需要相当长的时间来构建。我不认为这是要走的路。所以我还在寻找更好的。
        猜你喜欢
        • 2012-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-05
        • 1970-01-01
        • 1970-01-01
        • 2014-11-23
        • 1970-01-01
        相关资源
        最近更新 更多