1#!/usr/bin/python 2 3import sys 4import re 5import os 6 7INCLUDE_RE = re.compile('^#include "([^"]*)"$') 8 9def parse_include(line): 10 match = INCLUDE_RE.match(line) 11 return match.groups()[0] if match else None 12 13class Amalgamator: 14 def __init__(self, output_path, prefix): 15 self.include_paths = ["."] 16 self.included = set(["upb/port_def.inc", "upb/port_undef.inc"]) 17 self.output_h = open(output_path + prefix + "upb.h", "w") 18 self.output_c = open(output_path + prefix + "upb.c", "w") 19 20 self.output_c.write("/* Amalgamated source file */\n") 21 self.output_c.write('#include "%supb.h"\n' % (prefix)) 22 self.output_c.write(open("upb/port_def.inc").read()) 23 24 self.output_h.write("/* Amalgamated source file */\n") 25 self.output_h.write('#include <stdint.h>') 26 self.output_h.write(open("upb/port_def.inc").read()) 27 28 def add_include_path(self, path): 29 self.include_paths.append(path) 30 31 def finish(self): 32 self.output_c.write(open("upb/port_undef.inc").read()) 33 self.output_h.write(open("upb/port_undef.inc").read()) 34 35 def _process_file(self, infile_name, outfile): 36 file = None 37 for path in self.include_paths: 38 try: 39 full_path = os.path.join(path, infile_name) 40 file = open(full_path) 41 break 42 except IOError: 43 pass 44 if not file: 45 raise RuntimeError("Couldn't open file " + infile_name) 46 47 for line in file: 48 if not self._process_include(line, outfile): 49 outfile.write(line) 50 51 def _process_include(self, line, outfile): 52 include = parse_include(line) 53 if not include: 54 return False 55 if not (include.startswith("upb") or include.startswith("google")): 56 return False 57 if include.endswith("hpp"): 58 # Skip, we don't support the amalgamation from C++. 59 return True 60 else: 61 # Include this upb header inline. 62 if include not in self.included: 63 self.included.add(include) 64 self._add_header(include) 65 return True 66 67 def _add_header(self, filename): 68 self._process_file(filename, self.output_h) 69 70 def add_src(self, filename): 71 self._process_file(filename, self.output_c) 72 73# ---- main ---- 74 75output_path = sys.argv[1] 76prefix = sys.argv[2] 77amalgamator = Amalgamator(output_path, prefix) 78files = [] 79 80for arg in sys.argv[3:]: 81 arg = arg.strip() 82 if arg.startswith("-I"): 83 amalgamator.add_include_path(arg[2:]) 84 elif arg.endswith(".h") or arg.endswith(".inc"): 85 pass 86 else: 87 files.append(arg) 88 89for filename in files: 90 amalgamator.add_src(filename) 91 92amalgamator.finish() 93