remove `#!/usr/bin/env sh`
[liba.git] / script / single.py
blobd6c9d5a618d77eebf84e691d1d98077291e6b6b9
1 #!/usr/bin/env python
2 import sys, os, re
5 class single(object):
6 undef_macros = []
7 define_macros = []
8 include_files = {}
9 _include_dirs = []
10 _include_files = []
12 @property
13 def include_dirs(self):
14 return self._include_dirs
16 @include_dirs.setter
17 def include_dirs(self, values):
18 for value in values:
19 value = os.path.relpath(value)
20 self._include_dirs.append(value)
22 def read(self, name):
23 self.name = os.path.relpath(name).replace("\\", "/")
24 with open(self.name, "r") as f:
25 self.source = f.read()
26 return self
28 def write(self, name):
29 with open(name, "wb") as f:
30 f.write(self.source.encode())
31 return self
33 def stdout(self):
34 sys.stdout.write(self.source)
36 def __call__(self, *args):
37 macros = ""
38 if args:
39 name = args[0]
40 else:
41 name = self.name
42 name = name.replace("\\", "/")
43 if not os.path.exists(name):
44 return ""
45 if name in self._include_files:
46 return ""
47 if args:
48 with open(name, "r") as f:
49 source = f.read()
50 else:
51 source = self.source
52 include_dirs = [os.path.dirname(name)] + self._include_dirs
53 includes = re.findall(r"#include \"([^\"]+)\"", source)
54 for include in includes:
55 cur = '#include "{}"\n'.format(include)
56 for include_dir in include_dirs:
57 new = os.path.join(include_dir, include)
58 if not os.path.exists(new):
59 continue
60 new = self.__call__(new)
61 source = source.replace(cur, new)
62 self._include_files.append(name)
63 if name == self.name:
64 for define_macro in self.define_macros:
65 macros += "#define %s\n" % define_macro
66 for undef_macro in self.undef_macros:
67 macros += "#undef %s\n" % undef_macro
68 self.include_files[name] = {
69 "header": tuple(self._include_files),
70 "source": source,
72 self.source = macros + source
73 self._include_files.clear()
74 return source
77 if __name__ == "__main__":
78 import argparse
80 o = single()
81 parser = argparse.ArgumentParser()
82 parser.add_argument("-v", "--verbose", action="store_true")
83 parser.add_argument("-D", default=[], action="append")
84 parser.add_argument("-U", default=[], action="append")
85 parser.add_argument("-I", default=[], action="append")
86 parser.add_argument("-H")
87 parser.add_argument("-C")
88 parser.add_argument("-c")
89 parser.add_argument("-O")
90 parser.add_argument("-o")
91 args = parser.parse_known_args()
92 o.define_macros = args[0].D
93 o.undef_macros = args[0].U
94 o.include_dirs = args[0].I
95 if args[0].c:
96 o.read(args[0].c)()
97 if args[0].o:
98 o.write(args[0].o)
99 elif args[0].O:
100 outname = os.path.relpath(args[0].c)
101 outname = os.path.join(args[0].O, outname)
102 outpath = os.path.dirname(outname)
103 os.makedirs(outpath, exist_ok=True)
104 o.write(outname)
105 else:
106 o.stdout()
107 if args[0].O and args[0].H:
108 for dirpath, dirnames, filenames in os.walk(args[0].H):
109 outpath = os.path.relpath(dirpath, args[0].H)
110 outpath = os.path.join(args[0].O, outpath)
111 os.makedirs(outpath, exist_ok=True)
112 for filename in filenames:
113 header = os.path.join(dirpath, filename)
114 output = os.path.join(outpath, filename)
115 prefix, suffix = os.path.splitext(header)
116 if suffix in (".h", ".hh", ".hpp", ".hxx"):
117 o.read(header)()
118 o.write(output)
119 if args[0].O and args[0].C:
120 for dirpath, dirnames, filenames in os.walk(args[0].C):
121 outpath = os.path.relpath(dirpath, args[0].C)
122 outpath = os.path.join(args[0].O, outpath)
123 os.makedirs(outpath, exist_ok=True)
124 for filename in filenames:
125 source = os.path.join(dirpath, filename)
126 output = os.path.join(outpath, filename)
127 prefix, suffix = os.path.splitext(source)
128 if suffix in (".c", ".cc", ".cpp", ".cxx"):
129 o.read(source)()
130 o.write(output)
131 if args[0].verbose:
132 sources = " ".join(o.include_files)
133 objects = ".o ".join(o.include_files) + ".o"
134 for key in o.include_files:
135 item = o.include_files[key]
136 item = " ".join(reversed(item["header"]))
137 sys.stderr.write(key + ".o:%s\n" % item)
138 sys.stderr.write("SOURCES = %s\n" % sources)
139 sys.stderr.write("OBJECTS = %s\n" % objects)