Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for protoc --xxx_opt flag #290

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

marcoferrer
Copy link
Contributor

This PR resolves #210

static int compareProtocVersion(Project project, String target) {
String protocVersion = null
Dependency protocDep = project.configurations
.findByName("protobufToolsLocator_protoc").getAllDependencies()[0]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not happy about it but it seems that this was the only dependable way to get the current protoc compiler version configured. The artifact property of the protoc executable locator is overridden once the path is resolved.

Copy link
Collaborator

@zhangkun83 zhangkun83 Jan 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protoc may be from local path and you won't get the version from configurations at all.
A more reliable way is to run the protoc with --version. It should be run only once after protoc is resolved and saved somewhere (probably in ToolsLocator).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that idea a lot better

@marcoferrer
Copy link
Contributor Author

marcoferrer commented Jan 10, 2019

Code narc is unhappy, will push fix tomorrow

Copy link
Collaborator

@zhangkun83 zhangkun83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are codenarc failures:

File: com/google/protobuf/gradle/GenerateProtoTask.groovy
    Violation: Rule=SpaceAfterIf P=3 Line=455 Msg=[The if keyword within class com.google.protobuf.gradle.GenerateProtoTask is not followed by a single space] Src=[if(Utils.compareProtocVersion(project, "3.2") >= 0 && pluginOutPrefix.length() > 1){]
    Violation: Rule=SpaceBeforeOpeningBrace P=3 Line=455 Msg=[The opening brace for the block in class com.google.protobuf.gradle.GenerateProtoTask is not preceded by a space or whitespace] Src=[if(Utils.compareProtocVersion(project, "3.2") >= 0 && pluginOutPrefix.length() > 1){]
    Violation: Rule=UnnecessarySubstring P=3 Line=456 Msg=[Violation in class com.google.protobuf.gradle.GenerateProtoTask. The String.substring(int, int) method can be replaced with the subscript operator] Src=[baseCmd += "--${name}_opt=${pluginOutPrefix.substring(0, pluginOutPrefix.length() - 1)}"]

File: com/google/protobuf/gradle/Utils.groovy
    Violation: Rule=SpaceAfterIf P=3 Line=119 Msg=[The if keyword within class com.google.protobuf.gradle.Utils is not followed by a single space] Src=[if(protocDep != null){]
    Violation: Rule=SpaceBeforeOpeningBrace P=3 Line=119 Msg=[The opening brace for the block in class com.google.protobuf.gradle.Utils is not preceded by a space or whitespace] Src=[if(protocDep != null){]
    Violation: Rule=SpaceAfterIf P=3 Line=122 Msg=[The if keyword within class com.google.protobuf.gradle.Utils is not followed by a single space] Src=[if(protocVersion == null || protocVersion == ""){]
    Violation: Rule=SpaceBeforeOpeningBrace P=3 Line=122 Msg=[The opening brace for the block in class com.google.protobuf.gradle.Utils is not preceded by a space or whitespace] Src=[if(protocVersion == null || protocVersion == ""){]
    Violation: Rule=PublicMethodsBeforeNonPublicMethods P=3 Line=145 Msg=[The public method isTest in class com.google.protobuf.gradle.Utils is declared after a non-public method] Src=[static boolean isTest(String sourceSetOrVariantName) {]
    Violation: Rule=PublicMethodsBeforeNonPublicMethods P=3 Line=155 Msg=[The public method addToIdeSources in class com.google.protobuf.gradle.Utils is declared after a non-public method] Src=[static void addToIdeSources(Project project, boolean isTest, File f) {]

It also needs to be tested. It's not trivial because the project's test-ability is not that great. I am thinking maybe adding a "dry-run" flag to GenerateProtoTask, that will print out protoc command lines to a file instead of executing them. Then we create a "test project", say testProjectDryRuns, that will run protoc with versions pre-3.2 and post-3.2, with non-existing plugins, with and without options. Something like this:

protobuf {
  protoc {
    // The protocVersion property is set from the test spec where it's parameterized
    artifact = 'com.google.protobuf:protoc:${protocVersion}'
  }
  generateProtoTasks {
    all().each { task ->
      task.plugins {
        // When referring plugins without specifying their paths or artifacts, their bare
        // names are passed to protoc and protoc will run them from system path
        plugin1 {
          option 'feature1'
        }
        plugin2 {}
      }
      task.setDryRun(true)
    }
  }
}

This test project would have a custom test task that depends on generateProto and verify the output from the dry-runs.

@@ -451,7 +451,13 @@ public 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)}"
// Check if protoc supports opt flag
if(Utils.compareProtocVersion(project, "3.2") >= 0 && pluginOutPrefix.length() > 1){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For better readability, I would change makeOptionsPrefix() to assembleOptions(), which would leave out the trailing colon, then add the colon in the else branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to do that. That was my initial approach but I back tracked a bit. I was reluctant to introduce too many changes with out initial feedback.

static int compareProtocVersion(Project project, String target) {
String protocVersion = null
Dependency protocDep = project.configurations
.findByName("protobufToolsLocator_protoc").getAllDependencies()[0]
Copy link
Collaborator

@zhangkun83 zhangkun83 Jan 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protoc may be from local path and you won't get the version from configurations at all.
A more reliable way is to run the protoc with --version. It should be run only once after protoc is resolved and saved somewhere (probably in ToolsLocator).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Using ':' as the option delimiter breaks Windows build for some plugins
2 participants