waf/waflib/extras/protoc.py

151 lines
3.9 KiB
Python
Raw Normal View History

2012-09-27 21:08:26 +02:00
#!/usr/bin/env python
# encoding: utf-8
# Philipp Bender, 2012
# Matt Clarkson, 2012
2013-09-05 06:48:29 +02:00
import re
2012-09-27 21:08:26 +02:00
from waflib.Task import Task
from waflib.TaskGen import extension
from waflib import Errors
2012-09-27 21:08:26 +02:00
"""
A simple tool to integrate protocol buffers into your build system.
Example for C++:
2012-09-27 21:08:26 +02:00
def configure(conf):
conf.load('compiler_cxx cxx protoc')
def build(bld):
bld(
features = 'cxx cxxprogram'
source = 'main.cpp file1.proto proto/file2.proto',
includes = '. proto',
target = 'executable')
2012-09-27 21:08:26 +02:00
Example for Python:
def configure(conf):
conf.load('python protoc')
def build(bld):
bld(
features = 'py'
source = 'main.py file1.proto proto/file2.proto',
protoc_includes = 'proto')
Example for both Python and C++ at same time:
def configure(conf):
conf.load('cxx python protoc')
def build(bld):
bld(
features = 'cxx py'
source = 'file1.proto proto/file2.proto',
protoc_includes = 'proto') # or includes
Notes when using this tool:
- protoc command line parsing is tricky.
The generated files can be put in subfolders which depend on
the order of the include paths.
Try to be simple when creating task generators
containing protoc stuff.
2012-09-27 21:08:26 +02:00
"""
class protoc(Task):
run_str = '${PROTOC} ${PROTOC_FL:PROTOC_FLAGS} ${PROTOC_ST:INCPATHS} ${PROTOC_ST:PROTOC_INCPATHS} ${SRC[0].bldpath()}'
2012-09-27 21:08:26 +02:00
color = 'BLUE'
ext_out = ['.h', 'pb.cc', '.py']
2013-09-05 06:48:29 +02:00
def scan(self):
"""
Scan .proto dependencies
"""
node = self.inputs[0]
nodes = []
names = []
seen = []
search_nodes = []
2013-09-05 06:48:29 +02:00
if not node:
return (nodes, names)
2013-09-05 06:48:29 +02:00
if 'cxx' in self.generator.features:
search_nodes = self.generator.includes_nodes
if 'py' in self.generator.features:
for incpath in getattr(self.generator, 'protoc_includes', []):
search_nodes.append(self.generator.bld.path.find_node(incpath))
2013-09-05 06:48:29 +02:00
def parse_node(node):
if node in seen:
return
seen.append(node)
2015-03-03 12:19:25 +01:00
code = node.read().splitlines()
2013-09-05 06:48:29 +02:00
for line in code:
m = re.search(r'^import\s+"(.*)";.*(//)?.*', line)
if m:
dep = m.groups()[0]
for incnode in search_nodes:
found = incnode.find_resource(dep)
2013-09-05 06:48:29 +02:00
if found:
nodes.append(found)
parse_node(found)
else:
names.append(dep)
parse_node(node)
return (nodes, names)
2012-09-27 21:08:26 +02:00
@extension('.proto')
def process_protoc(self, node):
incdirs = []
out_nodes = []
protoc_flags = []
2017-09-15 20:59:37 +02:00
# ensure PROTOC_FLAGS is a list; a copy is used below anyway
self.env.PROTOC_FLAGS = self.to_list(self.env.PROTOC_FLAGS)
if 'cxx' in self.features:
cpp_node = node.change_ext('.pb.cc')
hpp_node = node.change_ext('.pb.h')
self.source.append(cpp_node)
out_nodes.append(cpp_node)
out_nodes.append(hpp_node)
protoc_flags.append('--cpp_out=%s' % node.parent.get_bld().bldpath())
if 'py' in self.features:
py_node = node.change_ext('_pb2.py')
self.source.append(py_node)
out_nodes.append(py_node)
protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath())
2017-09-15 20:59:37 +02:00
if not out_nodes:
raise Errors.WafError('Feature %r not supported by protoc extra' % self.features)
2017-09-15 20:59:37 +02:00
tsk = self.create_task('protoc', node, out_nodes)
tsk.env.append_value('PROTOC_FLAGS', protoc_flags)
2017-09-15 20:59:37 +02:00
# Instruct protoc where to search for .proto included files.
# For C++ standard include files dirs are used,
# but this doesn't apply to Python for example
for incpath in getattr(self, 'protoc_includes', []):
incdirs.append(self.bld.path.find_node(incpath).bldpath())
2017-09-15 20:59:37 +02:00
tsk.env.PROTOC_INCPATHS = incdirs
2012-09-27 21:08:26 +02:00
use = getattr(self, 'use', '')
if not 'PROTOBUF' in use:
self.use = self.to_list(use) + ['PROTOBUF']
def configure(conf):
2017-09-15 20:59:37 +02:00
conf.check_cfg(package='protobuf', uselib_store='PROTOBUF', args=['--cflags', '--libs'])
2012-09-27 21:08:26 +02:00
conf.find_program('protoc', var='PROTOC')
conf.env.PROTOC_ST = '-I%s'
conf.env.PROTOC_FL = '%s'