core_builders.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. """Functions used to generate source files during build time
  2. All such functions are invoked in a subprocess on Windows to prevent build flakiness.
  3. """
  4. from platform_methods import subprocess_main
  5. from compat import iteritems, itervalues, open_utf8, escape_string, byte_to_str
  6. def make_certs_header(target, source, env):
  7. src = source[0]
  8. dst = target[0]
  9. f = open(src, "rb")
  10. g = open_utf8(dst, "w")
  11. buf = f.read()
  12. decomp_size = len(buf)
  13. import zlib
  14. buf = zlib.compress(buf)
  15. g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
  16. g.write("#ifndef _CERTS_RAW_H\n")
  17. g.write("#define _CERTS_RAW_H\n")
  18. # System certs path. Editor will use them if defined. (for package maintainers)
  19. path = env["system_certs_path"]
  20. g.write('#define _SYSTEM_CERTS_PATH "%s"\n' % str(path))
  21. if env["builtin_certs"]:
  22. # Defined here and not in env so changing it does not trigger a full rebuild.
  23. g.write("#define BUILTIN_CERTS_ENABLED\n")
  24. g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n")
  25. g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n")
  26. g.write("static const unsigned char _certs_compressed[] = {\n")
  27. for i in range(len(buf)):
  28. g.write("\t" + byte_to_str(buf[i]) + ",\n")
  29. g.write("};\n")
  30. g.write("#endif")
  31. g.close()
  32. f.close()
  33. def make_authors_header(target, source, env):
  34. sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"]
  35. sections_id = ["AUTHORS_FOUNDERS", "AUTHORS_LEAD_DEVELOPERS", "AUTHORS_PROJECT_MANAGERS", "AUTHORS_DEVELOPERS"]
  36. src = source[0]
  37. dst = target[0]
  38. f = open_utf8(src, "r")
  39. g = open_utf8(dst, "w")
  40. g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
  41. g.write("#ifndef _EDITOR_AUTHORS_H\n")
  42. g.write("#define _EDITOR_AUTHORS_H\n")
  43. reading = False
  44. def close_section():
  45. g.write("\t0\n")
  46. g.write("};\n")
  47. for line in f:
  48. if reading:
  49. if line.startswith(" "):
  50. g.write('\t"' + escape_string(line.strip()) + '",\n')
  51. continue
  52. if line.startswith("## "):
  53. if reading:
  54. close_section()
  55. reading = False
  56. for section, section_id in zip(sections, sections_id):
  57. if line.strip().endswith(section):
  58. current_section = escape_string(section_id)
  59. reading = True
  60. g.write("const char *const " + current_section + "[] = {\n")
  61. break
  62. if reading:
  63. close_section()
  64. g.write("#endif\n")
  65. g.close()
  66. f.close()
  67. def make_donors_header(target, source, env):
  68. sections = [
  69. "Patrons",
  70. "Platinum sponsors",
  71. "Gold sponsors",
  72. "Silver sponsors",
  73. "Diamond members",
  74. "Titanium members",
  75. "Platinum members",
  76. "Gold members",
  77. ]
  78. sections_id = [
  79. "DONORS_PATRONS",
  80. "DONORS_SPONSORS_PLATINUM",
  81. "DONORS_SPONSORS_GOLD",
  82. "DONORS_SPONSORS_SILVER",
  83. "DONORS_MEMBERS_DIAMOND",
  84. "DONORS_MEMBERS_TITANIUM",
  85. "DONORS_MEMBERS_PLATINUM",
  86. "DONORS_MEMBERS_GOLD",
  87. ]
  88. src = source[0]
  89. dst = target[0]
  90. f = open_utf8(src, "r")
  91. g = open_utf8(dst, "w")
  92. g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
  93. g.write("#ifndef _EDITOR_DONORS_H\n")
  94. g.write("#define _EDITOR_DONORS_H\n")
  95. reading = False
  96. def close_section():
  97. g.write("\t0\n")
  98. g.write("};\n")
  99. for line in f:
  100. if reading >= 0:
  101. if line.startswith(" "):
  102. g.write('\t"' + escape_string(line.strip()) + '",\n')
  103. continue
  104. if line.startswith("## "):
  105. if reading:
  106. close_section()
  107. reading = False
  108. for section, section_id in zip(sections, sections_id):
  109. if line.strip().endswith(section):
  110. current_section = escape_string(section_id)
  111. reading = True
  112. g.write("const char *const " + current_section + "[] = {\n")
  113. break
  114. if reading:
  115. close_section()
  116. g.write("#endif\n")
  117. g.close()
  118. f.close()
  119. def make_license_header(target, source, env):
  120. src_copyright = source[0]
  121. src_license = source[1]
  122. dst = target[0]
  123. class LicenseReader:
  124. def __init__(self, license_file):
  125. self._license_file = license_file
  126. self.line_num = 0
  127. self.current = self.next_line()
  128. def next_line(self):
  129. line = self._license_file.readline()
  130. self.line_num += 1
  131. while line.startswith("#"):
  132. line = self._license_file.readline()
  133. self.line_num += 1
  134. self.current = line
  135. return line
  136. def next_tag(self):
  137. if not ":" in self.current:
  138. return ("", [])
  139. tag, line = self.current.split(":", 1)
  140. lines = [line.strip()]
  141. while self.next_line() and self.current.startswith(" "):
  142. lines.append(self.current.strip())
  143. return (tag, lines)
  144. from collections import OrderedDict
  145. projects = OrderedDict()
  146. license_list = []
  147. with open_utf8(src_copyright, "r") as copyright_file:
  148. reader = LicenseReader(copyright_file)
  149. part = {}
  150. while reader.current:
  151. tag, content = reader.next_tag()
  152. if tag in ("Files", "Copyright", "License"):
  153. part[tag] = content[:]
  154. elif tag == "Comment":
  155. # attach part to named project
  156. projects[content[0]] = projects.get(content[0], []) + [part]
  157. if not tag or not reader.current:
  158. # end of a paragraph start a new part
  159. if "License" in part and not "Files" in part:
  160. # no Files tag in this one, so assume standalone license
  161. license_list.append(part["License"])
  162. part = {}
  163. reader.next_line()
  164. data_list = []
  165. for project in itervalues(projects):
  166. for part in project:
  167. part["file_index"] = len(data_list)
  168. data_list += part["Files"]
  169. part["copyright_index"] = len(data_list)
  170. data_list += part["Copyright"]
  171. with open_utf8(dst, "w") as f:
  172. f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
  173. f.write("#ifndef _EDITOR_LICENSE_H\n")
  174. f.write("#define _EDITOR_LICENSE_H\n")
  175. f.write("const char *const GODOT_LICENSE_TEXT =")
  176. with open_utf8(src_license, "r") as license_file:
  177. for line in license_file:
  178. escaped_string = escape_string(line.strip())
  179. f.write('\n\t\t"' + escaped_string + '\\n"')
  180. f.write(";\n\n")
  181. f.write(
  182. "struct ComponentCopyrightPart {\n"
  183. "\tconst char *license;\n"
  184. "\tconst char *const *files;\n"
  185. "\tconst char *const *copyright_statements;\n"
  186. "\tint file_count;\n"
  187. "\tint copyright_count;\n"
  188. "};\n\n"
  189. )
  190. f.write(
  191. "struct ComponentCopyright {\n"
  192. "\tconst char *name;\n"
  193. "\tconst ComponentCopyrightPart *parts;\n"
  194. "\tint part_count;\n"
  195. "};\n\n"
  196. )
  197. f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n")
  198. for line in data_list:
  199. f.write('\t"' + escape_string(line) + '",\n')
  200. f.write("};\n\n")
  201. f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
  202. part_index = 0
  203. part_indexes = {}
  204. for project_name, project in iteritems(projects):
  205. part_indexes[project_name] = part_index
  206. for part in project:
  207. f.write(
  208. '\t{ "'
  209. + escape_string(part["License"][0])
  210. + '", '
  211. + "&COPYRIGHT_INFO_DATA["
  212. + str(part["file_index"])
  213. + "], "
  214. + "&COPYRIGHT_INFO_DATA["
  215. + str(part["copyright_index"])
  216. + "], "
  217. + str(len(part["Files"]))
  218. + ", "
  219. + str(len(part["Copyright"]))
  220. + " },\n"
  221. )
  222. part_index += 1
  223. f.write("};\n\n")
  224. f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n")
  225. f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n")
  226. for project_name, project in iteritems(projects):
  227. f.write(
  228. '\t{ "'
  229. + escape_string(project_name)
  230. + '", '
  231. + "&COPYRIGHT_PROJECT_PARTS["
  232. + str(part_indexes[project_name])
  233. + "], "
  234. + str(len(project))
  235. + " },\n"
  236. )
  237. f.write("};\n\n")
  238. f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n")
  239. f.write("const char *const LICENSE_NAMES[] = {\n")
  240. for l in license_list:
  241. f.write('\t"' + escape_string(l[0]) + '",\n')
  242. f.write("};\n\n")
  243. f.write("const char *const LICENSE_BODIES[] = {\n\n")
  244. for l in license_list:
  245. for line in l[1:]:
  246. if line == ".":
  247. f.write('\t"\\n"\n')
  248. else:
  249. f.write('\t"' + escape_string(line) + '\\n"\n')
  250. f.write('\t"",\n\n')
  251. f.write("};\n\n")
  252. f.write("#endif\n")
  253. if __name__ == "__main__":
  254. subprocess_main(globals())