Some time ago I needed a way to build a bunch of select gradle modules, independently, and I discovered the bash syntax <(cmd)
. It creates an unnamed pipe with the content that is output from the command.
Bash unnamed pipes
I used this to skip a list of newline separated modules from being built, by filtering a list of folders, to keep only those that did not exist in the file I gave to grep -v -f <file>
. This way it was not nescessary to clean up intermediary files afterwards.
man grep
-f file, --file=file
Read one or more newline separated patterns from file. Empty pattern lines match every input line. Newlines are not considered part of a pattern.
If file is empty, nothing is matched.
...
-v, --invert-match
Selected lines are those not matching any of the specified patterns.
By using cat <<EOF
to build newline separated content in the variable skip_modules
, it can be passed to grep
pretending to be a file, using <(echo "$skip_modules")
. An unnamed pipe! It looked like this
skip_modules=$(cat <<EOF
folders
to
skip
EOF
)
# build all modules idependently, except excluded ones found in skip_modules
for build in $(find . -name settings.gradle.kts | xargs dirname | grep -v -f <(echo "$skip_modules")); do
pushd $build
./gradlew clean build "$@"
popd
done
You could have used a gradle composite build!
I could have. I did, once. That looked like this
fun includeBuild(moduleSettingsGradleKts: String) {
val module =
moduleSettingsGradleKts
.replace("${rootDir.path}/", "")
.replace("/settings.gradle.kts", "")
println(":: includeBuild($module)")
includeBuild(module)
}
val sharedModulesPath = "modules"
includeBuild("$rootDir/$sharedModulesPath/settings.gradle.kts")
// automatically create a composite build that includeBuild()-s all top level
// deployables, which have standalone gradle builds
var topLevelModules =
rootDir.listFiles()!!
.filter { it.isDirectory }
.flatMap { directory ->
directory.walkTopDown()
.maxDepth(2)
.filter { it.isFile }
.filter { it.name == "settings.gradle.kts" }
.filter { it.parentFile.name != rootProject.name }
.filter { !it.path.contains(sharedModulesPath) }
.map { file -> file.path }
}
topLevelModules.forEach(::includeBuild)