From cc4c151458d0d6ad02ccff353376f70c3a14114f Mon Sep 17 00:00:00 2001 From: rougsig Date: Tue, 24 Jan 2023 03:22:49 +0300 Subject: [PATCH 01/16] Extract GenerateProtoTask configuration fields to GenerateProtoTaskSpec --- .../protobuf/gradle/GenerateProtoTask.groovy | 224 ++++-------------- .../protobuf/gradle/ProtobufPlugin.groovy | 2 +- .../internal/DefaultDescriptorSetSpec.groovy | 51 ++++ .../DefaultGenerateProtoTaskSpec.groovy | 77 ++++++ .../gradle/internal/DefaultPluginSpec.groovy | 44 ++++ .../internal/PluginSpecObjectFactory.groovy | 20 ++ .../gradle/tasks/DescriptorSetSpec.groovy | 48 ++++ .../gradle/tasks/GenerateProtoTaskSpec.groovy | 67 ++++++ .../protobuf/gradle/tasks/PluginSpec.groovy | 39 +++ 9 files changed, 389 insertions(+), 183 deletions(-) create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/DefaultDescriptorSetSpec.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/DefaultPluginSpec.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecObjectFactory.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/tasks/DescriptorSetSpec.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/tasks/PluginSpec.groovy diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index c38506c9..82dea60b 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -31,15 +31,20 @@ package com.google.protobuf.gradle import static java.nio.charset.StandardCharsets.US_ASCII +import org.gradle.api.Action +import org.gradle.util.ConfigureUtil +import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.PluginSpec +import org.gradle.api.file.DeleteSpec +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Nested import groovy.transform.CompileStatic import groovy.transform.PackageScope import groovy.transform.TypeChecked import groovy.transform.TypeCheckingMode -import org.gradle.api.Action import org.gradle.api.DefaultTask import org.gradle.api.GradleException -import org.gradle.api.Named -import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.gradle.api.file.ProjectLayout @@ -53,17 +58,12 @@ import org.gradle.api.tasks.IgnoreEmptyDirectories import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Nested -import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.SkipWhenEmpty import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskAction - -import javax.annotation.Nullable import javax.inject.Inject /** @@ -90,8 +90,6 @@ public abstract class GenerateProtoTask extends DefaultTask { private final ConfigurableFileCollection includeDirs = objectFactory.fileCollection() // source files are proto files that will be compiled by protoc private final ConfigurableFileCollection sourceDirs = objectFactory.fileCollection() - private final NamedDomainObjectContainer builtins = objectFactory.domainObjectContainer(PluginOptions) - private final NamedDomainObjectContainer plugins = objectFactory.domainObjectContainer(PluginOptions) private final ProjectLayout projectLayout = project.layout private final ToolsLocator toolsLocator = project.extensions.findByType(ProtobufExtension).tools @@ -116,49 +114,10 @@ public abstract class GenerateProtoTask extends DefaultTask { return Utils.isTest(sourceSet.name) } - /** - * If true, will set the protoc flag - * --descriptor_set_out="${outputBaseDir}/descriptor_set.desc" - * - * Default: false - */ - @Internal("Handled as input via getDescriptorSetOptionsForCaching()") - boolean generateDescriptorSet - - /** - * Configuration object for descriptor generation details. - */ - public class DescriptorSetOptions { - /** - * If set, specifies an alternative location than the default for storing the descriptor - * set. - * - * Default: null - */ - @Nullable - @Optional - @OutputFile - String path - - /** - * If true, source information (comments, locations) will be included in the descriptor set. - * - * Default: false - */ - @Input - boolean includeSourceInfo - - /** - * If true, imports are included in the descriptor set, such that it is self-containing. - * - * Default: false - */ - @Input - boolean includeImports - } - - @Internal("Handled as input via getDescriptorSetOptionsForCaching()") - final DescriptorSetOptions descriptorSetOptions = new DescriptorSetOptions() + @SuppressWarnings("AbstractClassWithPublicConstructor") // required to configure properties convention values + GenerateProtoTask() { + this.spec.convention(new DefaultGenerateProtoTaskSpec(this.project.objects)) + } // protoc allows you to prefix comma-delimited options to the path in // the --*_out flags, e.g., @@ -355,7 +314,7 @@ public abstract class GenerateProtoTask extends DefaultTask { } private List getAllExecutableLocators() { - [toolsLocator.protoc] + plugins.collect { PluginOptions it -> toolsLocator.plugins.getByName(it.name) } + [toolsLocator.protoc] + requireSpec().plugins.collect { PluginSpec it -> toolsLocator.plugins.getByName(it.name) } } @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") @@ -402,11 +361,13 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Tracked as an input via getDescriptorSetOptionsForCaching()") String getDescriptorPath() { - if (!generateDescriptorSet) { + GenerateProtoTaskSpec spec = requireSpec() + if (!spec.generateDescriptorSet) { throw new IllegalStateException( "requested descriptor path but descriptor generation is off") } - return descriptorSetOptions.path != null ? descriptorSetOptions.path : "${outputBaseDir.get()}/descriptor_set.desc" + return spec.descriptorSetOptions.path != null ? spec.descriptorSetOptions.path + : "${outputBaseDir.get()}/descriptor_set.desc" } @Inject @@ -415,51 +376,21 @@ public abstract class GenerateProtoTask extends DefaultTask { @Inject abstract ObjectFactory getObjectFactory() + @Nested + abstract Property getSpec() + //=========================================================================== // Configuration methods //=========================================================================== - /** - * Configures the protoc builtins in a closure, which will be manipulating a - * NamedDomainObjectContainer. - */ - public void builtins(Action> configureAction) { - checkCanConfig() - configureAction.execute(this.builtins) + @Deprecated // temporary method for refactoring + void spec(Action configureAction) { + configureAction.execute(this.spec.get()) } - /** - * Returns the container of protoc builtins. - */ - @Internal("Tracked as an input via getBuiltinsForCaching()") - public NamedDomainObjectContainer getBuiltins() { - checkCanConfig() - return builtins - } - - /** - * Configures the protoc plugins in a closure, which will be maniuplating a - * NamedDomainObjectContainer. - */ - public void plugins(Action> configureAction) { - checkCanConfig() - configureAction.execute(this.plugins) - } - - /** - * Returns the container of protoc plugins. - */ - @Internal("Tracked as an input via getPluginsForCaching()") - public NamedDomainObjectContainer getPlugins() { - checkCanConfig() - return plugins - } - - /** - * Returns true if the task has a plugin with the given name, false otherwise. - */ - public boolean hasPlugin(String name) { - return plugins.findByName(name) != null + @Deprecated // temporary method for refactoring + void spec(Closure closure) { + ConfigureUtil.configure(closure, this.spec.get()) } /** @@ -491,64 +422,11 @@ public abstract class GenerateProtoTask extends DefaultTask { return isTestProvider } - /** - * The container of command-line options for a protoc plugin or a built-in output. - */ - public static class PluginOptions implements Named { - private final List options = [] - private final String name - private String outputSubDir - - public PluginOptions(String name) { - this.name = name - } - - /** - * Adds a plugin option. - */ - public PluginOptions option(String option) { - options.add(option) - return this - } - - @Input - public List getOptions() { - return options - } - - /** - * Returns the name of the plugin or builtin. - */ - @Input - @Override - public String getName() { - return name - } - - /** - * Set the output directory for this plugin, relative to {@link GenerateProtoTask#outputBaseDir}. - */ - void setOutputSubDir(String outputSubDir) { - this.outputSubDir = outputSubDir - } - - /** - * Returns the relative outputDir for this plugin. If outputDir is not specified, name is used. - */ - @Input - public String getOutputSubDir() { - if (outputSubDir != null) { - return outputSubDir - } - return name - } - } - //=========================================================================== // protoc invocation logic //=========================================================================== - String getOutputDir(PluginOptions plugin) { + String getOutputDir(PluginSpec plugin) { return "${outputBaseDir.get()}/${plugin.outputSubDir}" } @@ -571,14 +449,16 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal @PackageScope Collection getOutputSourceDirectories() { + GenerateProtoTaskSpec spec = requireSpec() + Collection srcDirs = [] - builtins.each { builtin -> + spec.builtins.each { builtin -> File dir = new File(getOutputDir(builtin)) if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { srcDirs.add(dir) } } - plugins.each { plugin -> + spec.plugins.each { plugin -> File dir = new File(getOutputDir(plugin)) if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { srcDirs.add(dir) @@ -590,15 +470,16 @@ public abstract class GenerateProtoTask extends DefaultTask { @TaskAction void compile() { Preconditions.checkState(state == State.FINALIZED, 'doneConfig() has not been called') + GenerateProtoTaskSpec spec = requireSpec() - copyActionFacade.delete { spec -> - spec.delete(outputBaseDir) + copyActionFacade.delete { DeleteSpec deleteSpec -> + deleteSpec.delete(outputBaseDir) } // Sort to ensure generated descriptors have a canonical representation // to avoid triggering unnecessary rebuilds downstream List protoFiles = sourceDirs.asFileTree.files.sort() - [builtins, plugins]*.forEach { PluginOptions plugin -> + [spec.builtins, spec.plugins]*.forEach { PluginSpec plugin -> String outputPath = getOutputDir(plugin) File outputDir = new File(outputPath) // protoc is capable of output generated files directly to a JAR file @@ -621,14 +502,14 @@ public abstract class GenerateProtoTask extends DefaultTask { baseCmd.addAll(dirs) // Handle code generation built-ins - builtins.each { builtin -> + spec.builtins.each { builtin -> String outPrefix = makeOptionsPrefix(builtin.options) baseCmd += "--${builtin.name}_out=${outPrefix}${getOutputDir(builtin)}".toString() } Map executableLocations = toolsLocator.plugins.asMap // Handle code generation plugins - plugins.each { plugin -> + spec.plugins.each { PluginSpec plugin -> String name = plugin.name ExecutableLocator locator = executableLocations.get(name) if (locator != null) { @@ -640,7 +521,7 @@ public abstract class GenerateProtoTask extends DefaultTask { baseCmd += "--${name}_out=${pluginOutPrefix}${getOutputDir(plugin)}".toString() } - if (generateDescriptorSet) { + if (spec.generateDescriptorSet) { String path = getDescriptorPath() // Ensure that the folder for the descriptor exists; // the user may have set it to point outside an existing tree @@ -649,10 +530,10 @@ public abstract class GenerateProtoTask extends DefaultTask { folder.mkdirs() } baseCmd += "--descriptor_set_out=${path}".toString() - if (descriptorSetOptions.includeImports) { + if (spec.descriptorSetOptions.includeImports) { baseCmd += "--include_imports" } - if (descriptorSetOptions.includeSourceInfo) { + if (spec.descriptorSetOptions.includeSourceInfo) { baseCmd += "--include_source_info" } } @@ -663,29 +544,8 @@ public abstract class GenerateProtoTask extends DefaultTask { } } - /** - * Used to expose inputs to Gradle, not to be called directly. - */ - @Optional - @Nested - protected DescriptorSetOptions getDescriptorSetOptionsForCaching() { - return generateDescriptorSet ? descriptorSetOptions : null - } - - /** - * Used to expose inputs to Gradle, not to be called directly. - */ - @Nested - protected Collection getBuiltinsForCaching() { - return builtins - } - - /** - * Used to expose inputs to Gradle, not to be called directly. - */ - @Nested - protected Collection getPluginsForCaching() { - return plugins + private GenerateProtoTaskSpec requireSpec() { + return spec.get() } private static enum State { diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy index c0c2bae5..1500d470 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy @@ -251,7 +251,7 @@ class ProtobufPlugin implements Plugin { Provider generateProtoTask = addGenerateProtoTask(protoSourceSet) { it.sourceSet = sourceSet it.doneInitializing() - it.builtins.maybeCreate("java") + it.spec.get().builtins.maybeCreate("java") } sourceSet.java.srcDirs(protoSourceSet.output) diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultDescriptorSetSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultDescriptorSetSpec.groovy new file mode 100644 index 00000000..2e3956ad --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultDescriptorSetSpec.groovy @@ -0,0 +1,51 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.DescriptorSetSpec +import groovy.transform.CompileStatic +import org.gradle.api.model.ObjectFactory + +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +class DefaultDescriptorSetSpec implements DescriptorSetSpec { + private final ObjectFactory objects + private String path + private boolean includeSourceInfo + private boolean includeImports + + DefaultDescriptorSetSpec(ObjectFactory objects) { + this.objects = objects + this.path = null + this.includeSourceInfo = false + this.includeImports = false + } + + @Override + String getPath() { + return this.path + } + + @Override + void setPath(String value) { + this.path = value + } + + @Override + boolean getIncludeSourceInfo() { + return this.includeSourceInfo + } + + @Override + void setIncludeSourceInfo(boolean value) { + this.includeSourceInfo = value + } + + @Override + boolean getIncludeImports() { + return this.includeImports + } + + @Override + void setIncludeImports(boolean value) { + this.includeImports = value + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy new file mode 100644 index 00000000..98f69216 --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy @@ -0,0 +1,77 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.DescriptorSetSpec +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.PluginSpec +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.model.ObjectFactory +import org.gradle.util.ConfigureUtil + +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +class DefaultGenerateProtoTaskSpec implements GenerateProtoTaskSpec { + private final NamedDomainObjectContainer plugins + private final NamedDomainObjectContainer builtins + private final DescriptorSetSpec descriptorSetSpec + private boolean generateDescriptorSet = false + + DefaultGenerateProtoTaskSpec(ObjectFactory objects) { + NamedDomainObjectFactory pluginSpecObjectFactory = new PluginSpecObjectFactory(objects) + this.plugins = objects.domainObjectContainer(PluginSpec, pluginSpecObjectFactory) + this.builtins = objects.domainObjectContainer(PluginSpec, pluginSpecObjectFactory) + this.descriptorSetSpec = new DefaultDescriptorSetSpec(objects) + } + + @Override + boolean getGenerateDescriptorSet() { + return generateDescriptorSet + } + + @Override + void setGenerateDescriptorSet(boolean enabled) { + this.generateDescriptorSet = enabled + } + + @Override + DescriptorSetSpec getDescriptorSetOptions() { + return this.descriptorSetSpec + } + + @Override + NamedDomainObjectContainer getPlugins() { + return this.plugins + } + + @Override + NamedDomainObjectContainer getBuiltins() { + return this.builtins + } + + @Override + boolean hasPlugin(String name) { + return plugins.findByName(name) != null + } + + @Override + void builtins(Action> configureAction) { + configureAction.execute(builtins) + } + + @Override + void builtins(Closure> closure) { + ConfigureUtil.configure(closure, builtins) + } + + @Override + void plugins(Action> configureAction) { + configureAction.execute(plugins) + } + + @Override + void plugins(Closure> closure) { + ConfigureUtil.configure(closure, plugins) + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultPluginSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultPluginSpec.groovy new file mode 100644 index 00000000..8462519b --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultPluginSpec.groovy @@ -0,0 +1,44 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.PluginSpec +import groovy.transform.CompileStatic +import org.gradle.api.model.ObjectFactory + +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +class DefaultPluginSpec implements PluginSpec { + private final ObjectFactory objects + private final List options = [] + private final String name + private String outputSubDir + + DefaultPluginSpec(ObjectFactory objects, String name) { + this.objects = objects + this.name = name + } + + DefaultPluginSpec option(String option) { + options.add(option) + return this + } + + List getOptions() { + return options + } + + @Override + String getName() { + return name + } + + void setOutputSubDir(String outputSubDir) { + this.outputSubDir = outputSubDir + } + + String getOutputSubDir() { + if (outputSubDir != null) { + return outputSubDir + } + return name + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecObjectFactory.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecObjectFactory.groovy new file mode 100644 index 00000000..db76537b --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecObjectFactory.groovy @@ -0,0 +1,20 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.PluginSpec +import groovy.transform.CompileStatic +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.model.ObjectFactory + +@CompileStatic +class PluginSpecObjectFactory implements NamedDomainObjectFactory { + private final ObjectFactory objects + + PluginSpecObjectFactory(ObjectFactory objects) { + this.objects = objects + } + + @Override + PluginSpec create(String name) { + return new DefaultPluginSpec(objects, name) + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/DescriptorSetSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/DescriptorSetSpec.groovy new file mode 100644 index 00000000..4edcc85d --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/DescriptorSetSpec.groovy @@ -0,0 +1,48 @@ +package com.google.protobuf.gradle.tasks + +import groovy.transform.CompileStatic +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputFile + +import javax.annotation.Nullable + +/** + * Configuration object for descriptor generation details. + */ +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +interface DescriptorSetSpec { + /** + * If set, specifies an alternative location than the default for storing the descriptor + * set. + * + * Default: null + */ + @Nullable + @Optional + @OutputFile + String getPath() + + void setPath(String value) + + /** + * If true, source information (comments, locations) will be included in the descriptor set. + * + * Default: false + */ + @Input + boolean getIncludeSourceInfo() + + void setIncludeSourceInfo(boolean value) + + /** + * If true, imports are included in the descriptor set, such that it is self-containing. + * + * Default: false + */ + @Input + boolean getIncludeImports() + + void setIncludeImports(boolean value) +} diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy new file mode 100644 index 00000000..763d417b --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy @@ -0,0 +1,67 @@ +package com.google.protobuf.gradle.tasks + +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Nested + +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +interface GenerateProtoTaskSpec { + + /** + * If true, will set the protoc flag + * --descriptor_set_out="${outputBaseDir}/descriptor_set.desc" + * + * Default: false + */ + @Input + boolean getGenerateDescriptorSet() + + void setGenerateDescriptorSet(boolean enabled) + + @Nested + DescriptorSetSpec getDescriptorSetOptions() + + /** + * Returns the container of protoc plugins. + */ + @Nested + NamedDomainObjectContainer getPlugins() + + /** + * Returns the container of protoc builtins. + */ + @Nested + NamedDomainObjectContainer getBuiltins() + + /** + * Returns true if the task has a plugin with the given name, false otherwise. + */ + boolean hasPlugin(String name) + + /** + * Configures the protoc builtins in a closure, which will be manipulating a + * NamedDomainObjectContainer. + */ + void builtins(Action> configureAction) + + /** + * Configures the protoc builtins in a closure, which will be manipulating a + * NamedDomainObjectContainer. + */ + void builtins(Closure> closure) + + /** + * Configures the protoc plugins in a closure, which will be maniuplating a + * NamedDomainObjectContainer. + */ + void plugins(Action> configureAction) + + /** + * Configures the protoc plugins in a closure, which will be maniuplating a + * NamedDomainObjectContainer. + */ + void plugins(Closure> closure) +} diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/PluginSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/PluginSpec.groovy new file mode 100644 index 00000000..a517ea5a --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/PluginSpec.groovy @@ -0,0 +1,39 @@ +package com.google.protobuf.gradle.tasks + +import groovy.transform.CompileStatic +import org.gradle.api.tasks.Input + +/** + * The container of command-line options for a protoc plugin or a built-in output. + */ +@CompileStatic +@SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class +interface PluginSpec { + + /** + * Adds a plugin option. + */ + PluginSpec option(String option) + + @Input + List getOptions() + + /** + * Returns the name of the plugin or builtin. + */ + @Input + String getName() + + /** + * Set the output directory for this plugin, + * relative to {@link GenerateProtoTask#outputBaseDir}. + */ + void setOutputSubDir(String outputSubDir) + + /** + * Returns the relative outputDir for this plugin. + * If outputDir is not specified, name is used. + */ + @Input + String getOutputSubDir() +} From 46acc137df213718737cf004a2f021fa2c7df33a Mon Sep 17 00:00:00 2001 From: rougsig Date: Tue, 24 Jan 2023 22:17:52 +0300 Subject: [PATCH 02/16] Migrate test project to use temporary spec configuration method --- .../exampleKotlinDslProject/build.gradle.kts | 14 +++++++------ examples/exampleProject/build.gradle | 14 +++++++------ testProjectAndroidBase/build_base.gradle | 20 +++++++++++++------ .../build_base.gradle | 20 +++++++++++++------ testProjectAndroidKotlinDsl/build.gradle.kts | 16 +++++++++------ testProjectAndroidLibrary/build.gradle | 20 +++++++++++++------ testProjectBase/build_base.gradle | 10 ++++++---- testProjectKotlinDslBase/build.gradle.kts | 10 ++++++---- testProjectLite/build.gradle | 12 ++++++----- 9 files changed, 87 insertions(+), 49 deletions(-) diff --git a/examples/exampleKotlinDslProject/build.gradle.kts b/examples/exampleKotlinDslProject/build.gradle.kts index 75451acf..7e10a901 100644 --- a/examples/exampleKotlinDslProject/build.gradle.kts +++ b/examples/exampleKotlinDslProject/build.gradle.kts @@ -47,12 +47,14 @@ protobuf { } generateProtoTasks { ofSourceSet("main").forEach { - it.plugins { - // Apply the "grpc" plugin whose spec is defined above, without - // options. Note the braces cannot be omitted, otherwise the - // plugin will not be added. This is because of the implicit way - // NamedDomainObjectContainer binds the methods. - id("grpc") { } + it.spec { + plugins { + // Apply the "grpc" plugin whose spec is defined above, without + // options. Note the braces cannot be omitted, otherwise the + // plugin will not be added. This is because of the implicit way + // NamedDomainObjectContainer binds the methods. + id("grpc") { } + } } } } diff --git a/examples/exampleProject/build.gradle b/examples/exampleProject/build.gradle index 4fd561f1..c0ff34be 100644 --- a/examples/exampleProject/build.gradle +++ b/examples/exampleProject/build.gradle @@ -45,12 +45,14 @@ protobuf { } generateProtoTasks { ofSourceSet('main').configureEach { - plugins { - // Apply the "grpc" plugin whose spec is defined above, without - // options. Note the braces cannot be omitted, otherwise the - // plugin will not be added. This is because of the implicit way - // NamedDomainObjectContainer binds the methods. - grpc { } + it.spec { + plugins { + // Apply the "grpc" plugin whose spec is defined above, without + // options. Note the braces cannot be omitted, otherwise the + // plugin will not be added. This is because of the implicit way + // NamedDomainObjectContainer binds the methods. + grpc { } + } } } } diff --git a/testProjectAndroidBase/build_base.gradle b/testProjectAndroidBase/build_base.gradle index 29f9fc16..40651d75 100644 --- a/testProjectAndroidBase/build_base.gradle +++ b/testProjectAndroidBase/build_base.gradle @@ -83,13 +83,21 @@ protobuf { } } generateProtoTasks { - all()*.plugins { - javalite { } + all().each { + it.spec { + plugins { + javalite { } + } + } } - ofNonTest()*.plugins { - grpc { - // Options added to --grpc_out - option 'lite' + ofNonTest().each { + it.spec { + plugins { + grpc { + // Options added to --grpc_out + option 'lite' + } + } } } } diff --git a/testProjectAndroidDependentBase/build_base.gradle b/testProjectAndroidDependentBase/build_base.gradle index 165aea5c..607717da 100644 --- a/testProjectAndroidDependentBase/build_base.gradle +++ b/testProjectAndroidDependentBase/build_base.gradle @@ -83,13 +83,21 @@ protobuf { } } generateProtoTasks { - all()*.plugins { - javalite { } + all().each { + it.spec { + plugins { + javalite {} + } + } } - ofNonTest()*.plugins { - grpc { - // Options added to --grpc_out - option 'lite' + ofNonTest().each { + it.spec { + plugins { + grpc { + // Options added to --grpc_out + option 'lite' + } + } } } } diff --git a/testProjectAndroidKotlinDsl/build.gradle.kts b/testProjectAndroidKotlinDsl/build.gradle.kts index cad04866..5c549fd8 100644 --- a/testProjectAndroidKotlinDsl/build.gradle.kts +++ b/testProjectAndroidKotlinDsl/build.gradle.kts @@ -106,15 +106,19 @@ protobuf { } generateProtoTasks { all().forEach { task -> - task.plugins { - id("javalite") { } + task.spec { + plugins { + id("javalite") { } + } } } ofNonTest().forEach { task -> - task.plugins { - id("grpc") { - // Options added to --grpc_out - option("lite") + task.spec { + plugins { + id("grpc") { + // Options added to --grpc_out + option("lite") + } } } } diff --git a/testProjectAndroidLibrary/build.gradle b/testProjectAndroidLibrary/build.gradle index 4539129c..4a5f061d 100644 --- a/testProjectAndroidLibrary/build.gradle +++ b/testProjectAndroidLibrary/build.gradle @@ -65,13 +65,21 @@ protobuf { } } generateProtoTasks { - all()*.plugins { - javalite { } + all().each { + it.spec { + plugins { + javalite {} + } + } } - ofNonTest()*.plugins { - grpc { - // Options added to --grpc_out - option 'lite' + ofNonTest().each { + it.spec { + plugins { + grpc { + // Options added to --grpc_out + option 'lite' + } + } } } } diff --git a/testProjectBase/build_base.gradle b/testProjectBase/build_base.gradle index 287e151d..6368aaba 100644 --- a/testProjectBase/build_base.gradle +++ b/testProjectBase/build_base.gradle @@ -46,12 +46,14 @@ protobuf { } generateProtoTasks { ofSourceSet('grpc').each { task -> - task.plugins { - grpc { - outputSubDir = 'grpc_output' + task.spec { + plugins { + grpc { + outputSubDir = 'grpc_output' + } } + generateDescriptorSet = true } - task.generateDescriptorSet = true } } } diff --git a/testProjectKotlinDslBase/build.gradle.kts b/testProjectKotlinDslBase/build.gradle.kts index ed2a37a5..4c125999 100644 --- a/testProjectKotlinDslBase/build.gradle.kts +++ b/testProjectKotlinDslBase/build.gradle.kts @@ -57,12 +57,14 @@ protobuf { } generateProtoTasks { ofSourceSet("grpc").forEach { task -> - task.plugins { - id("grpc") { - outputSubDir = "grpc_output" + task.spec { + plugins { + id("grpc") { + outputSubDir = "grpc_output" + } } + generateDescriptorSet = true } - task.generateDescriptorSet = true } } } diff --git a/testProjectLite/build.gradle b/testProjectLite/build.gradle index 62239c94..5ff1d07b 100644 --- a/testProjectLite/build.gradle +++ b/testProjectLite/build.gradle @@ -29,11 +29,13 @@ protobuf { } generateProtoTasks { all().each { task -> - task.builtins { - remove java - } - task.plugins { - javalite { } + task.spec { + builtins { + remove java + } + plugins { + javalite { } + } } } } From e319c643b7377bd4d318aa8ea7fa6b1a28cf54e2 Mon Sep 17 00:00:00 2001 From: rougsig Date: Tue, 24 Jan 2023 23:10:20 +0300 Subject: [PATCH 03/16] Specify spec configuration method closure type --- .../groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index 82dea60b..267cdb22 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -389,7 +389,7 @@ public abstract class GenerateProtoTask extends DefaultTask { } @Deprecated // temporary method for refactoring - void spec(Closure closure) { + void spec(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { ConfigureUtil.configure(closure, this.spec.get()) } From 93ddb7af2b41686b6cb3063860bf42aa56a12b84 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 03:11:56 +0300 Subject: [PATCH 04/16] Extract GenerateProtoTask querying fields to ProtoVariant --- .../protobuf/gradle/GenerateProtoTask.groovy | 126 +----------------- .../protobuf/gradle/ProtobufExtension.groovy | 123 ++++++++++------- .../protobuf/gradle/ProtobufPlugin.groovy | 27 ++-- .../internal/DefaultProtoVariant.groovy | 74 ++++++++++ .../ProtoSourceSetObjectFactory.groovy | 20 +++ .../internal/ProtoVariantObjectFactory.groovy | 20 +++ .../protobuf/gradle/tasks/ProtoVariant.groovy | 26 ++++ 7 files changed, 231 insertions(+), 185 deletions(-) create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/ProtoSourceSetObjectFactory.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/tasks/ProtoVariant.groovy diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index 267cdb22..4f2e24e7 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -41,8 +41,6 @@ import org.gradle.api.provider.Property import org.gradle.api.tasks.Nested import groovy.transform.CompileStatic import groovy.transform.PackageScope -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.file.ConfigurableFileCollection @@ -62,7 +60,6 @@ import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.SkipWhenEmpty -import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskAction import javax.inject.Inject @@ -72,7 +69,7 @@ import javax.inject.Inject // TODO(zhangkun83): add per-plugin output dir reconfiguraiton. @CompileStatic @CacheableTask -public abstract class GenerateProtoTask extends DefaultTask { +abstract class GenerateProtoTask extends DefaultTask { // Windows CreateProcess has command line limit of 32768: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx static final int WINDOWS_CMD_LENGTH_LIMIT = 32760 @@ -98,21 +95,6 @@ public abstract class GenerateProtoTask extends DefaultTask { // constructor arguments. We use the initializing flag to prevent users from // accidentally modifying them. private Provider outputBaseDir - // Tags for selectors inside protobuf.generateProtoTasks; do not serialize with Gradle configuration caching - @SuppressWarnings("UnnecessaryTransientModifier") // It is not necessary for task to implement Serializable - transient private SourceSet sourceSet - @SuppressWarnings("UnnecessaryTransientModifier") // It is not necessary for task to implement Serializable - transient private Object variant - private List flavors - private String buildType - private boolean isTestVariant - private final Provider isAndroidProject = providerFactory.provider { Utils.isAndroidProject(project) } - private final Provider isTestProvider = providerFactory.provider { - if (Utils.isAndroidProject(project)) { - return isTestVariant - } - return Utils.isTest(sourceSet.name) - } @SuppressWarnings("AbstractClassWithPublicConstructor") // required to configure properties convention values GenerateProtoTask() { @@ -211,7 +193,6 @@ public abstract class GenerateProtoTask extends DefaultTask { } void setOutputBaseDir(Provider outputBaseDir) { - checkInitializing() Preconditions.checkState(this.outputBaseDir == null, 'outputBaseDir is already set') this.outputBaseDir = outputBaseDir } @@ -221,43 +202,6 @@ public abstract class GenerateProtoTask extends DefaultTask { return outputBaseDir.get() } - void setSourceSet(SourceSet sourceSet) { - checkInitializing() - Preconditions.checkState(!isAndroidProject.get(), - 'sourceSet should not be set in an Android project') - this.sourceSet = sourceSet - } - - void setVariant(Object variant, boolean isTestVariant) { - checkInitializing() - Preconditions.checkState(isAndroidProject.get(), - 'variant should not be set in a Java project') - this.variant = variant - this.isTestVariant = isTestVariant - } - - void setFlavors(List flavors) { - checkInitializing() - Preconditions.checkState(isAndroidProject.get(), - 'flavors should not be set in a Java project') - this.flavors = Collections.unmodifiableList(new ArrayList(flavors)) - } - - void setBuildType(String buildType) { - checkInitializing() - Preconditions.checkState(isAndroidProject.get(), - 'buildType should not be set in a Java project') - this.buildType = buildType - } - - @Internal("Inputs tracked in getSourceDirs()") - SourceSet getSourceSet() { - Preconditions.checkState(!isAndroidProject.get(), - 'sourceSet should not be used in an Android project') - Preconditions.checkNotNull(sourceSet, 'sourceSet is not set') - return sourceSet - } - @SkipWhenEmpty @PathSensitive(PathSensitivity.RELATIVE) @IgnoreEmptyDirectories @@ -272,14 +216,6 @@ public abstract class GenerateProtoTask extends DefaultTask { return includeDirs } - @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") - Object getVariant() { - Preconditions.checkState(isAndroidProject.get(), - 'variant should not be used in a Java project') - Preconditions.checkNotNull(variant, 'variant is not set') - return variant - } - /** * Not for external use. Used to expose inputs to Gradle. * @@ -317,48 +253,6 @@ public abstract class GenerateProtoTask extends DefaultTask { [toolsLocator.protoc] + requireSpec().plugins.collect { PluginSpec it -> toolsLocator.plugins.getByName(it.name) } } - @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") - Provider getIsAndroidProject() { - return isAndroidProject - } - - @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") - boolean getIsTestVariant() { - Preconditions.checkState(isAndroidProject.get(), - 'isTestVariant should not be used in a Java project') - Preconditions.checkNotNull(variant, 'variant is not set') - return isTestVariant - } - - @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") - List getFlavors() { - Preconditions.checkState(isAndroidProject.get(), - 'flavors should not be used in a Java project') - Preconditions.checkNotNull(flavors, 'flavors is not set') - return flavors - } - - @TypeChecked(TypeCheckingMode.SKIP) // Don't depend on AGP - @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") - String getBuildType() { - Preconditions.checkState(isAndroidProject.get(), - 'buildType should not be used in a Java project') - Preconditions.checkState( - variant.name == 'test' || buildType, - 'buildType is not set and task is not for local unit test variant') - return buildType - } - - void doneInitializing() { - Preconditions.checkState(state == State.INIT, "Invalid state: ${state}") - state = State.CONFIG - } - - void doneConfig() { - Preconditions.checkState(state == State.CONFIG, "Invalid state: ${state}") - state = State.FINALIZED - } - @Internal("Tracked as an input via getDescriptorSetOptionsForCaching()") String getDescriptorPath() { GenerateProtoTaskSpec spec = requireSpec() @@ -397,7 +291,6 @@ public abstract class GenerateProtoTask extends DefaultTask { * Add a directory to protoc's include path. */ public void addIncludeDir(FileCollection dir) { - checkCanConfig() includeDirs.from(dir) } @@ -405,7 +298,6 @@ public abstract class GenerateProtoTask extends DefaultTask { * Add a collection of proto source files to be compiled. */ public void addSourceDirs(FileCollection dirs) { - checkCanConfig() sourceDirs.from(dirs) } @@ -469,7 +361,6 @@ public abstract class GenerateProtoTask extends DefaultTask { @TaskAction void compile() { - Preconditions.checkState(state == State.FINALIZED, 'doneConfig() has not been called') GenerateProtoTaskSpec spec = requireSpec() copyActionFacade.delete { DeleteSpec deleteSpec -> @@ -548,21 +439,6 @@ public abstract class GenerateProtoTask extends DefaultTask { return spec.get() } - private static enum State { - INIT, CONFIG, FINALIZED - } - - private State state = State.INIT - - private void checkInitializing() { - Preconditions.checkState(state == State.INIT, 'Should not be called after initilization has finished') - } - - private void checkCanConfig() { - Preconditions.checkState(state == State.CONFIG || state == State.INIT, - 'Should not be called after configuration has finished') - } - private void compileFiles(List cmd) { logger.log(LogLevel.INFO, cmd.toString()) diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy index 0de530f8..34688b04 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy @@ -28,17 +28,19 @@ */ package com.google.protobuf.gradle -import com.google.protobuf.gradle.internal.DefaultProtoSourceSet +import com.google.protobuf.gradle.internal.ProtoSourceSetObjectFactory +import com.google.protobuf.gradle.internal.ProtoVariantObjectFactory +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.ProtoSourceSet +import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic import groovy.transform.PackageScope -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.NamedDomainObjectSet import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property -import org.gradle.api.tasks.TaskCollection /** * Adds the protobuf {} block as a property of the project. @@ -50,8 +52,8 @@ abstract class ProtobufExtension { private final Project project private final GenerateProtoTaskCollection tasks private final ToolsLocator tools - private final ArrayList> taskConfigActions private final NamedDomainObjectContainer sourceSets + private final NamedDomainObjectContainer variants @PackageScope final String defaultGeneratedFilesBaseDir @@ -60,12 +62,13 @@ abstract class ProtobufExtension { this.project = project this.tasks = new GenerateProtoTaskCollection(project) this.tools = new ToolsLocator(project) - this.taskConfigActions = [] + this.defaultGeneratedFilesBaseDir = "${project.buildDir}/generated/source/proto" this.generatedFilesBaseDirProperty.convention(defaultGeneratedFilesBaseDir) - this.sourceSets = project.objects.domainObjectContainer(ProtoSourceSet) { String name -> - new DefaultProtoSourceSet(name, project.objects) - } + + ObjectFactory objects = project.objects + this.sourceSets = project.objects.domainObjectContainer(ProtoSourceSet, new ProtoSourceSetObjectFactory(objects)) + this.variants = project.objects.domainObjectContainer(ProtoVariant, new ProtoVariantObjectFactory(project)) } @PackageScope @@ -73,6 +76,11 @@ abstract class ProtobufExtension { return this.sourceSets } + @PackageScope + NamedDomainObjectContainer getVariants() { + return variants + } + @PackageScope ToolsLocator getTools() { return tools @@ -94,13 +102,6 @@ abstract class ProtobufExtension { @PackageScope abstract Property getGeneratedFilesBaseDirProperty() - @PackageScope - void configureTasks() { - this.taskConfigActions.each { action -> - action.execute(tasks) - } - } - //=========================================================================== // Configuration methods //=========================================================================== @@ -132,8 +133,8 @@ abstract class ProtobufExtension { * change the task in your own afterEvaluate closure, as the change may not * be picked up correctly by the wired javaCompile task. */ - public void generateProtoTasks(Action configureAction) { - taskConfigActions.add(configureAction) + void generateProtoTasks(Action action) { + action.execute(tasks) } /** @@ -148,6 +149,7 @@ abstract class ProtobufExtension { return tasks } + @CompileStatic public class GenerateProtoTaskCollection { private final Project project @@ -155,45 +157,76 @@ abstract class ProtobufExtension { this.project = project } - public TaskCollection all() { - return project.tasks.withType(GenerateProtoTask) + private NamedDomainObjectSet variants() { + return project.extensions.getByType(ProtobufExtension).variants + } + + void all(Action action) { + variants.all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + void all(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + all(closure as Action) + } + + void ofSourceSet(String sourceSet, Action action) { + variants() + .matching { ProtoVariant variant -> !Utils.isAndroidProject(project) && variant.sourceSet == sourceSet } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + void ofSourceSet(String sourceSet, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofSourceSet(sourceSet, closure as Action) + } + + void ofFlavor(String flavor, Action action) { + variants() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.flavors.contains(flavor) } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + void ofFlavor(String flavor, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofFlavor(flavor, closure as Action) + } + + void ofBuildType(String buildType, Action action) { + variants() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.buildType == buildType } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + void ofBuildType(String buildType, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofBuildType(buildType, closure as Action) } - public TaskCollection ofSourceSet(String sourceSet) { - return all().matching { GenerateProtoTask task -> - !Utils.isAndroidProject(project) && task.sourceSet.name == sourceSet - } + void ofVariant(String name, Action action) { + variants() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.name == name } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } } - public TaskCollection ofFlavor(String flavor) { - return all().matching { GenerateProtoTask task -> - Utils.isAndroidProject(project) && task.flavors.contains(flavor) - } + void ofVariant(String name, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofVariant(name, closure as Action) } - public TaskCollection ofBuildType(String buildType) { - return all().matching { GenerateProtoTask task -> - Utils.isAndroidProject(project) && task.buildType == buildType - } + void ofNonTest(Action action) { + variants() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && !variant.isTest } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } } - @TypeChecked(TypeCheckingMode.SKIP) // Don't depend on AGP - public TaskCollection ofVariant(String variant) { - return all().matching { GenerateProtoTask task -> - Utils.isAndroidProject(project) && task.variant.name == variant - } + void ofNonTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofNonTest(closure as Action) } - public TaskCollection ofNonTest() { - return all().matching { GenerateProtoTask task -> - Utils.isAndroidProject(project) && !task.isTestVariant - } + void ofTest(Action action) { + variants() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.isTest } + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } } - public TaskCollection ofTest() { - return all().matching { GenerateProtoTask task -> - Utils.isAndroidProject(project) && task.isTestVariant - } + void ofTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { + ofTest(closure as Action) } } } diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy index 1500d470..5246e235 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy @@ -36,6 +36,7 @@ import com.android.builder.model.SourceProvider import com.google.protobuf.gradle.internal.DefaultProtoSourceSet import com.google.protobuf.gradle.internal.ProjectExt import com.google.protobuf.gradle.tasks.ProtoSourceSet +import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic import groovy.transform.TypeChecked import groovy.transform.TypeCheckingMode @@ -153,11 +154,6 @@ class ProtobufPlugin implements Plugin { } } project.afterEvaluate { - this.protobufExtension.configureTasks() - // Disallow user configuration outside the config closures, because the operations just - // after the doneConfig() loop over the generated outputs and will be out-of-date if - // plugin output is added after this point. - this.protobufExtension.generateProtoTasks.all().configureEach { it.doneConfig() } postConfigure.each { it.call() } // protoc and codegen plugin configuration may change through the protobuf{} // block. Only at this point the configuration has been finalized. @@ -237,6 +233,7 @@ class ProtobufPlugin implements Plugin { private void addTasksForSourceSet( SourceSet sourceSet, ProtoSourceSet protoSourceSet, Configuration protobufConfig, Configuration compileProtoPath, Collection postConfigure) { + ProtoVariant protoVariant = protobufExtension.variants.create(sourceSet.name) Provider extractProtosTask = setupExtractProtosTask(protoSourceSet, protobufConfig) Provider extractIncludeProtosTask = setupExtractIncludeProtosTask( @@ -248,10 +245,11 @@ class ProtobufPlugin implements Plugin { protoSourceSet.includesFrom(protobufExtension.sourceSets.getByName("main")) } + protoVariant.sourceSet = sourceSet.name + protoVariant.isTest = Utils.isTest(sourceSet.name) + protoVariant.generateProtoTaskSpec.builtins.maybeCreate("java") Provider generateProtoTask = addGenerateProtoTask(protoSourceSet) { - it.sourceSet = sourceSet - it.doneInitializing() - it.spec.get().builtins.maybeCreate("java") + it.spec.set(protoVariant.generateProtoTaskSpec) } sourceSet.java.srcDirs(protoSourceSet.output) @@ -296,6 +294,7 @@ class ProtobufPlugin implements Plugin { NamedDomainObjectContainer variantSourceSets, Collection postConfigure ) { + ProtoVariant protoVariant = protobufExtension.variants.create(variant.name) Boolean isTestVariant = variant instanceof TestVariant || variant instanceof UnitTestVariant ProtoSourceSet variantSourceSet = variantSourceSets.create(variant.name) @@ -310,7 +309,7 @@ class ProtobufPlugin implements Plugin { // Make protos in 'test' variant able to import protos from the 'main' variant. // Pass include proto files from main to test. - if (variant instanceof TestVariant || variant instanceof UnitTestVariant) { + if (isTestVariant) { postConfigure.add { variantSourceSet.includesFrom(protobufExtension.sourceSets.getByName("main")) variantSourceSet.includesFrom(variantSourceSets.getByName(variant.testedVariant.name)) @@ -324,13 +323,11 @@ class ProtobufPlugin implements Plugin { variantSourceSet.extendsFrom(protobufExtension.sourceSets.getByName(sourceProvider.name)) } + protoVariant.isTest = isTestVariant + protoVariant.flavors = variant.productFlavors.collect { it.name } as Set + protoVariant.buildType = variant.hasProperty('buildType') ? variant.buildType.name : null Provider generateProtoTask = addGenerateProtoTask(variantSourceSet) { - it.setVariant(variant, isTestVariant) - it.flavors = variant.productFlavors.collect { it.name } - if (variant.hasProperty('buildType')) { - it.buildType = variant.buildType.name - } - it.doneInitializing() + it.spec.set(protoVariant.generateProtoTaskSpec) } if (project.android.hasProperty('libraryVariants')) { diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy new file mode 100644 index 00000000..4cc18443 --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy @@ -0,0 +1,74 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.ProtoVariant +import groovy.transform.CompileStatic +import org.gradle.api.Project + +@CompileStatic +class DefaultProtoVariant implements ProtoVariant { + private final Project project + private final GenerateProtoTaskSpec generateProtoTaskSpec + private final String name + private String sourceSet + private String buildType + private boolean isTest + private Set flavors + + DefaultProtoVariant(String name, Project project) { + this.project = project + this.name = name + this.generateProtoTaskSpec = new DefaultGenerateProtoTaskSpec(project.objects) + this.flavors = [] as Set + } + + @Override + GenerateProtoTaskSpec getGenerateProtoTaskSpec() { + return this.generateProtoTaskSpec + } + + @Override + String getSourceSet() { + return this.sourceSet + } + + @Override + void setSourceSet(String sourceSet) { + this.sourceSet = sourceSet + } + + @Override + String getName() { + return this.name + } + + @Override + Set getFlavors() { + return this.flavors + } + + @Override + void setFlavors(Set flavors) { + this.flavors = flavors + } + + @Override + String getBuildType() { + return this.buildType + } + + @Override + void setBuildType(String buildType) { + this.buildType = buildType + } + + @Override + boolean getIsTest() { + return this.isTest + } + + @Override + void setIsTest(boolean isTest) { + this.isTest = isTest + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/ProtoSourceSetObjectFactory.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoSourceSetObjectFactory.groovy new file mode 100644 index 00000000..9175da61 --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoSourceSetObjectFactory.groovy @@ -0,0 +1,20 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.ProtoSourceSet +import groovy.transform.CompileStatic +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.model.ObjectFactory + +@CompileStatic +class ProtoSourceSetObjectFactory implements NamedDomainObjectFactory { + private final ObjectFactory objects + + ProtoSourceSetObjectFactory(ObjectFactory objects) { + this.objects = objects + } + + @Override + ProtoSourceSet create(String name) { + return new DefaultProtoSourceSet(name, objects) + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy new file mode 100644 index 00000000..36c4d754 --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy @@ -0,0 +1,20 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.ProtoVariant +import groovy.transform.CompileStatic +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.Project + +@CompileStatic +class ProtoVariantObjectFactory implements NamedDomainObjectFactory { + private final Project project + + ProtoVariantObjectFactory(Project project) { + this.project = project + } + + @Override + ProtoVariant create(String name) { + return new DefaultProtoVariant(name, project) + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/ProtoVariant.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/ProtoVariant.groovy new file mode 100644 index 00000000..8b6deacc --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/ProtoVariant.groovy @@ -0,0 +1,26 @@ +package com.google.protobuf.gradle.tasks + +import groovy.transform.CompileStatic + +@CompileStatic +interface ProtoVariant { + GenerateProtoTaskSpec getGenerateProtoTaskSpec() + + String getSourceSet() + + void setSourceSet(String name) + + String getName() + + Set getFlavors() + + void setFlavors(Set flavors) + + String getBuildType() + + void setBuildType(String name) + + boolean getIsTest() + + void setIsTest(boolean value) +} From 415c9be54e509c187a500e9ae9644ede1d6c03e0 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 03:15:28 +0300 Subject: [PATCH 05/16] Migrate test projects to use newer configuration api --- .../exampleKotlinDslProject/build.gradle.kts | 16 +++++++-------- examples/exampleProject/build.gradle | 16 +++++++-------- testProjectAndroidBase/build_base.gradle | 20 ++++++++----------- .../build_base.gradle | 20 ++++++++----------- testProjectAndroidKotlinDsl/build.gradle.kts | 20 ++++++++----------- testProjectAndroidLibrary/build.gradle | 12 ++++------- testProjectBase/build_base.gradle | 12 +++++------ testProjectKotlinDslBase/build.gradle.kts | 12 +++++------ testProjectLite/build.gradle | 14 ++++++------- 9 files changed, 58 insertions(+), 84 deletions(-) diff --git a/examples/exampleKotlinDslProject/build.gradle.kts b/examples/exampleKotlinDslProject/build.gradle.kts index 7e10a901..81576145 100644 --- a/examples/exampleKotlinDslProject/build.gradle.kts +++ b/examples/exampleKotlinDslProject/build.gradle.kts @@ -46,15 +46,13 @@ protobuf { } } generateProtoTasks { - ofSourceSet("main").forEach { - it.spec { - plugins { - // Apply the "grpc" plugin whose spec is defined above, without - // options. Note the braces cannot be omitted, otherwise the - // plugin will not be added. This is because of the implicit way - // NamedDomainObjectContainer binds the methods. - id("grpc") { } - } + ofSourceSet("main") { + plugins { + // Apply the "grpc" plugin whose spec is defined above, without + // options. Note the braces cannot be omitted, otherwise the + // plugin will not be added. This is because of the implicit way + // NamedDomainObjectContainer binds the methods. + id("grpc") { } } } } diff --git a/examples/exampleProject/build.gradle b/examples/exampleProject/build.gradle index c0ff34be..9c3561a3 100644 --- a/examples/exampleProject/build.gradle +++ b/examples/exampleProject/build.gradle @@ -44,15 +44,13 @@ protobuf { } } generateProtoTasks { - ofSourceSet('main').configureEach { - it.spec { - plugins { - // Apply the "grpc" plugin whose spec is defined above, without - // options. Note the braces cannot be omitted, otherwise the - // plugin will not be added. This is because of the implicit way - // NamedDomainObjectContainer binds the methods. - grpc { } - } + ofSourceSet('main') { + plugins { + // Apply the "grpc" plugin whose spec is defined above, without + // options. Note the braces cannot be omitted, otherwise the + // plugin will not be added. This is because of the implicit way + // NamedDomainObjectContainer binds the methods. + grpc { } } } } diff --git a/testProjectAndroidBase/build_base.gradle b/testProjectAndroidBase/build_base.gradle index 40651d75..748a0138 100644 --- a/testProjectAndroidBase/build_base.gradle +++ b/testProjectAndroidBase/build_base.gradle @@ -83,20 +83,16 @@ protobuf { } } generateProtoTasks { - all().each { - it.spec { - plugins { - javalite { } - } + all { + plugins { + javalite { } } } - ofNonTest().each { - it.spec { - plugins { - grpc { - // Options added to --grpc_out - option 'lite' - } + ofNonTest { + plugins { + grpc { + // Options added to --grpc_out + option 'lite' } } } diff --git a/testProjectAndroidDependentBase/build_base.gradle b/testProjectAndroidDependentBase/build_base.gradle index 607717da..b6727de3 100644 --- a/testProjectAndroidDependentBase/build_base.gradle +++ b/testProjectAndroidDependentBase/build_base.gradle @@ -83,20 +83,16 @@ protobuf { } } generateProtoTasks { - all().each { - it.spec { - plugins { - javalite {} - } + all { + plugins { + javalite {} } } - ofNonTest().each { - it.spec { - plugins { - grpc { - // Options added to --grpc_out - option 'lite' - } + ofNonTest { + plugins { + grpc { + // Options added to --grpc_out + option 'lite' } } } diff --git a/testProjectAndroidKotlinDsl/build.gradle.kts b/testProjectAndroidKotlinDsl/build.gradle.kts index 5c549fd8..4532b415 100644 --- a/testProjectAndroidKotlinDsl/build.gradle.kts +++ b/testProjectAndroidKotlinDsl/build.gradle.kts @@ -105,20 +105,16 @@ protobuf { } } generateProtoTasks { - all().forEach { task -> - task.spec { - plugins { - id("javalite") { } - } + all { + plugins { + id("javalite") { } } } - ofNonTest().forEach { task -> - task.spec { - plugins { - id("grpc") { - // Options added to --grpc_out - option("lite") - } + ofNonTest { + plugins { + id("grpc") { + // Options added to --grpc_out + option("lite") } } } diff --git a/testProjectAndroidLibrary/build.gradle b/testProjectAndroidLibrary/build.gradle index 4a5f061d..79a23857 100644 --- a/testProjectAndroidLibrary/build.gradle +++ b/testProjectAndroidLibrary/build.gradle @@ -65,15 +65,11 @@ protobuf { } } generateProtoTasks { - all().each { - it.spec { - plugins { - javalite {} - } + all { + plugins { + javalite {} } - } - ofNonTest().each { - it.spec { + ofNonTest { plugins { grpc { // Options added to --grpc_out diff --git a/testProjectBase/build_base.gradle b/testProjectBase/build_base.gradle index 6368aaba..9ef93a96 100644 --- a/testProjectBase/build_base.gradle +++ b/testProjectBase/build_base.gradle @@ -45,15 +45,13 @@ protobuf { } } generateProtoTasks { - ofSourceSet('grpc').each { task -> - task.spec { - plugins { - grpc { - outputSubDir = 'grpc_output' - } + ofSourceSet('grpc') { + plugins { + grpc { + outputSubDir = 'grpc_output' } - generateDescriptorSet = true } + generateDescriptorSet = true } } } diff --git a/testProjectKotlinDslBase/build.gradle.kts b/testProjectKotlinDslBase/build.gradle.kts index 4c125999..82c8562f 100644 --- a/testProjectKotlinDslBase/build.gradle.kts +++ b/testProjectKotlinDslBase/build.gradle.kts @@ -56,15 +56,13 @@ protobuf { } } generateProtoTasks { - ofSourceSet("grpc").forEach { task -> - task.spec { - plugins { - id("grpc") { - outputSubDir = "grpc_output" - } + ofSourceSet("grpc") { + plugins { + id("grpc") { + outputSubDir = "grpc_output" } - generateDescriptorSet = true } + generateDescriptorSet = true } } } diff --git a/testProjectLite/build.gradle b/testProjectLite/build.gradle index 5ff1d07b..0d14e252 100644 --- a/testProjectLite/build.gradle +++ b/testProjectLite/build.gradle @@ -28,14 +28,12 @@ protobuf { } } generateProtoTasks { - all().each { task -> - task.spec { - builtins { - remove java - } - plugins { - javalite { } - } + all { + builtins { + remove java + } + plugins { + javalite { } } } } From 61747be5517d73d6e254690a5a394628114031d1 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 03:48:05 +0300 Subject: [PATCH 06/16] Fix GenerateProtoTaskCollection method with closures --- .../protobuf/gradle/GenerateProtoTask.groovy | 23 ---------------- .../protobuf/gradle/ProtobufExtension.groovy | 27 ++++++++++++++----- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index 4f2e24e7..3fd54d78 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -277,16 +277,6 @@ abstract class GenerateProtoTask extends DefaultTask { // Configuration methods //=========================================================================== - @Deprecated // temporary method for refactoring - void spec(Action configureAction) { - configureAction.execute(this.spec.get()) - } - - @Deprecated // temporary method for refactoring - void spec(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ConfigureUtil.configure(closure, this.spec.get()) - } - /** * Add a directory to protoc's include path. */ @@ -301,19 +291,6 @@ abstract class GenerateProtoTask extends DefaultTask { sourceDirs.from(dirs) } - /** - * Returns true if the Java source set or Android variant is test related. - */ - @Input - public boolean getIsTest() { - return isTestProvider.get() - } - - @Internal("Already captured with getIsTest()") - Provider getIsTestProvider() { - return isTestProvider - } - //=========================================================================== // protoc invocation logic //=========================================================================== diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy index 34688b04..ad0c3c63 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy @@ -41,6 +41,7 @@ import org.gradle.api.NamedDomainObjectSet import org.gradle.api.Project import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property +import org.gradle.util.ConfigureUtil /** * Adds the protobuf {} block as a property of the project. @@ -114,6 +115,10 @@ abstract class ProtobufExtension { configureAction.execute(tools.protoc) } + public void protoc(@DelegatesTo(ExecutableLocator) Closure closure) { + ConfigureUtil.configure(closure, tools.protoc) + } + /** * Locate the codegen plugin executables. The closure will be manipulating a * NamedDomainObjectContainer. @@ -122,6 +127,10 @@ abstract class ProtobufExtension { configureAction.execute(tools.plugins) } + public void plugins(Closure> closure) { + ConfigureUtil.configure(closure, tools.plugins) + } + /** * Configures the generateProto tasks in the given closure. * @@ -137,6 +146,10 @@ abstract class ProtobufExtension { action.execute(tasks) } + void generateProtoTasks(@DelegatesTo(GenerateProtoTaskCollection) Closure closure) { + ConfigureUtil.configure(closure, tasks) + } + /** * Returns the collection of generateProto tasks. Note the tasks are * available only after project evaluation. @@ -166,7 +179,7 @@ abstract class ProtobufExtension { } void all(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - all(closure as Action) + all(ConfigureUtil.configureUsing(closure)) } void ofSourceSet(String sourceSet, Action action) { @@ -176,7 +189,7 @@ abstract class ProtobufExtension { } void ofSourceSet(String sourceSet, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofSourceSet(sourceSet, closure as Action) + ofSourceSet(sourceSet, ConfigureUtil.configureUsing(closure)) } void ofFlavor(String flavor, Action action) { @@ -186,7 +199,7 @@ abstract class ProtobufExtension { } void ofFlavor(String flavor, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofFlavor(flavor, closure as Action) + ofFlavor(flavor, ConfigureUtil.configureUsing(closure)) } void ofBuildType(String buildType, Action action) { @@ -196,7 +209,7 @@ abstract class ProtobufExtension { } void ofBuildType(String buildType, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofBuildType(buildType, closure as Action) + ofBuildType(buildType, ConfigureUtil.configureUsing(closure)) } void ofVariant(String name, Action action) { @@ -206,7 +219,7 @@ abstract class ProtobufExtension { } void ofVariant(String name, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofVariant(name, closure as Action) + ofVariant(name, ConfigureUtil.configureUsing(closure)) } void ofNonTest(Action action) { @@ -216,7 +229,7 @@ abstract class ProtobufExtension { } void ofNonTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofNonTest(closure as Action) + ofNonTest(ConfigureUtil.configureUsing(closure)) } void ofTest(Action action) { @@ -226,7 +239,7 @@ abstract class ProtobufExtension { } void ofTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofTest(closure as Action) + ofTest(ConfigureUtil.configureUsing(closure)) } } } From 1a8baea518c82380941e253a7e630bc666c6799a Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 03:48:30 +0300 Subject: [PATCH 07/16] Fix testProjectBuildTimeProto project --- testProjectBuildTimeProto/build.gradle | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/testProjectBuildTimeProto/build.gradle b/testProjectBuildTimeProto/build.gradle index a4ba1364..462cd343 100644 --- a/testProjectBuildTimeProto/build.gradle +++ b/testProjectBuildTimeProto/build.gradle @@ -1,3 +1,5 @@ +import com.google.protobuf.gradle.GenerateProtoTask + plugins { id 'java' id 'com.google.protobuf' @@ -40,7 +42,8 @@ protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.0.0' } - generateProtoTasks { - all().each { task -> task.dependsOn generateProtobuf } - } +} + +tasks.withType(GenerateProtoTask).configureEach { + dependsOn generateProtobuf } From 07a3bf2b21ceb97600ce5d92973aa2c6452f59b9 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 03:51:41 +0300 Subject: [PATCH 08/16] Fix codenarc issues --- .../groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index 3fd54d78..f2559ecd 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -31,8 +31,6 @@ package com.google.protobuf.gradle import static java.nio.charset.StandardCharsets.US_ASCII -import org.gradle.api.Action -import org.gradle.util.ConfigureUtil import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.PluginSpec From 3dbeccd403b4fa031d96d914f3b030200f789bf7 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 04:41:39 +0300 Subject: [PATCH 09/16] Fix tests for GenerateProtoTaskCollection --- .../protobuf/gradle/ProtobufExtension.groovy | 89 +------- .../DefaultGenerateProtoTaskCollection.groovy | 131 +++++++++++ .../tasks/GenerateProtoTaskCollection.groovy | 33 +++ testProjectAndroidBase/build_base.gradle | 204 ++++++++--------- .../build_base.gradle | 202 ++++++++--------- testProjectAndroidKotlinDsl/build.gradle.kts | 205 +++++++++--------- testProjectBase/build_base.gradle | 6 +- testProjectKotlinDslBase/build.gradle.kts | 3 +- 8 files changed, 478 insertions(+), 395 deletions(-) create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskCollection.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskCollection.groovy diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy index ad0c3c63..b1d62a9a 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy @@ -28,16 +28,16 @@ */ package com.google.protobuf.gradle +import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskCollection import com.google.protobuf.gradle.internal.ProtoSourceSetObjectFactory import com.google.protobuf.gradle.internal.ProtoVariantObjectFactory -import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.GenerateProtoTaskCollection import com.google.protobuf.gradle.tasks.ProtoSourceSet import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic import groovy.transform.PackageScope import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.NamedDomainObjectSet import org.gradle.api.Project import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property @@ -61,7 +61,7 @@ abstract class ProtobufExtension { public ProtobufExtension(final Project project) { this.project = project - this.tasks = new GenerateProtoTaskCollection(project) + this.tasks = new DefaultGenerateProtoTaskCollection(project) this.tools = new ToolsLocator(project) this.defaultGeneratedFilesBaseDir = "${project.buildDir}/generated/source/proto" @@ -72,12 +72,10 @@ abstract class ProtobufExtension { this.variants = project.objects.domainObjectContainer(ProtoVariant, new ProtoVariantObjectFactory(project)) } - @PackageScope NamedDomainObjectContainer getSourceSets() { return this.sourceSets } - @PackageScope NamedDomainObjectContainer getVariants() { return variants } @@ -161,85 +159,4 @@ abstract class ProtobufExtension { public GenerateProtoTaskCollection getGenerateProtoTasks() { return tasks } - - @CompileStatic - public class GenerateProtoTaskCollection { - private final Project project - - GenerateProtoTaskCollection(final Project project) { - this.project = project - } - - private NamedDomainObjectSet variants() { - return project.extensions.getByType(ProtobufExtension).variants - } - - void all(Action action) { - variants.all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void all(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - all(ConfigureUtil.configureUsing(closure)) - } - - void ofSourceSet(String sourceSet, Action action) { - variants() - .matching { ProtoVariant variant -> !Utils.isAndroidProject(project) && variant.sourceSet == sourceSet } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofSourceSet(String sourceSet, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofSourceSet(sourceSet, ConfigureUtil.configureUsing(closure)) - } - - void ofFlavor(String flavor, Action action) { - variants() - .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.flavors.contains(flavor) } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofFlavor(String flavor, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofFlavor(flavor, ConfigureUtil.configureUsing(closure)) - } - - void ofBuildType(String buildType, Action action) { - variants() - .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.buildType == buildType } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofBuildType(String buildType, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofBuildType(buildType, ConfigureUtil.configureUsing(closure)) - } - - void ofVariant(String name, Action action) { - variants() - .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.name == name } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofVariant(String name, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofVariant(name, ConfigureUtil.configureUsing(closure)) - } - - void ofNonTest(Action action) { - variants() - .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && !variant.isTest } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofNonTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofNonTest(ConfigureUtil.configureUsing(closure)) - } - - void ofTest(Action action) { - variants() - .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.isTest } - .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } - } - - void ofTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) { - ofTest(ConfigureUtil.configureUsing(closure)) - } - } } diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskCollection.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskCollection.groovy new file mode 100644 index 00000000..ee2537aa --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskCollection.groovy @@ -0,0 +1,131 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.ProtobufExtension +import com.google.protobuf.gradle.Utils +import com.google.protobuf.gradle.tasks.GenerateProtoTaskCollection +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import com.google.protobuf.gradle.tasks.ProtoVariant +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectSet +import org.gradle.api.Project +import org.gradle.util.ConfigureUtil + +@CompileStatic +class DefaultGenerateProtoTaskCollection implements GenerateProtoTaskCollection { + private final Project project + + DefaultGenerateProtoTaskCollection(Project project) { + this.project = project + } + + NamedDomainObjectSet all() { + return project.extensions.getByType(ProtobufExtension).variants + } + + @Override + void all(Action action) { + all().all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void all(Closure closure) { + all(ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofSourceSet(String sourceSet) { + return all() + .matching { ProtoVariant variant -> !Utils.isAndroidProject(project) && variant.sourceSet == sourceSet } + } + + @Override + void ofSourceSet(String sourceSet, Action action) { + ofSourceSet(sourceSet) + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofSourceSet(String sourceSet, Closure closure) { + ofSourceSet(sourceSet, ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofFlavor(String flavor) { + return all() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.flavors.contains(flavor) } + } + + @Override + void ofFlavor(String flavor, Action action) { + ofFlavor(flavor) + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofFlavor(String flavor, Closure closure) { + ofFlavor(flavor, ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofBuildType(String buildType) { + return all() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.buildType == buildType } + } + + @Override + void ofBuildType(String buildType, Action action) { + ofBuildType(buildType) + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofBuildType(String buildType, Closure closure) { + ofBuildType(buildType, ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofVariant(String name) { + return all() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.name == name } + } + + @Override + void ofVariant(String name, Action action) { + ofVariant(name) + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofVariant(String name, Closure closure) { + ofVariant(name, ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofNonTest() { + return all() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && !variant.isTest } + } + + @Override + void ofNonTest(Action action) { + ofNonTest() + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofNonTest(Closure closure) { + ofNonTest(ConfigureUtil.configureUsing(closure)) + } + + NamedDomainObjectSet ofTest() { + all() + .matching { ProtoVariant variant -> Utils.isAndroidProject(project) && variant.isTest } + } + + @Override + void ofTest(Action action) { + ofTest() + .all { ProtoVariant variant -> action.execute(variant.generateProtoTaskSpec) } + } + + @Override + void ofTest(Closure closure) { + ofTest(ConfigureUtil.configureUsing(closure)) + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskCollection.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskCollection.groovy new file mode 100644 index 00000000..ef9f951f --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskCollection.groovy @@ -0,0 +1,33 @@ +package com.google.protobuf.gradle.tasks + +import org.gradle.api.Action + +interface GenerateProtoTaskCollection { + void all(Action action) + + void all(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofSourceSet(String sourceSet, Action action) + + void ofSourceSet(String sourceSet, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofFlavor(String flavor, Action action) + + void ofFlavor(String flavor, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofBuildType(String buildType, Action action) + + void ofBuildType(String buildType, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofVariant(String name, Action action) + + void ofVariant(String name, @DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofNonTest(Action action) + + void ofNonTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) + + void ofTest(Action action) + + void ofTest(@DelegatesTo(GenerateProtoTaskSpec) Closure closure) +} diff --git a/testProjectAndroidBase/build_base.gradle b/testProjectAndroidBase/build_base.gradle index 748a0138..c68d64cf 100644 --- a/testProjectAndroidBase/build_base.gradle +++ b/testProjectAndroidBase/build_base.gradle @@ -132,133 +132,133 @@ afterEvaluate { test.doLast { assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.all().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', ] as Set == protobuf.generateProtoTasks.ofTest().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofNonTest().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('freeapp').collect({ it.name }) as Set assert [ - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('retailapp').collect({ it.name }) as Set assert [ - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('x86').collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('arm').collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappDebugProto' + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappDebug', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappDebug', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappDebug', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappDebug' ] as Set == protobuf.generateProtoTasks.ofBuildType('debug').collect({ it.name }) as Set assert [ - 'generateArmFreeappReleaseProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmRetailappReleaseProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateX86FreeappReleaseProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86RetailappReleaseProto', - 'generateX86RetailappReleaseUnitTestProto', + 'armFreeappRelease', + 'armFreeappReleaseUnitTest', + 'armRetailappRelease', + 'armRetailappReleaseUnitTest', + 'x86FreeappRelease', + 'x86FreeappReleaseUnitTest', + 'x86RetailappRelease', + 'x86RetailappReleaseUnitTest', ] as Set == protobuf.generateProtoTasks.ofBuildType('release').collect({ it.name }) as Set - assert ['generateX86FreeappDebugAndroidTestProto'] as Set == + assert ['x86FreeappDebugAndroidTestProto'] as Set == protobuf.generateProtoTasks.ofVariant('x86FreeappDebugAndroidTest').collect({ it.name }) as Set // "androidTest" sourceSet is not a flavor @@ -267,7 +267,7 @@ afterEvaluate { // "unitTest" sourceset is not a flavor assert [] as Set == protobuf.generateProtoTasks.ofFlavor('unitTest').collect({ it.name }) as Set - android.applicationVariants.each { variant -> + android.applicationVariants.each { variant -> assertJavaCompileHasProtoGeneratedDir(variant, ['javalite', 'grpc']) } diff --git a/testProjectAndroidDependentBase/build_base.gradle b/testProjectAndroidDependentBase/build_base.gradle index b6727de3..85fa0f13 100644 --- a/testProjectAndroidDependentBase/build_base.gradle +++ b/testProjectAndroidDependentBase/build_base.gradle @@ -132,133 +132,133 @@ afterEvaluate { test.doLast { assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.all().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', ] as Set == protobuf.generateProtoTasks.ofTest().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofNonTest().collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('freeapp').collect({ it.name }) as Set assert [ - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('retailapp').collect({ it.name }) as Set assert [ - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86FreeappReleaseProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappReleaseUnitTestProto', - 'generateX86RetailappDebugProto', - 'generateX86RetailappReleaseProto', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappReleaseUnitTest', + 'x86FreeappDebug', + 'x86FreeappRelease', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappReleaseUnitTest', + 'x86RetailappDebug', + 'x86RetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('x86').collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmFreeappReleaseProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateArmRetailappReleaseProto', + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappReleaseUnitTest', + 'armFreeappDebug', + 'armFreeappRelease', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappReleaseUnitTest', + 'armRetailappDebug', + 'armRetailappRelease', ] as Set == protobuf.generateProtoTasks.ofFlavor('arm').collect({ it.name }) as Set assert [ - 'generateArmFreeappDebugAndroidTestProto', - 'generateArmFreeappDebugUnitTestProto', - 'generateArmFreeappDebugProto', - 'generateArmRetailappDebugAndroidTestProto', - 'generateArmRetailappDebugUnitTestProto', - 'generateArmRetailappDebugProto', - 'generateX86FreeappDebugAndroidTestProto', - 'generateX86FreeappDebugUnitTestProto', - 'generateX86FreeappDebugProto', - 'generateX86RetailappDebugAndroidTestProto', - 'generateX86RetailappDebugUnitTestProto', - 'generateX86RetailappDebugProto' + 'armFreeappDebugAndroidTest', + 'armFreeappDebugUnitTest', + 'armFreeappDebug', + 'armRetailappDebugAndroidTest', + 'armRetailappDebugUnitTest', + 'armRetailappDebug', + 'x86FreeappDebugAndroidTest', + 'x86FreeappDebugUnitTest', + 'x86FreeappDebug', + 'x86RetailappDebugAndroidTest', + 'x86RetailappDebugUnitTest', + 'x86RetailappDebug' ] as Set == protobuf.generateProtoTasks.ofBuildType('debug').collect({ it.name }) as Set assert [ - 'generateArmFreeappReleaseProto', - 'generateArmFreeappReleaseUnitTestProto', - 'generateArmRetailappReleaseProto', - 'generateArmRetailappReleaseUnitTestProto', - 'generateX86FreeappReleaseProto', - 'generateX86FreeappReleaseUnitTestProto', - 'generateX86RetailappReleaseProto', - 'generateX86RetailappReleaseUnitTestProto', + 'armFreeappRelease', + 'armFreeappReleaseUnitTest', + 'armRetailappRelease', + 'armRetailappReleaseUnitTest', + 'x86FreeappRelease', + 'x86FreeappReleaseUnitTest', + 'x86RetailappRelease', + 'x86RetailappReleaseUnitTest', ] as Set == protobuf.generateProtoTasks.ofBuildType('release').collect({ it.name }) as Set - assert ['generateX86FreeappDebugAndroidTestProto'] as Set == + assert ['x86FreeappDebugAndroidTest'] as Set == protobuf.generateProtoTasks.ofVariant('x86FreeappDebugAndroidTest').collect({ it.name }) as Set // "androidTest" sourceSet is not a flavor diff --git a/testProjectAndroidKotlinDsl/build.gradle.kts b/testProjectAndroidKotlinDsl/build.gradle.kts index 4532b415..2011786c 100644 --- a/testProjectAndroidKotlinDsl/build.gradle.kts +++ b/testProjectAndroidKotlinDsl/build.gradle.kts @@ -1,6 +1,7 @@ import com.android.build.gradle.api.BaseVariant import com.google.protobuf.gradle.id import com.google.protobuf.gradle.proto +import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskCollection plugins { id("com.android.application") @@ -152,138 +153,138 @@ afterEvaluate { } test { doLast { - val genProtoTasks = project.protobuf.generateProtoTasks + val genProtoTasks = project.protobuf.generateProtoTasks as DefaultGenerateProtoTaskCollection val genProtoTaskNames = setOf( - "generateArmFreeappDebugAndroidTestProto", - "generateArmFreeappDebugUnitTestProto", - "generateArmFreeappReleaseUnitTestProto", - "generateArmFreeappDebugProto", - "generateArmFreeappReleaseProto", - "generateArmRetailappDebugAndroidTestProto", - "generateArmRetailappDebugUnitTestProto", - "generateArmRetailappReleaseUnitTestProto", - "generateArmRetailappDebugProto", - "generateArmRetailappReleaseProto", - "generateX86FreeappDebugAndroidTestProto", - "generateX86FreeappDebugUnitTestProto", - "generateX86FreeappReleaseUnitTestProto", - "generateX86FreeappDebugProto", - "generateX86FreeappReleaseProto", - "generateX86RetailappDebugAndroidTestProto", - "generateX86RetailappDebugUnitTestProto", - "generateX86RetailappReleaseUnitTestProto", - "generateX86RetailappDebugProto", - "generateX86RetailappReleaseProto") + "armFreeappDebugAndroidTest", + "armFreeappDebugUnitTest", + "armFreeappReleaseUnitTest", + "armFreeappDebug", + "armFreeappRelease", + "armRetailappDebugAndroidTest", + "armRetailappDebugUnitTest", + "armRetailappReleaseUnitTest", + "armRetailappDebug", + "armRetailappRelease", + "x86FreeappDebugAndroidTest", + "x86FreeappDebugUnitTest", + "x86FreeappReleaseUnitTest", + "x86FreeappDebug", + "x86FreeappRelease", + "x86RetailappDebugAndroidTest", + "x86RetailappDebugUnitTest", + "x86RetailappReleaseUnitTest", + "x86RetailappDebug", + "x86RetailappRelease") assert(genProtoTaskNames == genProtoTasks.all().map { it.name }.toSet()) val genProtoTaskNamesTests = setOf( - "generateArmFreeappDebugAndroidTestProto", - "generateArmFreeappDebugUnitTestProto", - "generateArmFreeappReleaseUnitTestProto", - "generateArmRetailappDebugAndroidTestProto", - "generateArmRetailappDebugUnitTestProto", - "generateArmRetailappReleaseUnitTestProto", - "generateX86FreeappDebugAndroidTestProto", - "generateX86FreeappDebugUnitTestProto", - "generateX86FreeappReleaseUnitTestProto", - "generateX86RetailappDebugAndroidTestProto", - "generateX86RetailappDebugUnitTestProto", - "generateX86RetailappReleaseUnitTestProto") + "armFreeappDebugAndroidTest", + "armFreeappDebugUnitTest", + "armFreeappReleaseUnitTest", + "armRetailappDebugAndroidTest", + "armRetailappDebugUnitTest", + "armRetailappReleaseUnitTest", + "x86FreeappDebugAndroidTest", + "x86FreeappDebugUnitTest", + "x86FreeappReleaseUnitTest", + "x86RetailappDebugAndroidTest", + "x86RetailappDebugUnitTest", + "x86RetailappReleaseUnitTest") assert(genProtoTaskNamesTests == genProtoTasks.ofNonTest().map { it.name }.toSet()) val genProtoTaskNamesNonTests = setOf( - "generateArmFreeappDebugProto", - "generateArmFreeappReleaseProto", - "generateArmRetailappDebugProto", - "generateArmRetailappReleaseProto", - "generateX86FreeappDebugProto", - "generateX86FreeappReleaseProto", - "generateX86RetailappDebugProto", - "generateX86RetailappReleaseProto") + "armFreeappDebug", + "armFreeappRelease", + "armRetailappDebug", + "armRetailappRelease", + "x86FreeappDebug", + "x86FreeappRelease", + "x86RetailappDebug", + "x86RetailappRelease") assert(genProtoTaskNamesNonTests == genProtoTasks.ofNonTest().map { it.name }.toSet()) val genProtoTaskNamesFreeApp = setOf( - "generateArmFreeappDebugAndroidTestProto", - "generateArmFreeappDebugUnitTestProto", - "generateArmFreeappReleaseUnitTestProto", - "generateArmFreeappDebugProto", - "generateArmFreeappReleaseProto", - "generateX86FreeappDebugAndroidTestProto", - "generateX86FreeappDebugUnitTestProto", - "generateX86FreeappReleaseUnitTestProto", - "generateX86FreeappDebugProto", - "generateX86FreeappReleaseProto") + "armFreeappDebugAndroidTest", + "armFreeappDebugUnitTest", + "armFreeappReleaseUnitTest", + "armFreeappDebug", + "armFreeappRelease", + "x86FreeappDebugAndroidTest", + "x86FreeappDebugUnitTest", + "x86FreeappReleaseUnitTest", + "x86FreeappDebug", + "x86FreeappRelease") assert(genProtoTaskNamesFreeApp == genProtoTasks.ofFlavor("freeapp").map { it.name }.toSet()) val genProtoTaskNamesRetailApp = setOf( - "generateArmRetailappDebugAndroidTestProto", - "generateArmRetailappDebugUnitTestProto", - "generateArmRetailappReleaseUnitTestProto", - "generateArmRetailappDebugProto", - "generateArmRetailappReleaseProto", - "generateX86RetailappDebugAndroidTestProto", - "generateX86RetailappDebugUnitTestProto", - "generateX86RetailappReleaseUnitTestProto", - "generateX86RetailappDebugProto", - "generateX86RetailappReleaseProto") + "armRetailappDebugAndroidTest", + "armRetailappDebugUnitTest", + "armRetailappReleaseUnitTest", + "armRetailappDebug", + "armRetailappRelease", + "x86RetailappDebugAndroidTest", + "x86RetailappDebugUnitTest", + "x86RetailappReleaseUnitTest", + "x86RetailappDebug", + "x86RetailappRelease") assert(genProtoTaskNamesRetailApp == genProtoTasks.ofFlavor("retailapp").map { it.name }.toSet()) val genProtoTaskNamesX86 = setOf( - "generateX86FreeappDebugAndroidTestProto", - "generateX86FreeappDebugUnitTestProto", - "generateX86FreeappReleaseUnitTestProto", - "generateX86FreeappDebugProto", - "generateX86FreeappReleaseProto", - "generateX86RetailappDebugAndroidTestProto", - "generateX86RetailappDebugUnitTestProto", - "generateX86RetailappReleaseUnitTestProto", - "generateX86RetailappDebugProto", - "generateX86RetailappReleaseProto") + "x86FreeappDebugAndroidTest", + "x86FreeappDebugUnitTest", + "x86FreeappReleaseUnitTest", + "x86FreeappDebug", + "x86FreeappRelease", + "x86RetailappDebugAndroidTest", + "x86RetailappDebugUnitTest", + "x86RetailappReleaseUnitTest", + "x86RetailappDebug", + "x86RetailappRelease") assert(genProtoTaskNamesX86 == genProtoTasks.ofFlavor("x86").map { it.name }.toSet()) val genProtoTaskNamesArm = setOf( - "generateArmFreeappDebugAndroidTestProto", - "generateArmFreeappDebugUnitTestProto", - "generateArmFreeappReleaseUnitTestProto", - "generateArmFreeappDebugProto", - "generateArmFreeappReleaseProto", - "generateArmRetailappDebugAndroidTestProto", - "generateArmRetailappDebugUnitTestProto", - "generateArmRetailappReleaseUnitTestProto", - "generateArmRetailappDebugProto", - "generateArmRetailappReleaseProto" + "armFreeappDebugAndroidTest", + "armFreeappDebugUnitTest", + "armFreeappReleaseUnitTest", + "armFreeappDebug", + "armFreeappRelease", + "armRetailappDebugAndroidTest", + "armRetailappDebugUnitTest", + "armRetailappReleaseUnitTest", + "armRetailappDebug", + "armRetailappRelease" ) assert(genProtoTaskNamesArm == genProtoTasks.ofFlavor("arm").map { it.name }.toSet()) val genProtoTaskNamesDebug = setOf( - "generateArmFreeappDebugAndroidTestProto", - "generateArmFreeappDebugUnitTestProto", - "generateArmFreeappDebugProto", - "generateArmRetailappDebugAndroidTestProto", - "generateArmRetailappDebugUnitTestProto", - "generateArmRetailappDebugProto", - "generateX86FreeappDebugAndroidTestProto", - "generateX86FreeappDebugUnitTestProto", - "generateX86FreeappDebugProto", - "generateX86RetailappDebugAndroidTestProto", - "generateX86RetailappDebugUnitTestProto", - "generateX86RetailappDebugProto") + "armFreeappDebugAndroidTest", + "armFreeappDebugUnitTest", + "armFreeappDebug", + "armRetailappDebugAndroidTest", + "armRetailappDebugUnitTest", + "armRetailappDebug", + "x86FreeappDebugAndroidTest", + "x86FreeappDebugUnitTest", + "x86FreeappDebug", + "x86RetailappDebugAndroidTest", + "x86RetailappDebugUnitTest", + "x86RetailappDebug") assert(genProtoTaskNamesDebug == genProtoTasks.ofBuildType("debug").map { it.name }.toSet()) val genProtoTaskNamesRelease = setOf( - "generateArmFreeappReleaseProto", - "generateArmFreeappReleaseUnitTestProto", - "generateArmRetailappReleaseProto", - "generateArmRetailappReleaseUnitTestProto", - "generateX86FreeappReleaseProto", - "generateX86FreeappReleaseUnitTestProto", - "generateX86RetailappReleaseProto", - "generateX86RetailappReleaseUnitTestProto") + "armFreeappRelease", + "armFreeappReleaseUnitTest", + "armRetailappRelease", + "armRetailappReleaseUnitTest", + "x86FreeappRelease", + "x86FreeappReleaseUnitTest", + "x86RetailappRelease", + "x86RetailappReleaseUnitTest") assert(genProtoTaskNamesRelease == genProtoTasks.ofBuildType("release").map { it.name }.toSet()) - assert(setOf("generateX86FreeappDebugAndroidTestProto") == + assert(setOf("x86FreeappDebugAndroidTest") == genProtoTasks.ofVariant("x86FreeappDebugAndroidTest").map { it.name }.toSet()) android.applicationVariants.forEach { variant -> diff --git a/testProjectBase/build_base.gradle b/testProjectBase/build_base.gradle index 9ef93a96..95804688 100644 --- a/testProjectBase/build_base.gradle +++ b/testProjectBase/build_base.gradle @@ -81,10 +81,10 @@ def assertFileExists(boolean exists, String path) { } test.doLast { - assert ['generateProto', 'generateGrpcProto', 'generateTestProto'] as Set == - protobuf.generateProtoTasks.all().collect({ it.name }) as Set + assert ['main', 'grpc', 'test'] as Set == + protobuf.generateProtoTasks.all().collect({ it.name }) as Set - assert ['generateProto'] as Set == protobuf.generateProtoTasks.ofSourceSet('main').collect({ it.name }) as Set + assert ['main'] as Set == protobuf.generateProtoTasks.ofSourceSet('main').collect({ it.name }) as Set assert [] as Set == protobuf.generateProtoTasks.ofTest().collect({ it.name }) as Set assert [] as Set == protobuf.generateProtoTasks.ofNonTest().collect({ it.name }) as Set assert [] as Set == protobuf.generateProtoTasks.ofFlavor('flavor-name').collect({ it.name }) as Set diff --git a/testProjectKotlinDslBase/build.gradle.kts b/testProjectKotlinDslBase/build.gradle.kts index 82c8562f..26a3cdd5 100644 --- a/testProjectKotlinDslBase/build.gradle.kts +++ b/testProjectKotlinDslBase/build.gradle.kts @@ -1,6 +1,7 @@ import com.google.protobuf.gradle.* import org.gradle.api.internal.HasConvention import org.gradle.kotlin.dsl.provider.gradleKotlinDslOf +import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskCollection plugins { java @@ -84,7 +85,7 @@ tasks { "test"{ doLast{ - val generateProtoTasks = project.protobuf.generateProtoTasks + val generateProtoTasks = project.protobuf.generateProtoTasks as DefaultGenerateProtoTaskCollection val generateProtoTaskNames = generateProtoTasks.all().map { it.name }.toSet() val generateProtoTaskNamesMain = generateProtoTasks.ofSourceSet("main").map { it.name }.toSet() From 5672e23b4d2b271543468d357d7bb75c482eb8ec Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 19:13:58 +0300 Subject: [PATCH 10/16] Fix tests again --- testProjectAndroidBase/build_base.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testProjectAndroidBase/build_base.gradle b/testProjectAndroidBase/build_base.gradle index c68d64cf..49956ccd 100644 --- a/testProjectAndroidBase/build_base.gradle +++ b/testProjectAndroidBase/build_base.gradle @@ -258,7 +258,7 @@ afterEvaluate { 'x86RetailappReleaseUnitTest', ] as Set == protobuf.generateProtoTasks.ofBuildType('release').collect({ it.name }) as Set - assert ['x86FreeappDebugAndroidTestProto'] as Set == + assert ['x86FreeappDebugAndroidTest'] as Set == protobuf.generateProtoTasks.ofVariant('x86FreeappDebugAndroidTest').collect({ it.name }) as Set // "androidTest" sourceSet is not a flavor From 835935cec12165036d6c872cc711a31186876f92 Mon Sep 17 00:00:00 2001 From: rougsig Date: Wed, 25 Jan 2023 20:12:16 +0300 Subject: [PATCH 11/16] Do not use GenerateProtoTask as source of output dirs information --- build.gradle | 2 +- .../protobuf/gradle/GenerateProtoTask.groovy | 73 ++----------------- .../protobuf/gradle/ProtobufPlugin.groovy | 48 ++++++------ .../DefaultGenerateProtoTaskSpec.groovy | 15 ++++ .../internal/GenerateProtoTaskSpecExt.groovy | 29 ++++++++ .../gradle/internal/PluginSpecExt.groovy | 14 ++++ .../gradle/internal/ProjectExt.groovy | 10 +++ .../gradle/tasks/GenerateProtoTaskSpec.groovy | 9 +++ 8 files changed, 112 insertions(+), 88 deletions(-) create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/GenerateProtoTaskSpecExt.groovy create mode 100644 src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecExt.groovy diff --git a/build.gradle b/build.gradle index 6e9e027f..787b6819 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ configurations { } dependencies { - compileOnly "com.android.tools.build:gradle:4.1.0" + compileOnly "com.android.tools.build:gradle:4.2.2" compileOnly "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.7.22" implementation 'com.google.gradle:osdetector-gradle-plugin:1.7.2' diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index f2559ecd..e102e5be 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -31,6 +31,7 @@ package com.google.protobuf.gradle import static java.nio.charset.StandardCharsets.US_ASCII +import com.google.protobuf.gradle.internal.PluginSpecExt import com.google.protobuf.gradle.internal.DefaultGenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.PluginSpec @@ -38,13 +39,11 @@ import org.gradle.api.file.DeleteSpec import org.gradle.api.provider.Property import org.gradle.api.tasks.Nested import groovy.transform.CompileStatic -import groovy.transform.PackageScope import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.gradle.api.file.ProjectLayout -import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.LogLevel import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider @@ -54,7 +53,6 @@ import org.gradle.api.tasks.IgnoreEmptyDirectories import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.SkipWhenEmpty @@ -88,12 +86,6 @@ abstract class GenerateProtoTask extends DefaultTask { private final ProjectLayout projectLayout = project.layout private final ToolsLocator toolsLocator = project.extensions.findByType(ProtobufExtension).tools - // These fields are set by the Protobuf plugin only when initializing the - // task. Ideally they should be final fields, but Gradle task cannot have - // constructor arguments. We use the initializing flag to prevent users from - // accidentally modifying them. - private Provider outputBaseDir - @SuppressWarnings("AbstractClassWithPublicConstructor") // required to configure properties convention values GenerateProtoTask() { this.spec.convention(new DefaultGenerateProtoTaskSpec(this.project.objects)) @@ -190,16 +182,6 @@ abstract class GenerateProtoTask extends DefaultTask { return java.path } - void setOutputBaseDir(Provider outputBaseDir) { - Preconditions.checkState(this.outputBaseDir == null, 'outputBaseDir is already set') - this.outputBaseDir = outputBaseDir - } - - @OutputDirectory - String getOutputBaseDir() { - return outputBaseDir.get() - } - @SkipWhenEmpty @PathSensitive(PathSensitivity.RELATIVE) @IgnoreEmptyDirectories @@ -259,7 +241,7 @@ abstract class GenerateProtoTask extends DefaultTask { "requested descriptor path but descriptor generation is off") } return spec.descriptorSetOptions.path != null ? spec.descriptorSetOptions.path - : "${outputBaseDir.get()}/descriptor_set.desc" + : "${spec.outputDir.get()}/descriptor_set.desc" } @Inject @@ -293,60 +275,19 @@ abstract class GenerateProtoTask extends DefaultTask { // protoc invocation logic //=========================================================================== - String getOutputDir(PluginSpec plugin) { - return "${outputBaseDir.get()}/${plugin.outputSubDir}" - } - - /** - * Returns a {@code SourceDirectorySet} representing the generated source - * directories. - */ - @Internal - @Deprecated - SourceDirectorySet getOutputSourceDirectorySet() { - String srcSetName = "generate-proto-" + name - SourceDirectorySet srcSet - srcSet = objectFactory.sourceDirectorySet(srcSetName, srcSetName) - srcSet.srcDirs objectFactory.fileCollection().builtBy(this).from(providerFactory.provider { - getOutputSourceDirectories() - }) - return srcSet - } - - @Internal - @PackageScope - Collection getOutputSourceDirectories() { - GenerateProtoTaskSpec spec = requireSpec() - - Collection srcDirs = [] - spec.builtins.each { builtin -> - File dir = new File(getOutputDir(builtin)) - if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { - srcDirs.add(dir) - } - } - spec.plugins.each { plugin -> - File dir = new File(getOutputDir(plugin)) - if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { - srcDirs.add(dir) - } - } - return srcDirs - } - @TaskAction void compile() { GenerateProtoTaskSpec spec = requireSpec() copyActionFacade.delete { DeleteSpec deleteSpec -> - deleteSpec.delete(outputBaseDir) + deleteSpec.delete(spec.outputDir) } // Sort to ensure generated descriptors have a canonical representation // to avoid triggering unnecessary rebuilds downstream List protoFiles = sourceDirs.asFileTree.files.sort() [spec.builtins, spec.plugins]*.forEach { PluginSpec plugin -> - String outputPath = getOutputDir(plugin) + String outputPath = PluginSpecExt.getOutputDir(plugin, spec.outputDir.get()) File outputDir = new File(outputPath) // protoc is capable of output generated files directly to a JAR file // or ZIP archive if the output location ends with .jar/.zip @@ -370,7 +311,8 @@ abstract class GenerateProtoTask extends DefaultTask { // Handle code generation built-ins spec.builtins.each { builtin -> String outPrefix = makeOptionsPrefix(builtin.options) - baseCmd += "--${builtin.name}_out=${outPrefix}${getOutputDir(builtin)}".toString() + String outputBuiltinPath = PluginSpecExt.getOutputDir(builtin, spec.outputDir.get()) + baseCmd += "--${builtin.name}_out=${outPrefix}${outputBuiltinPath}".toString() } Map executableLocations = toolsLocator.plugins.asMap @@ -384,7 +326,8 @@ abstract class GenerateProtoTask extends DefaultTask { logger.warn "protoc plugin '${name}' not defined. Trying to use 'protoc-gen-${name}' from system path" } String pluginOutPrefix = makeOptionsPrefix(plugin.options) - baseCmd += "--${name}_out=${pluginOutPrefix}${getOutputDir(plugin)}".toString() + String outputPluginPath = PluginSpecExt.getOutputDir(plugin, spec.outputDir.get()) + baseCmd += "--${name}_out=${pluginOutPrefix}${outputPluginPath}".toString() } if (spec.generateDescriptorSet) { diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy index 5246e235..0a3f4c75 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy @@ -34,7 +34,9 @@ import com.android.build.gradle.api.TestVariant import com.android.build.gradle.api.UnitTestVariant import com.android.builder.model.SourceProvider import com.google.protobuf.gradle.internal.DefaultProtoSourceSet +import com.google.protobuf.gradle.internal.GenerateProtoTaskSpecExt import com.google.protobuf.gradle.internal.ProjectExt +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.ProtoSourceSet import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic @@ -248,9 +250,7 @@ class ProtobufPlugin implements Plugin { protoVariant.sourceSet = sourceSet.name protoVariant.isTest = Utils.isTest(sourceSet.name) protoVariant.generateProtoTaskSpec.builtins.maybeCreate("java") - Provider generateProtoTask = addGenerateProtoTask(protoSourceSet) { - it.spec.set(protoVariant.generateProtoTaskSpec) - } + addGenerateProtoTask(protoVariant, protoSourceSet) sourceSet.java.srcDirs(protoSourceSet.output) @@ -263,12 +263,13 @@ class ProtobufPlugin implements Plugin { } postConfigure.add { + GenerateProtoTaskSpec spec = protoVariant.generateProtoTaskSpec + Collection outputDirs = GenerateProtoTaskSpecExt.getOutputSourceDirectories(spec) + project.plugins.withId("eclipse") { // This is required because the intellij/eclipse plugin does not allow adding source directories // that do not exist. The intellij/eclipse config files should be valid from the start. - generateProtoTask.get().getOutputSourceDirectories().each { File outputDir -> - outputDir.mkdirs() - } + outputDirs.each { File outputDir -> outputDir.mkdirs() } } project.plugins.withId("idea") { @@ -278,9 +279,7 @@ class ProtobufPlugin implements Plugin { } Utils.addToIdeSources(project, isTest, project.files(extractProtosTask).singleFile, true) Utils.addToIdeSources(project, isTest, project.files(extractIncludeProtosTask).singleFile, true) - generateProtoTask.get().getOutputSourceDirectories().each { File outputDir -> - Utils.addToIdeSources(project, isTest, outputDir, true) - } + outputDirs.each { File outputDir -> Utils.addToIdeSources(project, isTest, outputDir, true) } } } } @@ -326,9 +325,7 @@ class ProtobufPlugin implements Plugin { protoVariant.isTest = isTestVariant protoVariant.flavors = variant.productFlavors.collect { it.name } as Set protoVariant.buildType = variant.hasProperty('buildType') ? variant.buildType.name : null - Provider generateProtoTask = addGenerateProtoTask(variantSourceSet) { - it.spec.set(protoVariant.generateProtoTaskSpec) - } + Provider generateProtoTask = addGenerateProtoTask(protoVariant, variantSourceSet) if (project.android.hasProperty('libraryVariants')) { // Include source proto files in the compiled archive, so that proto files from @@ -340,15 +337,22 @@ class ProtobufPlugin implements Plugin { } } postConfigure.add { + Collection outputDirs = + GenerateProtoTaskSpecExt.getOutputSourceDirectories(protoVariant.generateProtoTaskSpec) + // This cannot be called once task execution has started. - variant.registerJavaGeneratingTask(generateProtoTask.get(), generateProtoTask.get().outputSourceDirectories) + if (ProjectExt.isAgpAbove422(project)) { + variant.registerJavaGeneratingTask(generateProtoTask, outputDirs) + } else { + variant.registerJavaGeneratingTask(generateProtoTask.get(), outputDirs) + } project.plugins.withId("org.jetbrains.kotlin.android") { project.afterEvaluate { String compileKotlinTaskName = Utils.getKotlinAndroidCompileTaskName(project, variant.name) project.tasks.named(compileKotlinTaskName, KotlinCompile) { KotlinCompile task -> task.dependsOn(generateProtoTask) - task.source(generateProtoTask.get().outputSourceDirectories) + task.source(outputDirs) } } } @@ -366,19 +370,18 @@ class ProtobufPlugin implements Plugin { * for; for Android it's the collection of sourceSets that the variant includes. */ private Provider addGenerateProtoTask( - ProtoSourceSet protoSourceSet, - Action configureAction + ProtoVariant protoVariant, + ProtoSourceSet protoSourceSet ) { String sourceSetName = protoSourceSet.name String taskName = 'generate' + Utils.getSourceSetSubstringForTaskNames(sourceSetName) + 'Proto' String defaultGeneratedFilesBaseDir = protobufExtension.defaultGeneratedFilesBaseDir Provider generatedFilesBaseDirProvider = protobufExtension.generatedFilesBaseDirProperty + protoVariant.generateProtoTaskSpec.outputDir.set("${defaultGeneratedFilesBaseDir}/${sourceSetName}".toString()) Provider task = project.tasks.register(taskName, GenerateProtoTask) { + it.spec.set(protoVariant.generateProtoTaskSpec) CopyActionFacade copyActionFacade = CopyActionFacade.Loader.create(it.project, it.objectFactory) it.description = "Compiles Proto source for '${sourceSetName}'".toString() - it.outputBaseDir = project.providers.provider { - "${defaultGeneratedFilesBaseDir}/${sourceSetName}".toString() - } it.addSourceDirs(protoSourceSet.proto) it.addIncludeDir(protoSourceSet.proto.sourceDirectories) it.addIncludeDir(protoSourceSet.includeProtoDirs) @@ -390,13 +393,14 @@ class ProtobufPlugin implements Plugin { // Purposefully don't wire this up to outputs, as it can be mixed with other files. copyActionFacade.copy { CopySpec spec -> spec.includeEmptyDirs = false - spec.from(it.outputBaseDir) + spec.from(protoVariant.generateProtoTaskSpec.outputDir.get()) spec.into("${generatedFilesBaseDir}/${sourceSetName}") } } - configureAction.execute(it) } - protoSourceSet.output.from(task.map { GenerateProtoTask it -> it.outputSourceDirectories }) + protoSourceSet.output.from(task.map { + GenerateProtoTaskSpecExt.getOutputSourceDirectories(protoVariant.generateProtoTaskSpec) + }) return task } diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy index 98f69216..12256076 100644 --- a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultGenerateProtoTaskSpec.groovy @@ -8,6 +8,8 @@ import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectFactory import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.util.ConfigureUtil @CompileStatic @@ -16,15 +18,28 @@ class DefaultGenerateProtoTaskSpec implements GenerateProtoTaskSpec { private final NamedDomainObjectContainer plugins private final NamedDomainObjectContainer builtins private final DescriptorSetSpec descriptorSetSpec + private final Property outputDir private boolean generateDescriptorSet = false DefaultGenerateProtoTaskSpec(ObjectFactory objects) { NamedDomainObjectFactory pluginSpecObjectFactory = new PluginSpecObjectFactory(objects) this.plugins = objects.domainObjectContainer(PluginSpec, pluginSpecObjectFactory) this.builtins = objects.domainObjectContainer(PluginSpec, pluginSpecObjectFactory) + this.outputDir = objects.property(String) this.descriptorSetSpec = new DefaultDescriptorSetSpec(objects) } + @Override + Property getOutputDir() { + return this.outputDir + } + + @Override + @Deprecated + void setOutputBaseDir(Provider outputBaseDir) { + this.outputDir.set(outputBaseDir) + } + @Override boolean getGenerateDescriptorSet() { return generateDescriptorSet diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/GenerateProtoTaskSpecExt.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/GenerateProtoTaskSpecExt.groovy new file mode 100644 index 00000000..d159418f --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/GenerateProtoTaskSpecExt.groovy @@ -0,0 +1,29 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec +import groovy.transform.CompileStatic + +@CompileStatic +class GenerateProtoTaskSpecExt { + private GenerateProtoTaskSpecExt() { + } + + static Collection getOutputSourceDirectories(GenerateProtoTaskSpec spec) { + Collection srcDirs = [] + + spec.builtins.each { builtin -> + File dir = new File(PluginSpecExt.getOutputDir(builtin, spec.outputDir.get())) + if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { + srcDirs.add(dir) + } + } + spec.plugins.each { plugin -> + File dir = new File(PluginSpecExt.getOutputDir(plugin, spec.outputDir.get())) + if (!dir.name.endsWith(".zip") && !dir.name.endsWith(".jar")) { + srcDirs.add(dir) + } + } + + return srcDirs + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecExt.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecExt.groovy new file mode 100644 index 00000000..f51580e9 --- /dev/null +++ b/src/main/groovy/com/google/protobuf/gradle/internal/PluginSpecExt.groovy @@ -0,0 +1,14 @@ +package com.google.protobuf.gradle.internal + +import com.google.protobuf.gradle.tasks.PluginSpec +import groovy.transform.CompileStatic + +@CompileStatic +class PluginSpecExt { + private PluginSpecExt() { + } + + static String getOutputDir(PluginSpec plugin, String outputBaseDir) { + return "${outputBaseDir}/${plugin.outputSubDir}" + } +} diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy index b1a261b5..2583b238 100644 --- a/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy @@ -65,4 +65,14 @@ class ProjectExt { (android as TestedExtension).getUnitTestVariants().all(action) } } + + static boolean isAgpAbove422(Project project) { + // Different type between agp 4.2.2 and 7.0.0 + // androidComponents exists since agp 4.2 + Object androidComponents = project.extensions.findByName("androidComponents") + + // Below 4.2 androidComponents extension does not exists + // Below 7.0.0 androidComponents extension does not have pluginVersion field + return androidComponents != null && androidComponents.hasProperty("pluginVersion") + } } diff --git a/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy index 763d417b..bdadac14 100644 --- a/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/tasks/GenerateProtoTaskSpec.groovy @@ -3,13 +3,22 @@ package com.google.protobuf.gradle.tasks import groovy.transform.CompileStatic import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Input import org.gradle.api.tasks.Nested +import org.gradle.api.tasks.OutputDirectory @CompileStatic @SuppressWarnings("JUnitPublicNonTestMethod") // it is not a test class interface GenerateProtoTaskSpec { + @OutputDirectory + Property getOutputDir() + + @Deprecated + void setOutputBaseDir(Provider outputBaseDir) + /** * If true, will set the protoc flag * --descriptor_set_out="${outputBaseDir}/descriptor_set.desc" From 4b4d226bd09fa3d94cce423b8c64fb23a858106a Mon Sep 17 00:00:00 2001 From: rougsig Date: Thu, 26 Jan 2023 01:17:43 +0300 Subject: [PATCH 12/16] Fix codenarc issues --- .../com/google/protobuf/gradle/internal/ProjectExt.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy index 2583b238..8045b8e2 100644 --- a/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/internal/ProjectExt.groovy @@ -70,7 +70,7 @@ class ProjectExt { // Different type between agp 4.2.2 and 7.0.0 // androidComponents exists since agp 4.2 Object androidComponents = project.extensions.findByName("androidComponents") - + // Below 4.2 androidComponents extension does not exists // Below 7.0.0 androidComponents extension does not have pluginVersion field return androidComponents != null && androidComponents.hasProperty("pluginVersion") From 8d0e1fd62f129a3e08e8d75a8c85be620f1c1cf1 Mon Sep 17 00:00:00 2001 From: rougsig Date: Thu, 26 Jan 2023 01:25:20 +0300 Subject: [PATCH 13/16] Do not use project in GenerateProtoTask constructor https://docs.gradle.org/7.6/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution --- .../groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index e102e5be..0c929456 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -88,7 +88,7 @@ abstract class GenerateProtoTask extends DefaultTask { @SuppressWarnings("AbstractClassWithPublicConstructor") // required to configure properties convention values GenerateProtoTask() { - this.spec.convention(new DefaultGenerateProtoTaskSpec(this.project.objects)) + this.spec.convention(new DefaultGenerateProtoTaskSpec(objectFactory)) } // protoc allows you to prefix comma-delimited options to the path in From 536b166c88128881520bd2aade0d8b0bbed7f536 Mon Sep 17 00:00:00 2001 From: rougsig Date: Thu, 26 Jan 2023 01:49:10 +0300 Subject: [PATCH 14/16] Do not use project in any GenerateProtoTask @Input field https://docs.gradle.org/7.6/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution --- .../google/protobuf/gradle/ProtobufExtension.groovy | 2 +- .../gradle/internal/DefaultProtoVariant.groovy | 8 +++----- .../gradle/internal/ProtoVariantObjectFactory.groovy | 10 +++++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy index b1d62a9a..399d5c79 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy @@ -69,7 +69,7 @@ abstract class ProtobufExtension { ObjectFactory objects = project.objects this.sourceSets = project.objects.domainObjectContainer(ProtoSourceSet, new ProtoSourceSetObjectFactory(objects)) - this.variants = project.objects.domainObjectContainer(ProtoVariant, new ProtoVariantObjectFactory(project)) + this.variants = project.objects.domainObjectContainer(ProtoVariant, new ProtoVariantObjectFactory(objects)) } NamedDomainObjectContainer getSourceSets() { diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy index 4cc18443..3863c2a4 100644 --- a/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/internal/DefaultProtoVariant.groovy @@ -3,11 +3,10 @@ package com.google.protobuf.gradle.internal import com.google.protobuf.gradle.tasks.GenerateProtoTaskSpec import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic -import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory @CompileStatic class DefaultProtoVariant implements ProtoVariant { - private final Project project private final GenerateProtoTaskSpec generateProtoTaskSpec private final String name private String sourceSet @@ -15,10 +14,9 @@ class DefaultProtoVariant implements ProtoVariant { private boolean isTest private Set flavors - DefaultProtoVariant(String name, Project project) { - this.project = project + DefaultProtoVariant(String name, ObjectFactory objects) { this.name = name - this.generateProtoTaskSpec = new DefaultGenerateProtoTaskSpec(project.objects) + this.generateProtoTaskSpec = new DefaultGenerateProtoTaskSpec(objects) this.flavors = [] as Set } diff --git a/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy index 36c4d754..58c728ea 100644 --- a/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/internal/ProtoVariantObjectFactory.groovy @@ -3,18 +3,18 @@ package com.google.protobuf.gradle.internal import com.google.protobuf.gradle.tasks.ProtoVariant import groovy.transform.CompileStatic import org.gradle.api.NamedDomainObjectFactory -import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory @CompileStatic class ProtoVariantObjectFactory implements NamedDomainObjectFactory { - private final Project project + private final ObjectFactory objects - ProtoVariantObjectFactory(Project project) { - this.project = project + ProtoVariantObjectFactory(ObjectFactory objects) { + this.objects = objects } @Override ProtoVariant create(String name) { - return new DefaultProtoVariant(name, project) + return new DefaultProtoVariant(name, objects) } } From 1d4eac5e329a838a3fa8369d65791bfc51d8def2 Mon Sep 17 00:00:00 2001 From: rougsig Date: Fri, 27 Jan 2023 17:31:00 +0300 Subject: [PATCH 15/16] Add android task configuration avoidance test --- .../gradle/ProtobufAndroidPluginTest.groovy | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy index a281e8cc..16047efa 100644 --- a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy +++ b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy @@ -173,4 +173,36 @@ class ProtobufAndroidPluginTest extends Specification { agpVersion << ANDROID_PLUGIN_VERSION.takeRight(1) gradleVersion << GRADLE_VERSION.takeRight(1) } + + @Unroll + void "tests android build should be without eager task creation [android #agpVersion, gradle #gradleVersion]"() { + given: "a project with android plugin" + File mainProjectDir = ProtobufPluginTestHelper.projectBuilder("singleModuleAndroidProject") + .copyDirs('testProjectAndroid', 'testProjectAndroidBare') + .withAndroidPlugin(agpVersion) + .build() + new File(mainProjectDir, "build.gradle") << """ + |tasks + | // Lifecycle 'clean' task always eager + | // https://github.com/gradle/gradle/issues/20864 + | .matching { it.name != "help" && it.name != "clean" } + | .configureEach { throw new IllegalStateException("\$it was eagerly created") } + """.stripMargin() + + when: "evaluate project by help task" + BuildResult result = ProtobufPluginTestHelper.getAndroidGradleRunner( + mainProjectDir, + gradleVersion, + agpVersion, + "help" + ).build() + + then: "it succeed" + println result.output + assert result.task(":help").outcome == TaskOutcome.SUCCESS + + where: + agpVersion << ANDROID_PLUGIN_VERSION.takeRight(1) + gradleVersion << GRADLE_VERSION.takeRight(1) + } } From e076fa3616985280b56c60cb0c74a5ff34c4286d Mon Sep 17 00:00:00 2001 From: rougsig Date: Fri, 27 Jan 2023 18:33:17 +0300 Subject: [PATCH 16/16] Fix codenarc issues --- .../com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy index 16047efa..701488a7 100644 --- a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy +++ b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy @@ -198,7 +198,6 @@ class ProtobufAndroidPluginTest extends Specification { ).build() then: "it succeed" - println result.output assert result.task(":help").outcome == TaskOutcome.SUCCESS where: