Skip to content

Commit

Permalink
Allow custom proto source directories. Resolves #1
Browse files Browse the repository at this point in the history
Create protoSources convention that can be used to override the default
proto file location, i.e., "src/main/proto" etc.
Create testProjectCustomProtoDir to test it.
  • Loading branch information
zhangkun83 committed Apr 21, 2015
1 parent 4c26802 commit e49c439
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 7 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dependencies {
}
```

More examples can be found in the test projects (``testProject*/``).

## Pre-compiled ``protoc`` artifacts
This [Maven Central directory](https://repo1.maven.org/maven2/com/google/protobuf/protoc/)
lists pre-compiled ``protoc`` artifacts that can be used by this plugin.
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ repositories {

dependencies {
compile gradleApi()
compile 'com.google.guava:guava:18.0'
testCompile group: 'junit', name: 'junit', version: '4.8.1'
compile localGroovy()
compile 'com.google.gradle:osdetector-gradle-plugin:1.2.1'
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ if ('test' in gradle.startParameter.taskNames) {
logger.warn('To test the current code, make sure you have run "./gradlew install" first.')
logger.warn('***************************************************************************')
include ':testProject'
include ':testProjectCustomProtoDir'
project(':testProject').projectDir = "$rootDir/testProject" as File
project(':testProjectCustomProtoDir').projectDir = "$rootDir/testProjectCustomProtoDir" as File
}

Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,15 @@ public class ProtobufCompile extends DefaultTask {
def plugins = project.convention.plugins.protobuf.protobufCodeGenPlugins
def protoc = project.convention.plugins.protobuf.protocPath
File destinationDir = project.file(destinationDir)
def srcDirs = [project.file("src/${sourceSetName}/proto"), "${project.extractedProtosDir}/${sourceSetName}"]

Set<File> protoFiles = inputs.sourceFiles.files
def srcDirs = protoFiles.collect {it.getParentFile()} as HashSet
destinationDir.mkdirs()
def dirs = CollectionUtils.join(" -I", srcDirs)
logger.debug "ProtobufCompile using directories ${dirs}"
logger.debug "ProtobufCompile using files ${inputs.sourceFiles.files}"
logger.debug "ProtobufCompile using files ${protoFiles}"
def cmd = [ protoc ]

cmd.addAll(srcDirs.collect {"-I${it}"})
//TODO: Figure out how to add variable to a task
cmd.addAll(includeDirs*.path.collect {"-I${it}"})
cmd += "--java_out=${destinationDir}"
// Handle code generation plugins
Expand All @@ -98,7 +97,7 @@ public class ProtobufCompile extends DefaultTask {
})
}

cmd.addAll inputs.sourceFiles.files
cmd.addAll protoFiles
logger.log(LogLevel.INFO, cmd.toString())
def output = new StringBuffer()
Process result = cmd.execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

package com.google.protobuf.gradle

import com.google.common.collect.ArrayListMultimap
import com.google.common.collect.Multimap
import org.gradle.api.Project

class ProtobufConvention {
Expand All @@ -40,6 +42,32 @@ class ProtobufConvention {

def String protocPath = "protoc"

/**
* Maps sourceSet names (String) -> proto source files.
* If no value is set, generateProto tasks will use the default source
* location: "src/${sourceSet.name}/proto", and will include all *.proto
* files.
* If any value is set, the default will no longer be used. Instead, the
* values will be fed to inputs.source of the generateProto tasks.
*/
private def Multimap<String, ?> protoSources = new ArrayListMultimap()

/**
* Overrides the default location of .proto files in the source. The
* default is *.proto under 'src/${sourceSet.name}/proto'.
*
* <p>Example:
* <pre>
* protoSources('main').add fileTree('src/main/protobuf') {
* include '**' + '/' + '*.proto'
* exclude 'src/main/protobuf/excluded.proto'
* }
* </pre>
*/
def List<?> protoSources(String sourceSetName) {
return protoSources.get(sourceSetName)
}

/**
* The spec of a pre-compiled protoc plugin that is fetched from repositories.
* It overrides 'protocPath'.
Expand Down
10 changes: 8 additions & 2 deletions src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,17 @@ class ProtobufPlugin implements Plugin<Project> {
}

private def addTasksToProjectForSourceSet(Project project, SourceSet sourceSet) {

def generateJavaTaskName = sourceSet.getTaskName('generate', 'proto')
project.tasks.create(generateJavaTaskName, ProtobufCompile) {
description = "Compiles Proto source '${sourceSet.name}:proto'"
inputs.source project.fileTree("src/${sourceSet.name}/proto") {include "**/*.proto"}
def List<?> protoSources = project.convention.plugins.protobuf.protoSources.get(sourceSet.name)
if (protoSources.isEmpty()) {
// if protoSources are not specified, use the default location
protoSources = [project.fileTree("src/${sourceSet.name}/proto") {include "**/*.proto"}] as List
}
protoSources.each() {
inputs.source it
}
inputs.source project.fileTree("${project.extractedProtosDir}/${sourceSet.name}") {include "**/*.proto"}
outputs.dir getGeneratedSourceDir(project, sourceSet)
//outputs.upToDateWhen {false}
Expand Down
44 changes: 44 additions & 0 deletions testProjectCustomProtoDir/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
buildscript {
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
classpath "com.google.protobuf:protobuf-gradle-plugin:${rootProject.version}"
}
}

apply plugin: 'protobuf'

repositories {
mavenCentral()
}

dependencies {
compile 'com.google.protobuf:protobuf-java:2.6.1'
testCompile 'junit:junit:4.7'
}

protocDep = 'com.google.protobuf:protoc:2.6.1'

// Override the default 'src/main/proto' directory
protoSources('main').add fileTree('src/main/protobuf') {
include '**/*.proto'
include '**/*.protodevel'
}

// Override the default 'src/test/proto' directory
protoSources('test').add fileTree('src/test/protocolbuffers') {
include '**/*.proto'
}

task printDeps(dependsOn: build) << {
configurations.each { println it }
sourceSets.each { println it.getCompileTaskName("proto") }
sourceSets.each { println it.getCompileTaskName("java") }
sourceSets.each { println it }
println tasks['generateProto'].source
println tasks['compileJava'].source
println project.buildDir
println project.buildDir.path
}
19 changes: 19 additions & 0 deletions testProjectCustomProtoDir/src/main/java/Foo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import com.google.protobuf.MessageLite;

import java.util.ArrayList;
import java.util.List;

public class Foo {
public static List<MessageLite> getDefaultInstances() {
ArrayList<MessageLite> list = new ArrayList<MessageLite>();
// from src/main/protobuf/test.protodevel
list.add(ws.antonov.protobuf.test.Test.TestMessage.getDefaultInstance());
list.add(ws.antonov.protobuf.test.Test.AnotherMessage.getDefaultInstance());
list.add(ws.antonov.protobuf.test.Test.Item.getDefaultInstance());
list.add(ws.antonov.protobuf.test.Test.DataMap.getDefaultInstance());
// from src/main/protobuf/sample.proto (java_multiple_files == true, thus no outter class)
list.add(com.example.tutorial.Msg.getDefaultInstance());
list.add(com.example.tutorial.SecondMsg.getDefaultInstance());
return list;
}
}
12 changes: 12 additions & 0 deletions testProjectCustomProtoDir/src/main/protobuf/sample.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
option java_package = "com.example.tutorial";
option java_outer_classname = "OuterSample";
option java_multiple_files = true;

message Msg {
optional string foo = 1;
optional SecondMsg blah = 2;
}

message SecondMsg {
optional int32 blah = 1;
}
23 changes: 23 additions & 0 deletions testProjectCustomProtoDir/src/main/protobuf/test.protodevel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ws.antonov.protobuf.test;

message TestMessage {
required int32 id = 1;
optional string name = 2;
}

message AnotherMessage {
repeated string names = 1;
optional DataPayload data = 2;

message DataPayload {
optional string payload = 1;
}
}

message Item {
required string name = 1;
optional string value = 2;
}
message DataMap {
repeated Item data_items = 1 [experimental_map_key="name"];
}
13 changes: 13 additions & 0 deletions testProjectCustomProtoDir/src/test/java/FooTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

public class FooTest {
@org.junit.Test
public void testMainProtos() {
org.junit.Assert.assertEquals(6, Foo.getDefaultInstances().size());
}

@org.junit.Test
public void testTestProtos() {
// from src/test/protocolbuffers/test.proto
Test.MsgTest.getDefaultInstance();
}
}
3 changes: 3 additions & 0 deletions testProjectCustomProtoDir/src/test/protocolbuffers/test.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message MsgTest {

}

0 comments on commit e49c439

Please sign in to comment.