wscript_capnproto (8512B)
1 # -*- python -*- 2 # against v0.8.0 57a4ca5af5a7f55b768a9d9d6655250bffb1257f 3 4 def options(ctx): 5 ctx.system_opt('capnproto') 6 grp = ctx.add_option_group('Dependency selection options') 7 grp.add_option('--system-capnpc', action='store_true', default=False, 8 help='Use system capnpc, even when bundling capnproto. ' 9 'Speeds up build, but the system must have the EXACT same ' 10 'capnproto version installed.') 11 12 def configure(ctx): 13 def find_tools(ctx): 14 ctx.find_program('capnpc', var='CAPNPC') 15 ctx.find_program('capnpc-c++', var='CAPNPC_CPP') 16 17 def system_capnproto(ctx): 18 ctx.check_cfg(package='capnp', args='--cflags --libs', 19 global_define=True) 20 ctx.undefine('HAVE_CAPNP') 21 find_tools(ctx) 22 def bundle_capnproto(ctx): 23 ctx.env.append_value('DEFINES_CAPNP', 'CAPNP_LITE') 24 ctx.env.append_value('SYSTEM_INCLUDES_CAPNP', 25 ctx.path.find_dir('capnproto/c++/src').abspath()) 26 if ctx.options.system_capnpc: 27 find_tools(ctx) 28 29 ctx.with_chk('capnproto', 30 {'system': system_capnproto, 'bundle': bundle_capnproto}) 31 ctx.add_os_flags('CAPNPCFLAGS') 32 33 def build(ctx): 34 if ctx.env.WITH_CAPNPROTO != 'bundle': return 35 36 src = [ 37 'capnproto/c++/src/kj/arena.c++', 38 'capnproto/c++/src/kj/array.c++', 39 'capnproto/c++/src/kj/common.c++', 40 'capnproto/c++/src/kj/debug.c++', 41 'capnproto/c++/src/kj/encoding.c++', # only needed on windows 42 'capnproto/c++/src/kj/exception.c++', 43 'capnproto/c++/src/kj/hash.c++', 44 'capnproto/c++/src/kj/io.c++', 45 'capnproto/c++/src/kj/main.c++', 46 'capnproto/c++/src/kj/memory.c++', 47 'capnproto/c++/src/kj/mutex.c++', 48 'capnproto/c++/src/kj/string.c++', 49 'capnproto/c++/src/kj/table.c++', 50 'capnproto/c++/src/kj/time.c++', # only needed on windows 51 'capnproto/c++/src/kj/units.c++', 52 53 'capnproto/c++/src/capnp/any.c++', 54 'capnproto/c++/src/capnp/arena.c++', 55 'capnproto/c++/src/capnp/blob.c++', 56 'capnproto/c++/src/capnp/c++.capnp.c++', 57 'capnproto/c++/src/capnp/layout.c++', 58 'capnproto/c++/src/capnp/message.c++', 59 'capnproto/c++/src/capnp/schema.capnp.c++', 60 'capnproto/c++/src/capnp/serialize-packed.c++', 61 'capnproto/c++/src/capnp/serialize.c++', 62 ] 63 64 src_heavy = src + [ 65 # src has #ifdef guard around correct os so we can compile both 66 'capnproto/c++/src/kj/filesystem-disk-unix.c++', 67 'capnproto/c++/src/kj/filesystem-disk-win32.c++', 68 'capnproto/c++/src/kj/filesystem.c++', 69 'capnproto/c++/src/kj/parse/char.c++', 70 'capnproto/c++/src/kj/refcount.c++', 71 'capnproto/c++/src/kj/string-tree.c++', 72 73 'capnproto/c++/src/capnp/compat/json.c++', 74 'capnproto/c++/src/capnp/compat/json.capnp.c++', 75 'capnproto/c++/src/capnp/dynamic.c++', 76 'capnproto/c++/src/capnp/schema-loader.c++', 77 'capnproto/c++/src/capnp/schema-parser.c++', 78 'capnproto/c++/src/capnp/schema.c++', 79 'capnproto/c++/src/capnp/serialize-text.c++', 80 'capnproto/c++/src/capnp/stream.capnp.c++', 81 'capnproto/c++/src/capnp/stringify.c++', 82 ] 83 84 ctx.stlib(idx = 51600, 85 source = src, 86 includes = 'capnproto/c++/src', 87 target = 'capnp', 88 uselib = 'CAPNP EXT') 89 90 def build_capnp_tool(ctx, pref): 91 # breaks with -fsanitize unless -fno-rtti is also used 92 # todo: figure out how to disable -fsanitize for this as it produces 93 # shittons of errors 94 ctx.stlib(idx = 51601, 95 source = src_heavy, 96 includes = 'capnproto/c++/src', 97 target = 'capnp_heavy', 98 uselib = 'EXT', 99 cxxflags = '-fno-rtti') 100 101 src = [ 102 'capnproto/c++/src/capnp/compiler/capnp.c++', 103 'capnproto/c++/src/capnp/compiler/compiler.c++', 104 'capnproto/c++/src/capnp/compiler/error-reporter.c++', 105 'capnproto/c++/src/capnp/compiler/generics.c++', 106 'capnproto/c++/src/capnp/compiler/grammar.capnp.c++', 107 'capnproto/c++/src/capnp/compiler/lexer.c++', 108 'capnproto/c++/src/capnp/compiler/lexer.capnp.c++', 109 'capnproto/c++/src/capnp/compiler/module-loader.c++', 110 'capnproto/c++/src/capnp/compiler/node-translator.c++', 111 'capnproto/c++/src/capnp/compiler/parser.c++', 112 'capnproto/c++/src/capnp/compiler/type-id.c++', 113 ] 114 ctx.program(idx = 51602, 115 source = src, 116 includes = 'capnproto/c++/src', 117 use = 'capnp_heavy', 118 uselib = 'EXT WINDOWS_CLI', 119 target = 'capnpc', 120 cxxflags = '-fno-rtti') 121 122 ctx.program(idx = 51603, 123 source = 'capnproto/c++/src/capnp/compiler/capnpc-c++.c++', 124 includes = 'capnproto/c++/src', 125 use = 'capnp_heavy', 126 uselib = 'EXT WINDOWS_CLI', 127 target = 'capnpc-c++', 128 cxxflags = '-fno-rtti') 129 if not ctx.env.CAPNPC: 130 ctx.in_host_env(build_capnp_tool) 131 132 import re 133 from waflib import Task 134 135 proto_re = re.compile('_([a-z0-9])') 136 import_re = re.compile('import +"([^\\"]*)\.o"') 137 cpp_re = re.compile('( |::)(get|set|has|is|init|adopt|disown|as)([A-Z])') 138 include_re = re.compile(r'^(#include ".*)\.o\.h"$', re.MULTILINE) 139 sys_include_re = re.compile(r'^(#include <.*>)$', re.MULTILINE) 140 undef_guard = ''' 141 #pragma GCC diagnostic push 142 #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 143 #pragma GCC diagnostic ignored "-Wold-style-cast" 144 #pragma GCC diagnostic ignored "-Wundef" 145 \\1 146 #pragma GCC diagnostic pop 147 ''' 148 149 class capnp(Task.Task): 150 color = 'BLUE' 151 vars = ['CAPNPCC', 'CAPNPC_CPP', 'CAPNPCFLAGS'] 152 153 def run(self): 154 inp = self.inputs[0] 155 data = inp.read() 156 data = proto_re.sub(lambda x: x.group(1).upper(), data) 157 out_proto = inp.change_ext('.capnp.o') 158 out_proto.write(data) 159 160 ret = self.exec_command( 161 [self.capnpc, 162 *self.flags, 163 *self.env.CAPNPCFLAGS, 164 '-o%s:%s' % (self.capnpc_cpp, self.outputs[0].parent.abspath()), 165 '--src-prefix=%s' % out_proto.parent.abspath(), 166 out_proto.abspath()]) 167 if ret != 0: return ret 168 169 def fix(inp, out): 170 data = inp.read() 171 data = include_re.sub(r'\1.hpp"', data) 172 data = sys_include_re.sub(undef_guard, data) 173 data = cpp_re.sub(lambda x: x.group(1) + x.group(2).title() + x.group(3), data) 174 out.write(data) 175 fix(self.outputs[0].change_ext('.o.c++'), self.outputs[0]) 176 fix(self.outputs[1].change_ext('.o.h'), self.outputs[1]) 177 178 # parse 'import "foo.capnp.o";' things 179 # ideally we would only need to depend on the preprocessor step and 180 # automatically add the .o extension, but whatever 181 def scan(self): 182 inp = self.inputs[0] 183 data = inp.read() 184 185 dep = [] 186 missing = [] 187 for i in import_re.findall(data): 188 r = inp.parent.find_resource(i+'.hpp') 189 if r: 190 dep.append(r) 191 else: 192 missing.append(i) 193 return (dep, missing) 194 195 from waflib.TaskGen import extension 196 @extension('.capnp') 197 def compile_capnp(self, node): 198 out_cpp = node.change_ext('.capnp.cpp') 199 out_hpp = node.change_ext('.capnp.hpp') 200 tsk = self.create_task('capnp', node, [out_cpp, out_hpp]) 201 202 if self.env.CAPNPC: 203 tsk.capnpc = self.env.CAPNPC[0] 204 tsk.capnpc_cpp = self.env.CAPNPC_CPP[0] 205 tsk.flags = [] 206 else: 207 capnpc = self.bld.get_tgen_by_name('capnpc').link_task.outputs[0] 208 capnpc_cpp_tsk = self.bld.get_tgen_by_name('capnpc-c++') 209 capnpc_cpp = capnpc_cpp_tsk.link_task.outputs[0] 210 inc = capnpc_cpp_tsk.compiled_tasks[0].inputs[0].find_node('../../..') 211 212 tsk.capnpc = capnpc.abspath() 213 tsk.capnpc_cpp = capnpc_cpp.abspath() 214 tsk.flags = ['--no-standard-import', '-I%s' % inc.abspath()] 215 tsk.dep_nodes += [capnpc, capnpc_cpp] 216 self.source.append(out_cpp)