【问题标题】:Gradle task replace string in .java fileGradle 任务替换 .java 文件中的字符串
【发布时间】:2015-11-01 16:46:15
【问题描述】:

我想在编译代码之前替换我的 Config.java 文件中的几行。我所能找到的只是在复制文件时通过过滤器解析文件。一旦我必须复制它,我就必须将它保存在某个地方 - 这就是我寻求解决方案的原因:在替换行时复制到临时位置 > 删除原始文件 > 将重复的文件复制回原始位置 > 删除临时文件。有没有更好的解决方案?

【问题讨论】:

    标签: java gradle task


    【解决方案1】:

    也许你应该试试像蚂蚁的replaceregexp:

    task myCopy << {
        ant.replaceregexp(match:'aaa', replace:'bbb', flags:'g', byline:true) {
            fileset(dir: 'src/main/java/android/app/cfg', includes: 'TestingConfigCopy.java')
        }
    }
    

    此任务会将所有出现的aaa 替换为bbb。无论如何,这只是一个示例,您可以根据自己的目的对其进行修改或尝试与ant类似的解决方案。

    【讨论】:

    【解决方案2】:

    为了补充lance-java 的回答,如果您只想更改一个值,我发现这个成语更简单:

    task generateSources(type: Copy) {
        from 'src/replaceme/java'
        into "$buildDir/generated-src"
        filter { line -> line.replaceAll('xxx', 'aaa') }
    }
    

    警告:请记住,Copy 任务仅在源文件更改时才会运行。如果您希望根据其他条件进行替换,则需要使用 Gradle 的增量构建功能来指定。

    【讨论】:

    • 小心,我们被烧毁了。我们使用 -Pversion={version} 运行,但目标一直说源文件不脏,因此我们的新版本从未被放入文件中。它适用于很多事情,但不适用于版本控制。我们在那里找到了艰难的道路。
    • @DeanHiller 感谢您的评论。我不是 100% 确定我明白你的意思。你是说你有没有改变的源文件,因此 Gradle 没有按照你想要的方式“改变”它们,即使它应该改变它们内部的“版本”?
    • 我们尝试使用该方法进行版本,但如果源文件没有更改,它实际上根本不会运行并且会进行 0 替换,所以我们最终会得到 'version-token从开发版本切换到发布版本时,我们的输出文件中会出现 -to-be-replaced'。目前还不确定最好的方法……也许只是文件生成。
    • 我明白了。事实上,复制任务仅在源文件更改时才会运行。这是它的默认行为。在您的情况下,您应该考虑导致这种替换发生的触发器是什么。你希望它在每次运行 Gradle 时都运行吗?是不是还有一个条件?一旦你弄清楚了,你应该使用 Gradle 的增量构建功能来指定它:例如指定任务的输入、输出或 updateToDateWhen。
    • 我会在我的回答中添加这个警告。随意对其他答案发表相同的评论,他们都关心这个极端案例
    【解决方案3】:
    1. 我绝对不会覆盖原文件
    2. 我喜欢基于目录而不是基于文件名,所以如果是我,我会将 Config.java 放在它自己的文件夹中(例如 src/replaceme/java)
    3. 我会在$buildDir 下创建一个generated-src 目录,以便通过clean 任务将其删除。

    您可以使用复制任务和 ReplaceTokens 过滤器。例如:

    apply plugin: 'java'
    task generateSources(type: Copy) {
        from 'src/replaceme/java'
        into "$buildDir/generated-src"
        filter(ReplaceTokens, tokens: [
            'xxx': 'aaa', 
            'yyy': 'bbb'
        ])
    }
    // the following lines are important to wire the task in with the compileJava task
    compileJava.source "$buildDir/generated-src"
    compileJava.dependsOn generateSources
    

    【讨论】:

    • 我已经使用了 replace 方法并且它的工作完美无缺,但是一旦我手动编辑 Config.java 文件,我可能会达到一些不需要的状态,所以你的解决方案似乎要好得多。 compileJava.source = [files] 到底是做什么的?它怎么知道我是否要替换包'com.example.cfg'中的Config.java而不是包'com.example.remote.cfg'中的同名文件?
    • 正如我所说,我更喜欢使用目录而不是特定的文件名模式。因此,在我的示例中,src/replaceme/java 中的所有内容都将被替换,而不管包如何。 compileJava.source generateSources.outputs.files 调用 JavaCompile.source(...) 最终添加生成的源文件,以便它们与普通源文件一起编译(在 src/main/java 中)。我的建议中没有“=”符号
    【解决方案4】:

    如果您确实希望使用临时文件策略覆盖原始文件,以下将创建过滤后的文件,将它们复制到原始文件上,然后删除临时文件。

    task copyAtoB(dependsOn: [existingTask]) {
        doLast {
            copy {
                from("folder/a") {
                    include "*.java"
                }
                // Have to use a new path for modified files
                into("folder/b")
                filter {
                    String line ->
                        line.replaceAll("changeme", "to this")
                }
            }
        }
    }
    
    task overwriteFilesInAfromB(dependsOn: [copyAtoB]) {
        doLast {
            copy {
                from("folder/b") {
                    include "*.java"
                }
                into("folder/a")
            }
        }
    }
    
    // Finally, delete the files in folder B
    task deleteB(type: Delete, dependsOn: overwriteFilesInAfromB) {
        delete("folder/b")
    }
    
    nextTask.dependsOn(deleteB)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 2018-10-29
      • 2013-09-08
      • 1970-01-01
      • 2014-06-21
      • 2015-09-04
      • 1970-01-01
      相关资源
      最近更新 更多