【问题标题】:How to make Gradle fail the build if a file dependency is not found?如果找不到文件依赖项,如何使 Gradle 构建失败?
【发布时间】:2017-07-20 12:55:26
【问题描述】:

我有一个 Gradle 构建,它具有一些表单的依赖项

compile files('path/to/local/lib.jar')

(正在迁移构建 - 最终这些将被替换)

构建失败,因为这些路径之一未正确指定。但由于编译错误而失败 - 看起来 Gradle 默默地忽略了丢失的依赖项。

如果任何依赖项(尤其是本地文件依赖项)无法解决(例如,文件丢失),是否有一个简单的选项或开关会强制 Gradle 使构建失败?

编辑:进一步澄清:

如果在配置的存储库中找不到依赖项,Gradle 将在尝试解析它们时使构建失败,正如预期的那样。

但是 - 如果依赖项被定义为“编译文件 ....”,并且指定的文件在构建时不存在,Gradle 将忽略该错误,并尝试编译。这似乎壮观错误的和不一致的默认行为。

我的问题是 - 我可以设置 Gradle 选项或开关或环境变量或系统属性来强制 Gradle 验证文件依赖项是否存在? (例如,以理智和理性的方式行事?)

【问题讨论】:

    标签: java gradle


    【解决方案1】:

    以下是使用 Gradle 7.3 检查传递依赖的方法(例如:如果项目直接或传递依赖 log4j,则失败)。

    Kotlin DSL

    configurations {
      all {
        relsolutionStrategy {
          eachDependency {
            if (requested.name == "log4j") {
              throw RuntimeException("Project depends on log4j")
            }
          }
        }
      }
    }
    

    Groovy DSL

    configurations.all {
        resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            if (details.requested.name == 'log4j') {
                throw new RuntimeException("Project depends on log4j")
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是一个老话题,但鉴于当前提出的解决方案都没有真正起作用,而且解决方案似乎很简单(整理其中两个),我将其留在这里以供将来参考。

      这里的重点是我们只是想确保文件确实存在,所以我们可以使用File类的exists()方法:

      task ensureDepsExist() {
          doLast {
              configurations.implementation.canBeResolved(true)
              Set<File> impFiles = configurations.implementation.resolve()
      
              impFiles.forEach { f ->
                  if (!f.exists()) {
                      ant.fail "${f} could not be found"
                  }
              }
          }
      }
      
      compileJava.dependsOn ensureDepsExist
      

      canBeResolved() 调用是必需的,否则 Gradle 会抱怨无法解析 configurations 依赖项。

      【讨论】:

        【解决方案3】:
        task ensureDependenciesExist() {
            doLast {
                configurations.implementation.canBeResolved(true)
                DependencySet deps = configurations.implementation.getDependencies()
                Set<File> impFiles = configurations.implementation.resolve()
                deps.each { d ->
                    boolean depWasResolved = impFiles.any { impFile -> impFile.name.find(".*${d.name}.*${d.version}") }
                    if (!depWasResolved) {
                        println "${d} was not resolved"
                        assert depWasResolved
                    }
                }
            }
        }
        
        compileJava.dependsOn ensureDependenciesExist
        

        【讨论】:

        • 嗨,欢迎来到 Stack Overflow。赞赏回答问题的努力。但是,不要只写一段代码,请考虑解释你的答案,为你的答案提供一点上下文。这可以帮助读者。
        • 更不用说,即使在最微不足道的情况下,这段代码也会惨遭失败
        【解决方案4】:

        您可以执行如下所示的操作。它不是内置的 Gradle 功能,但不需要代​​码来专门检查每个依赖项(它会在 compile 配置中检查所有内容):

        apply plugin: 'java'
        
        dependencies {
            compile files('lib/abc.jar')
            compile files('lib/def.jar')
        }
        
        task checkDependencies() {
            doLast {
                configurations.compile.each { file ->
                    assert file.exists() 
                }
            }
        }
        
        compileJava.dependsOn checkDependencies
        

        【讨论】:

          【解决方案5】:

          要使构建失败,您可以:

          ant.fail('message why it failed')
          

          然后您可以制作一个条件,然后通过漂亮的消息使构建失败;)

          我建议创建一个任务,首先将文件带到项目中,条件是检查文件是否可用等,如果不可用,则抛出 Gradle 异常并使构建失败并显示一条消息,然后首先执行任务在执行阶段。

          我现在没有机会测试它,但它可能是这样的,如果有任何语法错误,请纠正我 - 但你应该明白了。

          def yourDep = $/\path\to\your\depdendency/$
          
          task bringDeps << {
          
            if (yourDep.exists()){
              copy {
                from yourDep
                into $projectDir/depsOrSmthg
              }
            } else{
            ant.fail('message why it failed')
            }
          
          }
          

          【讨论】:

          • 这很有用,但我希望/询问是否有某种内置的 Gradle 函数可以验证依赖项的存在,而不必编写自定义代码来检查每个。
          • 抱歉,大卫,我不确定,你依赖那里的文件,我不是说没有,但我怀疑。
          • 另一方面,如果您像您所说的那样有大量依赖项,我建议您使用类似 Nexus 的东西,然后您可以指定另一个存储库并使用正常的依赖项语法,它会检查是否存在以及您可能寻找。
          • 这是一个我正在迁移的旧版本......目前有很多库位于各种 /lib 文件夹中。我可以将 Artifactory 设置为构建的缓存代理,并暂时将本地文件放在那里,但我希望 Gradle 会更有帮助...
          • @David 这有什么帮助吗?如果是,请记住stackoverflow.com/help/someone-answers
          猜你喜欢
          • 2016-07-11
          • 2018-03-10
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          • 1970-01-01
          • 2018-11-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多