user2569618
user2569618

Reputation: 687

Why does Gradle ignore sourceSets and/or srcDir when dealing with proto files?

My directory structure is src/ps/proto. My build.gradle file is located in the src directory. I've set sourceSets to

sourceSets {
    ps {
        proto {
             srcDir 'ps/proto'
        }
    }
}

Yet, a gradlew generatePsProto gives me a slew of error, one of which is that my source directory is src/src/ps/proto.

Execution failed for task ':generatePsProto'.
> protoc: stdout: . stderr: /home/build/tree/src/src/ps/proto: warning: directory does not exist.
  [libprotobuf WARNING google/protobuf/compiler/parser.cc:546] No syntax specified for the proto file: cldb.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
  ps/proto/security.proto: File not found.
  ps/proto/common.proto: File not found.
  ps/proto/cli.proto: File not found.
  ps/proto/volumemirrorcommon.proto: File not found.
  ps/proto/metrics.proto: File not found.
  cldb.proto: Import "ps/proto/security.proto" was not found or had errors.
  cldb.proto: Import "ps/proto/common.proto" was not found or had errors.
  mldb.proto: Import "ps/proto/cli.proto" was not found or had errors.
  mldb.proto:214:12: "CredentialsMsg" is not defined.
  mldb.proto:218:12: "CredentialsMsg" is not defined.
  [...]
  mldb.proto:3614:12: "Key" is not defined.
  mldb.proto:3618:12: "CredentialsMsg" is not defined.
  mldb.proto:3619:12: "ServerKeyType" is not defined.

I don't want the Gradle default of src/ps/proto. I want ps/proto. Can this be done? My goal is to remove the hard coded exec calls to protoc and use the protobuf pluging to compile the *.proto files into their respective *.h, *.cc, and eventually into *.o files.

Gradle 4.7 Build time: 2018-04-18 09:09:12 UTC Revision:
b9a962bf70638332300e7f810689cb2febbd4a6c

Groovy: 2.4.12 Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017 JVM: 1.8.0_144 (Oracle Corporation 25.144-b01) OS: Linux 3.10.0-514.el7.x86_64 amd64

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'
    }
}


apply plugin: 'c'
apply plugin: 'cpp'
apply plugin: 'java'
apply plugin: 'com.google.protobuf'

repositories {
    mavenCentral()
}

dependencies {
    compile "com.google.protobuf:protobuf-java:2.4.1"
}


sourceSets {
    ps {
        proto {
            srcDir 'ps/proto'
        }
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:2.4.1'
    }

    generateProtoTasks {
        all().each { task ->
            task.plugins {
                cpp {}
            }
        }
    }
}

Upvotes: 9

Views: 2998

Answers (2)

user675693
user675693

Reputation: 335

You seemed to have typo either for 'fs' or 'ps'.

The problem is the Import. because you have for example

cldb.proto: Import "ps/proto/security.proto"

mldb.proto: Import "ps/proto/cli.proto"

Edited:

you have to put every .proto file in src/yourCustomSourceSetName/proto/ps/proto/ and add

sourceSets {
    yourCustomSourceSetName {}
}
dependencies {
    compile ...  // dependencies for compileJava task
    yourCustomSourceSetNameCompile ... // dependencies for custom sourceSet
    compile sourceSets.yourCustomSourceSetName.output // compileJava uses output of the custom sourceSet
}

Then the import will look for other .proto files in the right place.

Upvotes: 0

Peter Ledbrook
Peter Ledbrook

Reputation: 4462

Gradle has a widely applicable convention that collection properties can be configured with methods of the same name. The key difference between setting a property using assignment (=) and using a method is that the latter appends its values.

So, to override the default source directory for the source set you need to use assignment:

sourceSets {
    ps {
        proto {
            srcDirs = ['ps/proto']
        }
    }
}

I don't really understand why you're getting an error message about src/src/ps/proto, so there may be some other issue. That error seems to be coming from protoc rather than Gradle.

EDIT

To solve your import problem, you should use

import security.proto;

i.e. without the source directory path. This is because the Protobuf Gradle Plugin appears to add each source directory as an "include directory". protoc only looks in such include directories for imports.

This is at least what I have garnered from the documentation and source code.

Upvotes: 0

Related Questions