Skip to content

Commit

Permalink
Emulate and deprecate generatedFilesBaseDir (#636)
Browse files Browse the repository at this point in the history
Fixes #33 for users not changing generatedFilesBaseDir. Stop documenting
generatedFilesBaseDir since it produces poor results, but keep it
functional with its existing Copy semantics. Fixes #332

This deprecates the setter, but I don't know how to make this trigger a warning,
for either Groovy and Kotlin. Both seem to ignore it.

Turn off UnnecessaryObjectReferences because it isn't providing value.
  • Loading branch information
ejona86 authored Jan 5, 2023
1 parent 2fbe179 commit 278f21b
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 62 deletions.
48 changes: 7 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,10 @@ task.plugins {

```gradle
protobuf {
generatedFilesBaseDir = "$projectDir/generated"
generateProtoTasks {
all().each { task ->
task.builtins {
// Generates Python code in the output folder:
// Generates Python code
python { }
// If you wish to avoid generating Java files:
Expand Down Expand Up @@ -410,7 +408,7 @@ protobuf {
```gradle
{ task ->
// If true, will generate a descriptor_set.desc file under
// $generatedFilesBaseDir/$sourceSet. Default is false.
// task.outputBaseDir. Default is false.
// See --descriptor_set_out in protoc documentation about what it is.
task.generateDescriptorSet = true
Expand All @@ -430,19 +428,11 @@ protobuf {

#### Change where files are generated

By default generated Java files are under
``$generatedFilesBaseDir/$sourceSet/$builtinPluginName``, where
``$generatedFilesBaseDir`` is ``$buildDir/generated/source/proto`` by default,
and is configurable. E.g.,

```gradle
protobuf {
...
 generatedFilesBaseDir = "$projectDir/src/generated"
}
```
Generated files are under `task.outputBaseDir` with a subdirectory per
builtin and plugin. This produces a folder structure of
``$buildDir/generated/source/proto/$sourceSet/$builtinPluginName``.

The subdirectory name, which is by default ``$builtinPluginName``, can also be
The subdirectory name, which is by default ``$builtinPluginName``, can be
changed by setting the ``outputSubDir`` property in the ``builtins`` or
``plugins`` block of a task configuration within ``generateProtoTasks`` block
(see previous section). E.g.,
Expand All @@ -451,8 +441,7 @@ changed by setting the ``outputSubDir`` property in the ``builtins`` or
{ task ->
task.plugins {
grpc {
// Write the generated files under
// "$generatedFilesBaseDir/$sourceSet/grpcjava"
// Use subdirectory 'grpcjava' instead of the default 'grpc'
outputSubDir = 'grpcjava'
}
}
Expand Down Expand Up @@ -521,29 +510,6 @@ This plugin integrates with the ``idea`` plugin and automatically
registers the proto files and generated Java code as sources.


```gradle
apply plugin: 'idea'
protobuf {
...
generatedFilesBaseDir = "$projectDir/gen"
}
clean {
delete protobuf.generatedFilesBaseDir
}
idea {
module {
// proto files and generated Java files are automatically added as
// source dirs.
// If you have additional sources, add them here:
sourceDirs += file("/path/to/other/sources");
}
}
```


## Testing the plugin

``testProject*`` are testing projects that uses this plugin to compile
Expand Down
4 changes: 4 additions & 0 deletions config/codenarc/codenarc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<ruleset-ref path='rulesets/unnecessary.xml'>
<exclude name="UnnecessaryCollectCall"/>
<exclude name="UnnecessaryGetter"/>

<exclude name="UnnecessaryGString"/>
<exclude name="UnnecessarySetter"/>
<exclude name="UnnecessaryPublicModifier"/>
<exclude name="UnnecessaryReturnKeyword"/>

<!-- Poor suggestion when using static typing -->
<exclude name="UnnecessaryObjectReferences"/>
</ruleset-ref>
</ruleset>
25 changes: 25 additions & 0 deletions src/main/groovy/com/google/protobuf/gradle/CopyActionFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.DeleteSpec;
import org.gradle.api.file.FileSystemOperations;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.tasks.WorkResult;
import org.gradle.util.GradleVersion;

import javax.inject.Inject;

Expand All @@ -46,6 +49,18 @@
@CompileStatic
interface CopyActionFacade {
WorkResult copy(Action<? super CopySpec> var1);
WorkResult delete(Action<? super DeleteSpec> action);

@CompileStatic
final class Loader {
public static CopyActionFacade create(Project project, ObjectFactory objectFactory) {
if (GradleVersion.current().compareTo(GradleVersion.version("6.0")) >= 0) {
// Use object factory to instantiate as that will inject the necessary service.
return objectFactory.newInstance(CopyActionFacade.FileSystemOperationsBased.class);
}
return new CopyActionFacade.ProjectBased(project);
}
}

@CompileStatic
class ProjectBased implements CopyActionFacade {
Expand All @@ -59,6 +74,11 @@ public ProjectBased(Project project) {
public WorkResult copy(Action<? super CopySpec> action) {
return project.copy(action);
}

@Override
public WorkResult delete(Action<? super DeleteSpec> action) {
return project.delete(action);
}
}

@CompileStatic
Expand All @@ -70,5 +90,10 @@ abstract class FileSystemOperationsBased implements CopyActionFacade {
public WorkResult copy(Action<? super CopySpec> action) {
return getFileSystemOperations().copy(action);
}

@Override
public WorkResult delete(Action<? super DeleteSpec> action) {
return getFileSystemOperations().delete(action);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public abstract class GenerateProtoTask extends DefaultTask {
static final int CMD_ARGUMENT_EXTRA_LENGTH = 3
private static final String JAR_SUFFIX = ".jar"

private final CopyActionFacade copyActionFacade = CopyActionFacade.Loader.create(project, objectFactory)
// include dirs are passed to the '-I' option of protoc. They contain protos
// that may be "imported" from the source protos, but will not be compiled.
private final ConfigurableFileCollection includeDirs = objectFactory.fileCollection()
Expand Down Expand Up @@ -587,6 +588,9 @@ public abstract class GenerateProtoTask extends DefaultTask {
void compile() {
Preconditions.checkState(state == State.FINALIZED, 'doneConfig() has not been called')

copyActionFacade.delete { spec ->
spec.delete(outputBaseDir)
}
// Sort to ensure generated descriptors have a canonical representation
// to avoid triggering unnecessary rebuilds downstream
List<File> protoFiles = sourceDirs.asFileTree.files.sort()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import groovy.transform.TypeCheckingMode
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.TaskCollection

/**
Expand All @@ -52,18 +53,16 @@ abstract class ProtobufExtension {
private final ArrayList<Action<GenerateProtoTaskCollection>> taskConfigActions
private final NamedDomainObjectContainer<ProtoSourceSet> sourceSets

/**
* The base directory of generated files. The default is
* "${project.buildDir}/generated/source/proto".
*/
private String generatedFilesBaseDir
@PackageScope
final String defaultGeneratedFilesBaseDir

public ProtobufExtension(final Project project) {
this.project = project
this.tasks = new GenerateProtoTaskCollection(project)
this.tools = new ToolsLocator(project)
this.taskConfigActions = []
this.generatedFilesBaseDir = "${project.buildDir}/generated/source/proto"
this.defaultGeneratedFilesBaseDir = "${project.buildDir}/generated/source/proto"
this.generatedFilesBaseDirProperty.convention(defaultGeneratedFilesBaseDir)
this.sourceSets = project.objects.domainObjectContainer(ProtoSourceSet) { String name ->
new DefaultProtoSourceSet(name, project.objects)
}
Expand All @@ -80,13 +79,21 @@ abstract class ProtobufExtension {
}

String getGeneratedFilesBaseDir() {
return generatedFilesBaseDir
return generatedFilesBaseDirProperty.get()
}

@Deprecated
void setGeneratedFilesBaseDir(String generatedFilesBaseDir) {
this.generatedFilesBaseDir = generatedFilesBaseDir
generatedFilesBaseDirProperty.set(generatedFilesBaseDir)
}

/**
* The base directory of generated files. The default is
* "${project.buildDir}/generated/source/proto".
*/
@PackageScope
abstract Property<String> getGeneratedFilesBaseDirProperty()

@PackageScope
void configureTasks() {
this.taskConfigActions.each { action ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import javax.inject.Inject
@CompileStatic
abstract class ProtobufExtract extends DefaultTask {

private final CopyActionFacade copyActionFacade = instantiateCopyActionFacade()
private final CopyActionFacade copyActionFacade = CopyActionFacade.Loader.create(project, objectFactory)
private final ArchiveActionFacade archiveActionFacade = instantiateArchiveActionFacade()
private final FileCollection filteredProtos = instantiateFilteredProtos()

Expand Down Expand Up @@ -98,14 +98,6 @@ abstract class ProtobufExtract extends DefaultTask {
@Inject
protected abstract ProviderFactory getProviderFactory()

private CopyActionFacade instantiateCopyActionFacade() {
if (GradleVersion.current() >= GradleVersion.version("6.0")) {
// Use object factory to instantiate as that will inject the necessary service.
return objectFactory.newInstance(CopyActionFacade.FileSystemOperationsBased)
}
return new CopyActionFacade.ProjectBased(project)
}

private ArchiveActionFacade instantiateArchiveActionFacade() {
if (GradleVersion.current() >= GradleVersion.version("6.0")) {
// Use object factory to instantiate as that will inject the necessary service.
Expand Down
22 changes: 18 additions & 4 deletions src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -374,15 +374,29 @@ class ProtobufPlugin implements Plugin<Project> {
) {
String sourceSetName = protoSourceSet.name
String taskName = 'generate' + Utils.getSourceSetSubstringForTaskNames(sourceSetName) + 'Proto'
Provider<String> outDir = project.providers.provider {
"${this.protobufExtension.generatedFilesBaseDir}/${sourceSetName}".toString()
}
String defaultGeneratedFilesBaseDir = protobufExtension.defaultGeneratedFilesBaseDir
Provider<String> generatedFilesBaseDirProvider = protobufExtension.generatedFilesBaseDirProperty
Provider<GenerateProtoTask> task = project.tasks.register(taskName, GenerateProtoTask) {
CopyActionFacade copyActionFacade = CopyActionFacade.Loader.create(it.project, it.objectFactory)
it.description = "Compiles Proto source for '${sourceSetName}'".toString()
it.outputBaseDir = outDir
it.outputBaseDir = project.providers.provider {
"${defaultGeneratedFilesBaseDir}/${sourceSetName}".toString()
}
it.addSourceDirs(protoSourceSet.proto)
it.addIncludeDir(protoSourceSet.proto.sourceDirectories)
it.addIncludeDir(protoSourceSet.includeProtoDirs)
it.doLast { task ->
String generatedFilesBaseDir = generatedFilesBaseDirProvider.get()
if (generatedFilesBaseDir == defaultGeneratedFilesBaseDir) {
return
}
// 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.into("${generatedFilesBaseDir}/${sourceSetName}")
}
}
configureAction.execute(it)
}
protoSourceSet.output.from(task.map { GenerateProtoTask it -> it.outputSourceDirectories })
Expand Down

0 comments on commit 278f21b

Please sign in to comment.