Nuklear
Minimal-state, immediate-mode graphical user interface toolkit written in ANSI C.
 
Loading...
Searching...
No Matches
build.py
1
2import fnmatch
3import os.path
4import sys
5import re
6
7def print_help():
8 print(
9"""usage: python single_header_packer.py --macro <macro> [--intro <files>] --extern <files> --pub <files> --priv1 <files> --priv2 <files> [--outro <files>]
10
11 where <files> can be a comma-separated list of files. e.g. --priv *.c,inc/*.h
12 or a space separated list encapsulated in quotes. e.g. --priv1 "file.c file2.c file3.c"
13
14 The 'extern' files are placed between 'priv1' and 'priv2'.
15
16 The resulting code is packed as follows:
17
18 [intro file contents]
19
20 #ifndef <macro>_SINGLE_HEADER
21 #define <macro>_SINGLE_HEADER
22 [public header file contents]
23 #endif /* <macro>_SINGLE_HEADER */
24
25 #ifdef <macro>_IMPLEMENTATION
26 [private header and source file contents]
27 #endif /* <macro>_IMPLEMENTATION */
28
29 /*
30 [outro file contents]
31 */""")
32
33def parse_files(arg):
34 files = []
35 paths = re.split(r'[,\s]', arg)
36
37 for path in paths:
38 if "*" in path:
39 # Wildcard
40 d = os.path.dirname(path)
41 if d == "": d = "."
42 if d == " ": continue
43 if not os.path.exists(d):
44 print(d + " does not exist.")
45 exit()
46
47 wildcard = os.path.basename(path)
48 unsorted = []
49 for file in os.listdir(d):
50 if fnmatch.fnmatch(file, wildcard):
51 unsorted.append(os.path.join(d, file))
52 unsorted.sort()
53 files.extend(unsorted)
54
55 else:
56 # Regular file
57 if not os.path.exists(path):
58 print(path + " does not exist.")
59 exit()
60 elif os.path.isdir(path):
61 print(path + " is a directory. Expected a file name.")
62 exit()
63 else:
64 files.append(path)
65
66 return files;
67
68def omit_includes(str, files):
69 for file in files:
70 fname = os.path.basename(file)
71 if ".h" in file:
72 str = str.replace("#include \"" + fname + "\"", "");
73 str = str.replace("#include <" + fname + ">", "");
74 return str
75
76def fix_comments(str):
77 return re.sub(r"//(.*)(\n|$)", "/* \\1 */\\2", str)
78
79# Main start
80# ==========
81
82if len(sys.argv) < 2:
83 print_help()
84 exit()
85
86intro_files = []
87pub_files = []
88priv_files1 = []
89outro_files2 = []
90extern_files = []
91cur_arg = 1
92macro = ""
93
94# Parse args
95# ----------
96while cur_arg < len(sys.argv):
97 if sys.argv[cur_arg] == "--help":
98 print_help()
99 exit()
100 elif sys.argv[cur_arg] == "--macro":
101 cur_arg += 1
102 macro = sys.argv[cur_arg]
103 elif sys.argv[cur_arg] == "--intro":
104 cur_arg += 1
105 intro_files = parse_files(sys.argv[cur_arg])
106 elif sys.argv[cur_arg] == "--pub":
107 cur_arg += 1
108 pub_files = parse_files(sys.argv[cur_arg])
109 elif sys.argv[cur_arg] == "--priv1":
110 cur_arg += 1
111 priv_files1 = parse_files(sys.argv[cur_arg])
112 elif sys.argv[cur_arg] == "--priv2":
113 cur_arg += 1
114 priv_files2 = parse_files(sys.argv[cur_arg])
115 elif sys.argv[cur_arg] == "--extern":
116 cur_arg += 1
117 extern_files = parse_files(sys.argv[cur_arg])
118 elif sys.argv[cur_arg] == "--outro":
119 cur_arg += 1
120 outro_files = parse_files(sys.argv[cur_arg])
121 else:
122 print("Unknown argument " + sys.argv[cur_arg])
123
124 cur_arg += 1
125
126if macro == "":
127 print("Option --macro <macro> is mandatory")
128 exit()
129
130# Print concatenated output
131# -------------------------
132for f in intro_files:
133 sys.stdout.write(open(f, 'r').read())
134
135# print("\n#ifndef " + macro + "_SINGLE_HEADER");
136# print("#define " + macro + "_SINGLE_HEADER");
137print("#ifndef NK_SINGLE_FILE");
138print(" #define NK_SINGLE_FILE");
139print("#endif");
140print("");
141
142for f in pub_files:
143 sys.stdout.write(open(f, 'r').read())
144# print("#endif /* " + macro + "_SINGLE_HEADER */");
145
146print("\n#ifdef " + macro + "_IMPLEMENTATION");
147print("");
148
149for f in priv_files1:
150 print(omit_includes(open(f, 'r').read(),
151 pub_files + priv_files1 + priv_files2 + extern_files))
152for f in extern_files:
153 print(fix_comments(open(f, 'r').read()))
154
155for f in priv_files2:
156 print(omit_includes(open(f, 'r').read(),
157 pub_files + priv_files1 + priv_files2 + extern_files))
158
159print("#endif /* " + macro + "_IMPLEMENTATION */");
160
161print("/*")
162for f in outro_files:
163 sys.stdout.write(open(f, 'r').read())
164 print("")
165print("*/")