Thank you for the reply.
My initial explanation was too abstract and lacked a concrete context. To clarify, my goal is to find the modern, idiomatic way to “share” Providers and Closures between different Gradle scripts acting as convention plugins in my build-logic.
Right now, I am using the legacy project.ext to expose a map of providers and closures from Script A to be consumed by other Scripts.
Here is a simplified example of my current approach:
Script A (The Provider/Closure Creator):
Object propsLocal = gradle.ext.propsLocal // from "local.properties"
Provider<Boolean> eMacProv = providers.systemProperty('os.name').map {
it.toLowerCase().contains('mac')
}
Provider<String> macDonoProv = project.providers.provider { propsLocal.getProperty('mac.dono') }
Provider<String> macSedeProv = project.providers.provider { propsLocal.getProperty('mac.sede') }
Provider<String> macDirProv = project.providers.provider { propsLocal.getProperty('mac.dir') }
Provider<String> nomeAppProv = providers.gradleProperty('projNome')
Provider<String> buildXDirProv = providers.gradleProperty('buildDirXcode')
Provider<String> vmDirProv = macDirProv.zip(nomeAppProv) { String dir, String app ->
new File(dir, app).path.replace(File.separator, '/')
}
Provider<String> simuladorUsualProv = project.providers.provider {
propsLocal.getProperty('simulador.ios')
}
Closure<List<String>> comandoRemoto = { List<String> cmds ->
final Map<String, String> vmCmds = [
killall: '/usr/bin/killall',
rm: '/bin/rm',
xcrun: '/usr/bin/xcrun',
]
List<String> cmdRemotos = cmds.collect { String arg -> vmCmds.getOrDefault(arg, arg) }
return [
'ssh', "${macDonoProv.get()}@${macSedeProv.get()}",
"\"cd \'${vmAppDirProv.get()}\' && ${cmdRemotos.join(' ')}\""
]
}
project.ext.x = [
auxs: [
comandoRemoto: comandoRemoto
],
provs: [
eMacProv: eMacProv,
nomeAppProv: nomeAppProv,
vmDirProv: vmDirProv,
simuladorUsualProv: simuladorUsualProv,
buildXDirProv: buildXDirProv
],
cons: [
workingDir: '/Users/user/project/path/'
]
]
Script B (The Consumer):
plugins.apply(libs.plugins.buildLogicA.get().getPluginId())
Object x = project.ext.x
Provider<String> vmXcodeDirProv = x.provs.vmDirProv.zip(x.provs.buildXDirProv) {
String dir, String bDir -> new File(dir.toString(), bDir).path.replace(File.separator, '/')
}
Provider<Directory> xcDirProv = project.providers.provider {
project.rootProject.layout.projectDirectory.dir(x.provs.buildXDirProv.get())
}
tasks.register('cleanMac', Exec) {
description = 'Limpa os arquivos de build do Xcode para iOS.'
group = 'MacOs Controller'
workingDir(x.cons.workingDir)
outputs.upToDateWhen { false }
doFirst {
String simulador = x.provs.simuladorUsualProv.get()
String dirXc = x.provs.eMacProv.get() ?
xcDirProv.get().asFile.absolutePath : vmXcodeDirProv.get()
commandLine x.auxs.comandoRemoto([
'killall', 'Xcode', '|| true &&',
'xcrun', '-k', '|| true &&',
'rm', '-rf', "\'${dirXc}\'", '|| true'
])
}
}
Given this structure, what is the recommended Gradle API or architectural pattern to replace this project.ext map? Should I register a custom Extension interface, use static utility classes as you mentioned, or perhaps create custom Task types and pass these providers as inputs? Is there any other alternative that I’m not aware of?