groovy - 发布工件覆盖Gradle中的其他工件

标签 groovy gradle ivy

我正在尝试使用Gradle构建一些jar,而不是维护一个包含EJB的类的列表,以便我可以分别部署它们,我认为在制作jar时扫描类可能很简洁。

与其加载类并使用反射来获取注释,不如使用asm扫描类可能更简单,因此在其中一项任务中使用笨拙的ClassReader。

我不认为这是个问题,因此可以忽略不计,基本上我有2个任务用于定义jar的内容,两个任务都报告每个内容都是通过eachFile打印出来的,但是当我查看时文件和关联的sha1的发布存储库位置相同。

要么Gradle坏了,或更可能是我做了一些疯狂的事情,但看不到它是什么,有人可以帮忙吗?

顺便说一句,如果我禁用了两个jar文件中的任何一个的发布,那么确实创建的jar文件是正确的,所以我认为发布是错误的,而不是令人讨厌,但这可能是错误的。

// ASM is used to interpret the class files, this avoids having to load all classes in the vm and use reflection
import org.objectweb.asm.*
task ejbJar(type: Jar) {
  //outputs.upToDateWhen { false }
  from "${project.buildDir}/classes/main"
  eachFile { println "EJB server: ${name}" }
  include getEjbClassFiles(project.buildDir)
}

task clientEjbJar(type: Jar) {
  //outputs.upToDateWhen { false }
  from "${project.buildDir}/classes/main/com/company/core/versioner"
  eachFile { println "Client EJB ${name}" }  
  include '**/*'
}

artifacts {    
  archives clientEjbJar
  archives ejbJar
}
String[] getEjbClassFiles(base) {
  def includedFiles = []
  def baseDir = project.file("${base}/classes/main")
  def parentPath = baseDir.toPath()
  if (baseDir.isDirectory()) {
    baseDir.eachFileRecurse(groovy.io.FileType.FILES) { file ->
      if(file.name.endsWith('.class')) {
        //get hold of annotations in there --- org.objectweb.asm.Opcodes.ASM4
        def reader = new ClassReader(file.bytes).accept(
          new ClassVisitor(Opcodes.ASM4) {
            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
              if(desc.equals("Ljavax/ejb/Stateless;") ||
                desc.equals("Ljavax/ejb/Stateful;")) {
                includedFiles += parentPath.relativize(file.toPath())
              }
              return null //no interest in actually visiting the annotation values
            }
          }, 
          ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE
        )
      }
    }
  }
  return includedFiles
}    

publishing {
  publications {
    mypub(IvyPublication) {
      artifact(ejbJar) {
        name 'ejb' 
      }
      artifact(clientEjbJar) { 
        name 'client-ejb' 
      }
    }
  }
  repositories {
    ivy {
      name 'personal'
      url "${ant['developer.repository']}/"
      layout 'pattern', {
        artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
    ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
      }
    }   
  }  
}

我确实把事情分解成一个简单的形式,因为我认为这可能是Gradle的错误。

简化形式为:
apply plugin: 'java'
apply plugin: 'ivy-publish'

task bigJar(type: Jar) {
  from "${rootDir}/src/main/resources"
  include '**/*'
}

task smallJar(type: Jar) {
  from "${rootDir}/src/main/resources/A/B"
  include '**/*'
}

group 'ICantBeEmpty'
artifacts {
  archives bigJar
  archives smallJar
}

publishing {
  publications {
    mypub(IvyPublication) {
      artifact(bigJar) { name 'biggie' }
      artifact(smallJar) { name 'smallie' }
    }
    repositories {
  ivy {
    name 'personal'
    url "c:/temp/gradletest"
    layout 'pattern', {
      artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
      ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
    }
      }
    }
  }
}

这将在c:/temp/gradletest/ICantBeEmpty/report-bug/biggie/unspecified/biggie-unspecified.jar和c:/ temp / gradletest / ICantBeEmpty / report-bug / smallie / unspecified / smallie-unspecified中生成2个文件。 jar
这两个文件是相同的,但是我想我知道为什么看到我以后的答案。

最佳答案

在查看一些配置时,我注意到一些奇怪的行为使我得以解决此问题,并且这是Gradle的错误。

在我的构建中,我有一个从头开始的任务

configurations.archives.artifacts.each { println it }

这给了我5条不同的线输出,但是将其更改为
configurations.archives.artifacts.each { println it.file }

产生相同的文件名5次。

事实证明,这与我的问题有关,尽管这些 Artifact 作为单独的实体存在,用于唯一标识它们的名称是相同的,因此在发布期间始终选择同一文件。 Artifact 的名称由$ {baseName}-$ {appendix}-$ {version}-$ {classifier}。$ {extension}在Java插件中默认指定。这意味着,如果未指定附录或分类器,则 Artifact 将具有相同的名称。

我通过添加附录名称使用上面的示例代码对此进行了测试
task bigJar(type: Jar) {
  appendix = 'big'
  from "${rootDir}/src/main/resources"
  include '**/*'
}

task smallJar(type: Jar) {
  appendix = 'small'
  from "${rootDir}/src/main/resources/A/B"
  include '**/*'
}

使用此代码而不是问题中的代码会生成2个不同的jar。

关于groovy - 发布工件覆盖Gradle中的其他工件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15879900/

相关文章:

java - ivy:使用分类器从 maven 安装

java - Java项目的定制构建生命周期

java - UncaughtExceptionHandler 未调用

java - Gradle 分发创建文件

ant - Ivy - 两次解析相同的依赖项(使用两个不同的版本),到两个不同的文件

properties - 如何在 gradle.properties 中使用用户环境变量

gradle - “./gradlew {package}-rpm”之后会发生什么

java - Grails 的 AOP

groovy - 在groovy中读写文件

jenkins - Groovy:读取数组中文件的内容并为某些内容进行 grep