Заменить токен в файле перед его созданием, но сохранить токен в источниках
Я хочу заменить токен @[email protected]
в исходном java файле версией перед сборкой (Gradle - моя предпочтительная система сборки).
В моем текущем скрипте ant.replace(file: 'src/main/java/randers/notenoughvocab/main/Reference.java', token: '@[email protected]', value: version)
он заменяет вхождения @[email protected]
в фактический исходный файл, поэтому после сборки все вхождения шаблона были заменены версией, и если я изменю версию, файл сборки gradle больше не найдет там никаких шаблонов, и версия не обновится.
Я также видел задачу здесь, но я не понимаю, какие значения должны применяться для моего конкретного проекта.
Макет проекта для моего проекта, если это необходимо:
![Screenshot of file layout taken from IntelliJ IDEA 14.1.2, Dark theme]()
Мой файл сборки gradle: просмотр на github
Ответы
Ответ 1
Вам нужно заменить токены @[email protected]
, прежде чем публиковать свое программное обеспечение. Здесь я определил задачу 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')
}
Я не рекомендую возиться со стандартными задачами, определенными плагином Java, потому что это добавит лишние накладные расходы для каждой сборки.
Ответ 2
ПРЕДУПРЕЖДЕНИЕ: Как указано в комментариях исходным кодом фильтрации @Raffaele, могут возникнуть серьезные проблемы. Этот ответ предполагает, что вы хорошо знаете, что вы делаете, и осознаете потенциальные проблемы, которые могут возникнуть.
Проблема заключается в том, что исходные файлы java не копируются - они только скомпилированы - на месте. Поэтому вам нужно:
- Перед компиляцией - скопируйте файл, содержащий
@[email protected]
- Отфильтровать файл.
- Compile
- Восстановить исходный файл.
Не уверен о путях, но следующий фрагмент кода должен быть полезен:
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: '@[email protected]', value: version)
}
compileJava.doLast {
copy {
from(tempDir + '/' + versionFileName)
into(project.file(versionFile).parent)
}
}
Ответ 3
Я столкнулся с той же проблемой. И я не смог найти рабочее решение. Ни один из примеров, которые я нашел, не работал. Я считаю, что это может быть фактом, что я новичок в Gradle, и эти примеры опускают некоторые очевидные фрагменты кода. Поэтому я просмотрел Gradle и нашел свое собственное решение, которое я хотел бы поделиться:
import org.apache.tools.ant.filters.ReplaceTokens
// Change compiler source directory
sourceSets {
main {
java {
srcDirs = ['build/src/main/java']
}
}
}
// Prepare sources for compilation
task prepareSources(type: Copy) {
from('src/main/java')
into('build/src/main/java')
filter(ReplaceTokens, tokens: [pluginVersion: version])
}
// Prepare sources, before compile
compileJava {
dependsOn prepareSources
}
Ответ 4
Я нашел некоторые ответы несколько неудовлетворительными, поэтому вот мое решение:
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
}
Это решает различные проблемы следующим образом:
- В отличие от ответа @Opal, основной источник остается неиспорченным; вместо этого он ставится с изменениями в
$buildDir/src
с processSource
задачи processSource
, которая отражает стандартные processResources
. - В отличие от ответа @Gregory Stachowiak,
sourceSets.main.java.srcDirs
остается значением по умолчанию, и в определении местоположения, которое (пока) не существует, нет ловкости рук - В отличие от ответа @Raffaele, не существует отдельной задачи для выпуска против других сборок. Я не согласен с тем, что разделение их желательно; Я думаю, что дополнительная сложность не стоит того, если вы не измерили какой-либо удар по производительности и не нашли его неприемлемым. Прежде чем перейти к решению @Raffaele, я бы даже, например, предпочел ограничить область действия
filter
шаблонами include/exclude. - Зависимости задачи неявно определяются через выходные данные.
- Все местоположения взяты из значений по умолчанию, и ничего не напечатано строго. Единственное магическое значение здесь - это
src
, каталог в $buildDir
куда $buildDir
обработанные исходные файлы. - (Изменение: добавлено 2019/1/12) Другие ответы неправильно обрабатывают ситуации, когда изменилась только версия. Изменение версии само по себе должно сделать недействительным вывод задания. Это достигается с помощью
inputs.property
. - (Изменить 2019/5/20) Использует
Sync
а не Copy
чтобы файлы, удаленные из источника, также удалялись из отфильтрованного источника (спасибо, @Earthcomputer).
Ответ 5
В дополнение к другим ответам я нашел эту идиому более простой, если есть только одно значение, которое вы хотите изменить:
task generateSources(type: Copy) {
from 'src/main/java'
into 'build/src/main/java'
filter { line -> line.replaceAll('xxx', 'aaa') }
}