Ant 到 Gradle:可执行 JAR 转换

Ant to Gradle: Executable JAR conversion

我已经坚持了好几天了。我目前的任务是将相当多的 ant 脚本转换为 gradle。我对两者的复杂性都不是很了解,所以请原谅我的无知。

我没有在我的代码中使用依赖项或存储库,因为这是针对离线电脑的,但是我需要的所有 classes 和 jar 都可以在本地获得。到目前为止,转换一直在进行,但我还停留在可执行 jar 任务的转换上。

这是(本质上)ant 脚本:

<target name="makeJar">
  <jar destfile="someJar.jar">
    <fileset dir="somePlace"/>
    <fileset dir="someOtherPlace"/>
    <manifest>
      <attribute name="Main-Class" value="SOME.ARCHIVE.Main"/>
    </manifest>
    <zipgroupfileset dir="localFiles" includes="*.jar"/>
  </jar>   
</target>

SOME.ARCHIVE 在本地 .jar 文件之一中。我认为我的主要问题是,当我 运行 我的 gradle 脚本时,它只是将所有 classes 和 jar 一起加载并且几乎将它们压缩起来,所以它不可执行,虽然它应该是。 (这导致找不到SOME.ARCHIVE的Main-Class。) 我比较了从任一脚本中提取的 .jars,目录结构存在非常严重的差异 - gradle 脚本不会生成来自提取的 jars 的各种 poms。

我认为主要问题是我不知道如何复制 zipgroupfileset 的效果。我认为我可以规避的方式似乎过多(提取 jar,复制到包含 class 文件的目录,jar-ing 该目录)。在这一点上,从 gradle 导入 ant 脚本和 运行 似乎更有意义,但我不想这样做。

这是我的 gradle 脚本:

task makeJar (type: Jar) {
    baseName = "someJar"
    from files('somePlace')
    from files('someOtherPlace')
    from fileTree(dir: 'localFiles', include: '*.jar')

    manifest {
        attributes 'Main-Class': 'SOME.ARCHIVE.Main'
    }
}

编辑:我发布了对我有用的内容。 JBirdVegas 的回答可能是更合适的做法。

您可以通过 configurations 组件从类路径中打包所有 类。当然,如果需要,您可以在 from 中提供更多逻辑以仅包含特定文件或任何您的特定用例。

task fatJar(type: Jar) {
    manifest.attributes = jar.manifest.attributes
    includeEmptyDirs = jar.includeEmptyDirs
    baseName = project.name + '-fat'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

jar {
    manifest {
        attributes 'Implementation-Title': 'My executable jar!',
                'Implementation-Version': version,
                'Main-Class': 'com.example.so.q39209051.Main'
    }
    includeEmptyDirs false
    dependsOn 'fatJar'
}

对我读取 .jar 文件的方式进行了一些调整。 我现在不使用 fileTree(),而是使用 zipTree() 并遍历现有的 jar 文件。

task makeJar (type: Jar) {
    baseName = "someJar"
    from files('somePlace')
    from files('someOtherPlace')

    def mahJars =  fileTree('localFiles').filter { it.name.endsWith('.jar') }.files.path
    mahJars.each { one ->  from zipTree("$one") }

    manifest {
        attributes 'Main-Class': 'SOME.ARCHIVE.Main'
    }
}

我使用 .path 而不是 .name,因为有些子目录也包含 jar。使用 .name 会导致 MD5 哈希错误,因为它正在寻找不存在的目录中的文件。

{ it.name.endsWith('.jar') }.files.path