Java 格雷德尔:我可以编译依赖于自身输出的代码吗?

Java 格雷德尔:我可以编译依赖于自身输出的代码吗?,java,compiler-construction,gradle,Java,Compiler Construction,Gradle,这是一个奇怪的问题,但它不是理论上的 我想做一个Gradle项目,它使用buildSrc,里面有一个java项目。该java项目定义了构建过程中使用的一些类 令人讨厌的技巧是,Gradle项目产生了一系列输出,包括修改的类,这些类属于buildSrc本身的Java项目 有没有什么方法可以表达这一点 我现在想到的唯一解决方案是:连续运行整个构建脚本两次。有什么办法可以避免吗?例如,通过为buildSrc生成修改后的代码,重新编译buildSrc,然后生成主Gradle项目的附加输出?我相信的第59

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

  • 我想做一个Gradle项目,它使用
    buildSrc
    ,里面有一个java项目。该java项目定义了构建过程中使用的一些类

  • 令人讨厌的技巧是,Gradle项目产生了一系列输出,包括修改的类,这些类属于
    buildSrc
    本身的Java项目

  • 有没有什么方法可以表达这一点


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

    我相信的第59.4节可以帮助您

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

    这不涉及codegen,但可能足以提供帮助

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

    apply plugin: 'java'
    
    build << { 
        println "TRACER: hello from buildSrc java build"
    }
    
    task compile2() << {
        println "TRACER: hello from buildSrc compile2"
    }
    
    task build1() << {
        println "TRACER: top-level build1" 
    }
    
    task build2(type: GradleBuild) {
        buildFile = 'buildSrc/build.gradle'
        tasks = ['compile2']
    }
    
    build2.dependsOn build1
    
    这表明:

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

    classpath和codegen很糟糕,但可能很直接

    好的,以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
    

    task generateNewCode()您不能摆脱循环依赖关系吗?将Groovy项目分为代码生成模块和使用代码生成器输出的部分。(和/或可能是一些共享代码。)然后运行代码生成器,编译生成的Java,编译您的主要内容。这也是我的第一直觉。不幸的是,我正在处理一个遗留项目,其中代码生成实际上使用它输出的类。(这个过程不久前是手工引导的。)好的,但是循环依赖性意味着你不能一步完成。(从技术上讲,即使两个都不正确,正确的方法是重新运行代码生成器,直到没有任何变化。)我同意这是多个步骤(任务)。我只是想看看我是否能用一次调用Gradle就能做到。然后呢。。。将codegen拆分为自己的模块,并使用?它仍然有点脆弱,但至少在构建主模块时是自动化的。这本身就非常有用,我真的很欣赏这个具体的例子。但是如果我理解正确,在主构建脚本调用
    buildSrc
    compile2
    之后,主构建脚本将不会有新编译的
    buildSrc
    类可供执行。(也就是说,无法从新的
    buildSrc
    交换新类)。是这样吗?
    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