【问题标题】:Gradle: Can I compile code that depends on its own output?Gradle:我可以编译依赖于它自己的输出的代码吗?
【发布时间】:2013-09-24 18:47:14
【问题描述】:

这是一个奇怪的问题,但不是理论上的……

  1. 我想制作一个使用 buildSrc 和内部 java 项目的 Gradle 项目。该 java 项目定义了一些在构建过程中使用的类。

  2. 令人讨厌的技巧是,Gradle 项目产生了一堆输出,包括属于 buildSrc 本身的 Java 项目的修改类。

有什么方法可以用 Gradle 来表达吗?

我现在想到的唯一解决方案是:连续运行整个构建脚本两次。有没有办法避免这种情况?例如,通过为buildSrc 生成修改后的代码,重新编译buildSrc,然后生成Gradle 主项目的附加输出?

【问题讨论】:

  • 就不能摆脱循环依赖吗?将 Groovy 项目分成代码生成模块,以及消耗代码生成器输出的部分。 (和/或可能有一些共享代码。)然后运行代码生成器,编译生成的 Java,编译你的主要内容。
  • 我的第一直觉也是。不幸的是,我正在处理一个遗留项目,其中代码生成实际上使用它输出的类。 (该过程不久前是手动引导的。)
  • 好的,但是循环依赖几乎意味着您不能一步完成。 (从技术上讲,甚至两个都不正确,正确的方法是重新运行代码生成器,直到没有任何变化。)
  • 我同意这是多个步骤(任务)。我只是想看看我是否可以通过一次 Gradle 调用来做到这一点。
  • 然后呃...将codegen拆分成自己的模块,并使用custom task?调用codegen它仍然有点脆弱,但至少在构建主模块时它是自动化的。

标签: java compiler-construction gradle


【解决方案1】:

好的,以 Michael Easter 的精彩示例为基础,我可以让主级构建调用 GradleBuild 在它自己的一项任务上:

task generateNewCode() << {
  println("tracer top build")

  // BuildTool is a Java class defined in `buildSrc`
  // ... and it has a cyclic dependency on its own 
  // output (eek -- but that's what I'm dealing with!)
  BuildTool.generateNewCode();
}

task generateDocs(type: GradleBuild) {
  buildFile='build.gradle'
  tasks = ['generateDocs_Real']
}

task generateDocs_Real << {
  BuildTool.outputDocumentation();
}

generateDocs.dependsOn generateNewCode

然后我可以调用gradle generateDocs 来做:

  1. Codegen(在buildSrc 中创建新的 java 类
  2. 重新编译buildSrc
  3. 使用来自重新编译的buidSrc 的帮助程序生成文档

【讨论】:

    【解决方案2】:

    我相信the Gradle doc的第59.4节可以帮助到你。

    使用 Gradle 1.8,我尝试“从一个构建运行另一个 Gradle 构建”,其中另一个 Gradle 构建是 buildSrc。

    这不涉及代码生成,但可能足以提供帮助。

    为了复制,我在 buildSrc 中有一个简单的 Java 项目,其 build.gradle 如下所示:

    apply plugin: 'java'
    
    build << { 
        println "TRACER: hello from buildSrc java build"
    }
    
    task compile2() << {
        println "TRACER: hello from buildSrc compile2"
    }
    

    “构建”任务通过 buildSrc 机制自动调用。目标是从根目录调用“compile2”。在根目录下,build.gradle 看起来像这样:

    task build1() << {
        println "TRACER: top-level build1" 
    }
    
    task build2(type: GradleBuild) {
        buildFile = 'buildSrc/build.gradle'
        tasks = ['compile2']
    }
    
    build2.dependsOn build1
    

    在根级别,输出如下:

    $ gradle build2
    
    :buildSrc:compileJava etc etc
    TRACER: hello from buildSrc java build
    TRACER: top-level build1
    TRACER: hello from buildSrc compile2
    

    这表明:

    • buildSrc 中的 Java 项目已编译
    • 调用了根“build1”(在此处编译您的主项目)
    • buildSrc 'compile2' 被调用

    类路径和代码生成很糟糕,但可能很简单。

    【讨论】:

    • 这本身就非常有帮助,我非常感谢这个具体的例子。但如果我理解正确,在主构建脚本调用buildSrccompile2 之后,主构建脚本将没有新编译的buildSrc 类可供执行。 (也就是说,没有办法从新的buildSrc 中交换新的类)。对吗?
    猜你喜欢
    • 2017-05-31
    • 2021-10-03
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-26
    相关资源
    最近更新 更多