在构建之前替换文件中的标记,但将标记保留在源中

RAn*_*s00 21 java gradle

我想@VERSION@在构建之前用版本替换java源文件中的标记(Gradle是我选择的构建系统).

在我当前的脚本中,ant.replace(file: 'src/main/java/randers/notenoughvocab/main/Reference.java', token: '@VERSION@', value: version)它取代了@VERSION@实际源文件中出现的内容,因此在构建之后,所有出现的模式都被版本替换,如果我更改了gradle构建文件的版本,它将不再在那里找到任何模式并且版本不会更新.

我在这里也看到了一个任务,但是我没有得到需要为我的特定项目应用的值.

如果需要,我的项目的项目布局:
从IntelliJ IDEA 14.1.2,Dark主题获取的文件布局的屏幕截图

我的gradle构建文件:在github上查看

Raf*_*ele 18

@VERSION@在向公众发布软件之前,您只需要替换令牌.在这里,我定义了一个compileForRelease完成它的任务:

import org.apache.tools.ant.filters.ReplaceTokens

task sourcesForRelease(type: Copy) {
    from 'src/main/java'
    into 'build/adjustedSrc'
    filter(ReplaceTokens, tokens: [VERSION: '2.3.1'])
}

task compileForRelease(type: JavaCompile, dependsOn: sourcesForRelease) {
    source = sourcesForRelease.destinationDir
    classpath = sourceSets.main.compileClasspath
    destinationDir = file('build/adjustedClasses')
}
Run Code Online (Sandbox Code Playgroud)

我不建议搞乱Java插件定义的标准任务,因为这会给每个构建添加不必要的开销.


Opa*_*pal 7

警告:如@Raffaele的评论中所示,过滤源代码可能会导致严重问题.这个答案假定您很清楚自己在做什么,并且意识到可能发生的潜在问题.

问题在于java源文件没有被复制 - 它们只是编译 - 就位.所以你需要:

  1. 在编译之前 - 复制包含的文件 @VERSION@
  2. 过滤文件.
  3. 恢复原始文件.

不确定路径,但下面的代码应该是有用的:

apply plugin: 'java'

version = '0.0.1'
group = 'randers.notenoughvocab'
archivesBaseName = 'NotEnoughVocab'

def versionFile = 'src/main/java/randers/notenoughvocab/main/Reference.java'
def tempDir = 'build/tmp/sourcesCache'
def versionFileName = 'Reference.java'

compileJava.doFirst {
    copy {
        from(versionFile)
        into(tempDir)
    }
    ant.replace(file: versionFile, token: '@VERSION@', value: version)
}

compileJava.doLast {
    copy {
        from(tempDir + '/' + versionFileName)
        into(project.file(versionFile).parent)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • ** - 1:这在概念上是错误的并且非常危险:构建工具永远不应该触摸源文件**.即使源代码在某些源代码控制系统中,当构建失败时(或者构建文件中存在错误)并且工作目录不干净时,您也有可能永远**工作时间(天?).对于将来自Google的其他用户而言,这篇文章也很危险,并且会在不了解风险的情况下在构建文件中复制和修改此代码 (4认同)

Aar*_*ron 7

我发现现有的答案有些不令人满意,所以这是我的解决方案:

import org.apache.tools.ant.filters.ReplaceTokens

task processSource(type: Sync) {
    from sourceSets.main.java
    inputs.property 'version', version
    filter(ReplaceTokens, tokens: [VERSION: version])
    into "$buildDir/src"
}

compileJava {
    source = processSource.outputs
}
Run Code Online (Sandbox Code Playgroud)

这解决了以下各种问题:

  1. 与@Opal 的回答不同,主要来源没有受到干扰;相反,它会$buildDir/src根据processSource任务进行修改,这反映了标准processResources.
  2. 与@Gregory Stachowiak 的答案不同,它sourceSets.main.java.srcDirs仍然是默认值,并且在指定(尚)不存在的位置时没有任何技巧
  3. 与@Raffaele 的回答不同,发布版本与其他版本没有单独的任务集。我不同意将它们分开是可取的;我认为增加的复杂性是不值得的,除非您测量了任何性能损失并发现它是不可接受的。在使用@Raffaele 的解决方案之前,我什至更愿意限制filter包含/排除模式的范围。
  4. 任务依赖是通过输出隐式定义的。
  5. 所有位置均取自默认值,并且没有任何字符串类型。这里唯一的神奇值是src$buildDir处理过的源文件所在的目录。
  6. (编辑:2019 年 1 月 12 日添加)其他答案无法正确处理仅版本更改的情况。更改版本本身应该会使任务输出无效。这是通过inputs.property.
  7. (编辑 2019/5/20)使用Sync而不是Copy从源中删除的文件也从过滤的源中删除(谢谢,@Earthcomputer)。