protoc: simplify the java generation also solving problems with .proto input files generated during build

This commit is contained in:
Federico Pellegrin 2019-01-20 10:41:51 +00:00 committed by ita1024
parent 2f3d5e5163
commit 429c4c88d9
3 changed files with 68 additions and 55 deletions

View File

@ -0,0 +1,14 @@
package udp.tc.tests;
option java_package = "com.udp.tc.tests";
option java_outer_classname = "MessageInc";
option cc_generic_services = false;
option java_generic_services = false;
option py_generic_services = false;
message IncludeMe {
required int32 test = 1;
optional uint32 blah = 2;
optional uint32 justinc = 3;
}

View File

@ -0,0 +1,51 @@
#! /usr/bin/env python
# encoding: utf-8
# Federico Pellegrin, 2019 (fedepell)
import os
from waflib import Logs
top = '.'
out = 'build'
def options(opt):
opt.load('compiler_cxx java')
def configure(conf):
conf.load('compiler_cxx java protoc')
# Here you have to point to your protobuf-java JAR
conf.env.CLASSPATH_PROTOBUF = ['/usr/share/maven-repo/com/google/protobuf/protobuf-java/3.0.0/protobuf-java-3.0.0.jar']
def build(bld):
# this simulates a .proto generator. the gen.proto is generated in build
genp = bld(
rule = "cp ${SRC} ${TGT}",
source = "proto.source",
target = "inc/gen.proto"
)
# cxx doesn't have a problem with this, just knows gen.proto will pop up later
bld(
features = 'cxx cxxshlib',
source = [ bld.path.find_or_declare(genp.target) ],
name = 'somelib',
target = 'somelib'
)
# but for java:
# we either put grouping because of protoc java generations needs .proto to generate out fname (#2218)
# or accept that java dep is not strict on the .java file name (but relies just on explicit task ordering)
# bld.add_group()
# inc/gen.proto is an implicit dependency, but the file is generated at
# build time while protoc extra uses it before to determine the .java file
# name that will get generated
bld(
features = 'javac protoc',
name = 'pbjava',
srcdir = bld.path.find_or_declare(genp.target).parent,
source = [ bld.path.find_or_declare(genp.target) ],
use = 'PROTOBUF',
)

View File

@ -6,7 +6,7 @@
import re, os import re, os
from waflib.Task import Task from waflib.Task import Task
from waflib.TaskGen import extension from waflib.TaskGen import extension
from waflib import Errors, Context from waflib import Errors, Context, Logs
""" """
A simple tool to integrate protocol buffers into your build system. A simple tool to integrate protocol buffers into your build system.
@ -169,64 +169,12 @@ def process_protoc(self, node):
out_nodes.append(py_node) out_nodes.append(py_node)
protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath()) protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath())
if 'javac' in self.features and node.exists(): if 'javac' in self.features:
pkgname, javapkg, javacn, nodename = None, None, None, None
messages = []
# .java file name is done with some rules depending on .proto file content:
# -) package is either derived from option java_package if present
# or from package directive
# -) file name is either derived from option java_outer_classname if present
# or the .proto file is converted to camelcase. If a message
# is named the same then the behaviour depends on protoc version
#
# See also: https://developers.google.com/protocol-buffers/docs/reference/java-generated#invocation
code = node.read().splitlines()
for line in code:
m = re.search(r'^package\s+(.*);', line)
if m:
pkgname = m.groups()[0]
m = re.search(r'^option\s+(\S*)\s*=\s*"(\S*)";', line)
if m:
optname = m.groups()[0]
if optname == 'java_package':
javapkg = m.groups()[1]
elif optname == 'java_outer_classname':
javacn = m.groups()[1]
if self.env.PROTOC_MAJOR > '2':
m = re.search(r'^message\s+(\w*)\s*{*', line)
if m:
messages.append(m.groups()[0])
if javapkg:
nodename = javapkg
elif pkgname:
nodename = pkgname
else:
raise Errors.WafError('Cannot derive java name from protoc file')
nodename = nodename.replace('.',os.sep) + os.sep
if javacn:
nodename += javacn + '.java'
else:
filenamebase = node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].replace('_','')
filenamebase = filenamebase[:1].upper() + filenamebase[1:]
if self.env.PROTOC_MAJOR > '2' and node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].title() in messages:
nodename += filenamebase + 'OuterClass.java'
else:
nodename += filenamebase + '.java'
java_node = node.parent.find_or_declare(nodename)
out_nodes.append(java_node)
protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath())
# Make javac get also pick java code generated in build # Make javac get also pick java code generated in build
if not node.parent.get_bld() in self.javac_task.srcdir: if not node.parent.get_bld() in self.javac_task.srcdir:
self.javac_task.srcdir.append(node.parent.get_bld()) self.javac_task.srcdir.append(node.parent.get_bld())
if not out_nodes and node.exists(): protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath())
raise Errors.WafError('Feature %r not supported by protoc extra' % self.features)
tsk = self.create_task('protoc', node, out_nodes) tsk = self.create_task('protoc', node, out_nodes)
tsk.env.append_value('PROTOC_FLAGS', protoc_flags) tsk.env.append_value('PROTOC_FLAGS', protoc_flags)