Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 1 | #!/usr/bin/python |
Joshua Haberman | e59d2c8 | 2021-04-05 10:47:53 -0700 | [diff] [blame] | 2 | # |
Joshua Haberman | 823eb09 | 2021-04-05 12:26:41 -0700 | [diff] [blame] | 3 | # Copyright (c) 2009-2021, Google LLC |
Joshua Haberman | e59d2c8 | 2021-04-05 10:47:53 -0700 | [diff] [blame] | 4 | # All rights reserved. |
| 5 | # |
| 6 | # Redistribution and use in source and binary forms, with or without |
| 7 | # modification, are permitted provided that the following conditions are met: |
| 8 | # * Redistributions of source code must retain the above copyright |
| 9 | # notice, this list of conditions and the following disclaimer. |
| 10 | # * Redistributions in binary form must reproduce the above copyright |
| 11 | # notice, this list of conditions and the following disclaimer in the |
| 12 | # documentation and/or other materials provided with the distribution. |
| 13 | # * Neither the name of Google LLC nor the |
| 14 | # names of its contributors may be used to endorse or promote products |
| 15 | # derived from this software without specific prior written permission. |
| 16 | # |
| 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 20 | # DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY |
| 21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 27 | |
| 28 | import sys |
| 29 | import re |
Joshua Haberman | 985145c | 2019-04-24 17:36:17 +0000 | [diff] [blame] | 30 | import os |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 31 | |
| 32 | INCLUDE_RE = re.compile('^#include "([^"]*)"$') |
| 33 | |
| 34 | def parse_include(line): |
| 35 | match = INCLUDE_RE.match(line) |
| 36 | return match.groups()[0] if match else None |
| 37 | |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 38 | class Amalgamator: |
| 39 | def __init__(self, h_out, c_out): |
| 40 | self.include_paths = ["."] |
| 41 | self.included = set() |
| 42 | self.output_h = open(h_out, "w") |
| 43 | self.output_c = open(c_out, "w") |
| 44 | self.h_out = h_out.split("/")[-1] |
| 45 | |
| 46 | def amalgamate(self, h_files, c_files): |
| 47 | self.h_files = set(h_files) |
Joshua Haberman | 9bc7973 | 2019-01-23 17:16:31 -0800 | [diff] [blame] | 48 | self.output_c.write("/* Amalgamated source file */\n") |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 49 | self.output_c.write('#include "%s"\n' % (self.h_out)) |
| 50 | if self.h_out == "ruby-upb.h": |
Joshua Haberman | afffa9e | 2022-03-10 15:21:55 -0800 | [diff] [blame] | 51 | self.output_h.write("// Ruby is still using proto3 enum semantics for proto2\n") |
| 52 | self.output_h.write("#define UPB_DISABLE_PROTO2_ENUM_CHECKING\n") |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 53 | |
Joshua Haberman | 9bc7973 | 2019-01-23 17:16:31 -0800 | [diff] [blame] | 54 | self.output_h.write("/* Amalgamated source file */\n") |
Joshua Haberman | 3a37b91 | 2018-09-06 13:41:30 -0700 | [diff] [blame] | 55 | |
Eric Salo | f630787 | 2022-11-05 16:16:27 -0700 | [diff] [blame] | 56 | port_def = self._find_include_file("upb/port/def.inc") |
| 57 | port_undef = self._find_include_file("upb/port/undef.inc") |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 58 | self._process_file(port_def, self.output_h) |
| 59 | self._process_file(port_def, self.output_c) |
Joshua Haberman | 985145c | 2019-04-24 17:36:17 +0000 | [diff] [blame] | 60 | |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 61 | for file in c_files: |
| 62 | self._process_file(file, self.output_c) |
| 63 | |
| 64 | self._process_file(port_undef, self.output_h) |
| 65 | self._process_file(port_undef, self.output_c) |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 66 | |
| 67 | def _process_file(self, infile_name, outfile): |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 68 | lines = open(infile_name).readlines() |
Joshua Haberman | 4f1e48e | 2021-04-16 14:39:29 -0700 | [diff] [blame] | 69 | |
| 70 | has_copyright = lines[1].startswith(" * Copyright") |
| 71 | if has_copyright: |
| 72 | while not lines[0].startswith(" */"): |
| 73 | lines.pop(0) |
| 74 | lines.pop(0) |
| 75 | |
Joshua Haberman | 4f1e48e | 2021-04-16 14:39:29 -0700 | [diff] [blame] | 76 | for line in lines: |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 77 | if not self._process_include(line): |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 78 | outfile.write(line) |
| 79 | |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 80 | def _find_include_file(self, name): |
| 81 | for h_file in self.h_files: |
| 82 | if h_file.endswith(name): |
| 83 | return h_file |
| 84 | |
| 85 | def _process_include(self, line): |
Joshua Haberman | 2559e78 | 2020-04-09 14:36:24 -0700 | [diff] [blame] | 86 | include = parse_include(line) |
| 87 | if not include: |
| 88 | return False |
Joshua Haberman | 64abb5e | 2020-11-02 09:00:53 -0800 | [diff] [blame] | 89 | if not (include.startswith("upb") or include.startswith("google")): |
Joshua Haberman | 2559e78 | 2020-04-09 14:36:24 -0700 | [diff] [blame] | 90 | return False |
Eric Salo | f630787 | 2022-11-05 16:16:27 -0700 | [diff] [blame] | 91 | if include and (include.endswith("port/def.inc") or include.endswith("port/undef.inc")): |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 92 | # Skip, we handle this separately |
| 93 | return True |
Joshua Haberman | 2559e78 | 2020-04-09 14:36:24 -0700 | [diff] [blame] | 94 | if include.endswith("hpp"): |
| 95 | # Skip, we don't support the amalgamation from C++. |
| 96 | return True |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 97 | elif include in self.included: |
| 98 | return True |
Joshua Haberman | 2559e78 | 2020-04-09 14:36:24 -0700 | [diff] [blame] | 99 | else: |
| 100 | # Include this upb header inline. |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 101 | h_file = self._find_include_file(include) |
| 102 | if h_file: |
| 103 | self.h_files.remove(h_file) |
Joshua Haberman | 2559e78 | 2020-04-09 14:36:24 -0700 | [diff] [blame] | 104 | self.included.add(include) |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 105 | self._process_file(h_file, self.output_h) |
| 106 | return True |
| 107 | raise RuntimeError("Couldn't find include: " + include + ", h_files=" + repr(self.h_files)) |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 108 | |
| 109 | # ---- main ---- |
| 110 | |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 111 | c_out = sys.argv[1] |
| 112 | h_out = sys.argv[2] |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 113 | amalgamator = Amalgamator(h_out, c_out) |
| 114 | c_files = [] |
| 115 | h_files = [] |
Chris Fallin | b3f6daf | 2014-12-11 18:58:04 -0800 | [diff] [blame] | 116 | |
Joshua Haberman | 16facab | 2020-05-08 16:40:24 -0700 | [diff] [blame] | 117 | for arg in sys.argv[3:]: |
Joshua Haberman | 985145c | 2019-04-24 17:36:17 +0000 | [diff] [blame] | 118 | arg = arg.strip() |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 119 | if arg.endswith(".h") or arg.endswith(".inc"): |
| 120 | h_files.append(arg) |
Joshua Haberman | 985145c | 2019-04-24 17:36:17 +0000 | [diff] [blame] | 121 | else: |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 122 | c_files.append(arg) |
Joshua Haberman | 985145c | 2019-04-24 17:36:17 +0000 | [diff] [blame] | 123 | |
Joshua Haberman | ccd88d5 | 2022-09-03 01:52:54 +0000 | [diff] [blame] | 124 | amalgamator.amalgamate(h_files, c_files) |