diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/SCsub | 48 | ||||
-rw-r--r-- | core/core_builders.py | 236 | ||||
-rw-r--r-- | core/make_binders.py | 9 |
3 files changed, 268 insertions, 25 deletions
diff --git a/core/SCsub b/core/SCsub index c508ecc37e..c8e2e10b9f 100644 --- a/core/SCsub +++ b/core/SCsub @@ -2,7 +2,9 @@ Import('env') -import methods +import core_builders +import make_binders +from platform_methods import run_in_subprocess env.core_sources = [] @@ -21,7 +23,7 @@ gd_cpp += gd_inc gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n" with open("global_defaults.gen.cpp", "w") as f: - f.write(gd_cpp) + f.write(gd_cpp) # Generate AES256 script encryption key @@ -48,26 +50,27 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ): txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0" print("Invalid AES256 encryption key, not 64 bits hex: " + e) +# NOTE: It is safe to generate this file here, since this is still executed serially with open("script_encryption_key.gen.cpp", "w") as f: - f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n") + f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n") # Add required thirdparty code. Header paths are hardcoded, we don't need to append # to the include path (saves a few chars on the compiler invocation for touchy MSVC...) thirdparty_dir = "#thirdparty/misc/" thirdparty_sources = [ - # C sources - "base64.c", - "fastlz.c", - "sha256.c", - "smaz.c", - - # C++ sources - "aes256.cpp", - "hq2x.cpp", - "md5.cpp", - "pcg.cpp", - "triangulator.cpp", + # C sources + "base64.c", + "fastlz.c", + "sha256.c", + "smaz.c", + + # C++ sources + "aes256.cpp", + "hq2x.cpp", + "md5.cpp", + "pcg.cpp", + "triangulator.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env.add_source_files(env.core_sources, thirdparty_sources) @@ -76,9 +79,9 @@ env.add_source_files(env.core_sources, thirdparty_sources) # However, our version has some custom modifications, so it won't compile with the system one thirdparty_minizip_dir = "#thirdparty/minizip/" thirdparty_minizip_sources = [ - "ioapi.c", - "unzip.c", - "zip.c", + "ioapi.c", + "unzip.c", + "zip.c", ] thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources] env.add_source_files(env.core_sources, thirdparty_minizip_sources) @@ -92,20 +95,19 @@ env.add_source_files(env.core_sources, "*.cpp") # Make binders -import make_binders -env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', make_binders.run) +env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run)) # Authors env.Depends('#core/authors.gen.h', "../AUTHORS.md") -env.CommandNoCache('#core/authors.gen.h', "../AUTHORS.md", methods.make_authors_header) +env.CommandNoCache('#core/authors.gen.h', "../AUTHORS.md", run_in_subprocess(core_builders.make_authors_header)) # Donors env.Depends('#core/donors.gen.h', "../DONORS.md") -env.CommandNoCache('#core/donors.gen.h', "../DONORS.md", methods.make_donors_header) +env.CommandNoCache('#core/donors.gen.h', "../DONORS.md", run_in_subprocess(core_builders.make_donors_header)) # License env.Depends('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"]) -env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], methods.make_license_header) +env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(core_builders.make_license_header)) # Chain load SCsubs SConscript('os/SCsub') diff --git a/core/core_builders.py b/core/core_builders.py new file mode 100644 index 0000000000..90e505aab9 --- /dev/null +++ b/core/core_builders.py @@ -0,0 +1,236 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" +from platform_methods import subprocess_main +from compat import iteritems, itervalues, open_utf8, escape_string + + +def make_authors_header(target, source, env): + sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"] + sections_id = ["AUTHORS_FOUNDERS", "AUTHORS_LEAD_DEVELOPERS", "AUTHORS_PROJECT_MANAGERS", "AUTHORS_DEVELOPERS"] + + src = source[0] + dst = target[0] + f = open_utf8(src, "r") + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_AUTHORS_H\n") + g.write("#define _EDITOR_AUTHORS_H\n") + + reading = False + + def close_section(): + g.write("\t0\n") + g.write("};\n") + + for line in f: + if reading: + if line.startswith(" "): + g.write("\t\"" + escape_string(line.strip()) + "\",\n") + continue + if line.startswith("## "): + if reading: + close_section() + reading = False + for section, section_id in zip(sections, sections_id): + if line.strip().endswith(section): + current_section = escape_string(section_id) + reading = True + g.write("const char *const " + current_section + "[] = {\n") + break + + if reading: + close_section() + + g.write("#endif\n") + + g.close() + f.close() + + +def make_donors_header(target, source, env): + sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", + "Gold donors", "Silver donors", "Bronze donors"] + sections_id = ["DONORS_SPONSOR_PLAT", "DONORS_SPONSOR_GOLD", "DONORS_SPONSOR_MINI", + "DONORS_GOLD", "DONORS_SILVER", "DONORS_BRONZE"] + + src = source[0] + dst = target[0] + f = open_utf8(src, "r") + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_DONORS_H\n") + g.write("#define _EDITOR_DONORS_H\n") + + reading = False + + def close_section(): + g.write("\t0\n") + g.write("};\n") + + for line in f: + if reading >= 0: + if line.startswith(" "): + g.write("\t\"" + escape_string(line.strip()) + "\",\n") + continue + if line.startswith("## "): + if reading: + close_section() + reading = False + for section, section_id in zip(sections, sections_id): + if line.strip().endswith(section): + current_section = escape_string(section_id) + reading = True + g.write("const char *const " + current_section + "[] = {\n") + break + + if reading: + close_section() + + g.write("#endif\n") + + g.close() + f.close() + + +def make_license_header(target, source, env): + src_copyright = source[0] + src_license = source[1] + dst = target[0] + + class LicenseReader: + def __init__(self, license_file): + self._license_file = license_file + self.line_num = 0 + self.current = self.next_line() + + def next_line(self): + line = self._license_file.readline() + self.line_num += 1 + while line.startswith("#"): + line = self._license_file.readline() + self.line_num += 1 + self.current = line + return line + + def next_tag(self): + if not ':' in self.current: + return ('', []) + tag, line = self.current.split(":", 1) + lines = [line.strip()] + while self.next_line() and self.current.startswith(" "): + lines.append(self.current.strip()) + return (tag, lines) + + from collections import OrderedDict + projects = OrderedDict() + license_list = [] + + with open_utf8(src_copyright, "r") as copyright_file: + reader = LicenseReader(copyright_file) + part = {} + while reader.current: + tag, content = reader.next_tag() + if tag in ("Files", "Copyright", "License"): + part[tag] = content[:] + elif tag == "Comment": + # attach part to named project + projects[content[0]] = projects.get(content[0], []) + [part] + + if not tag or not reader.current: + # end of a paragraph start a new part + if "License" in part and not "Files" in part: + # no Files tag in this one, so assume standalone license + license_list.append(part["License"]) + part = {} + reader.next_line() + + data_list = [] + for project in itervalues(projects): + for part in project: + part["file_index"] = len(data_list) + data_list += part["Files"] + part["copyright_index"] = len(data_list) + data_list += part["Copyright"] + + with open_utf8(dst, "w") as f: + + f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + f.write("#ifndef _EDITOR_LICENSE_H\n") + f.write("#define _EDITOR_LICENSE_H\n") + f.write("const char *const GODOT_LICENSE_TEXT =") + + with open_utf8(src_license, "r") as license_file: + for line in license_file: + escaped_string = escape_string(line.strip()) + f.write("\n\t\t\"" + escaped_string + "\\n\"") + f.write(";\n\n") + + f.write("struct ComponentCopyrightPart {\n" + "\tconst char *license;\n" + "\tconst char *const *files;\n" + "\tconst char *const *copyright_statements;\n" + "\tint file_count;\n" + "\tint copyright_count;\n" + "};\n\n") + + f.write("struct ComponentCopyright {\n" + "\tconst char *name;\n" + "\tconst ComponentCopyrightPart *parts;\n" + "\tint part_count;\n" + "};\n\n") + + f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n") + for line in data_list: + f.write("\t\"" + escape_string(line) + "\",\n") + f.write("};\n\n") + + f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n") + part_index = 0 + part_indexes = {} + for project_name, project in iteritems(projects): + part_indexes[project_name] = part_index + for part in project: + f.write("\t{ \"" + escape_string(part["License"][0]) + "\", " + + "©RIGHT_INFO_DATA[" + str(part["file_index"]) + "], " + + "©RIGHT_INFO_DATA[" + str(part["copyright_index"]) + "], " + + str(len(part["Files"])) + ", " + + str(len(part["Copyright"])) + " },\n") + part_index += 1 + f.write("};\n\n") + + f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n") + + f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n") + for project_name, project in iteritems(projects): + f.write("\t{ \"" + escape_string(project_name) + "\", " + + "©RIGHT_PROJECT_PARTS[" + str(part_indexes[project_name]) + "], " + + str(len(project)) + " },\n") + f.write("};\n\n") + + f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n") + + f.write("const char *const LICENSE_NAMES[] = {\n") + for l in license_list: + f.write("\t\"" + escape_string(l[0]) + "\",\n") + f.write("};\n\n") + + f.write("const char *const LICENSE_BODIES[] = {\n\n") + for l in license_list: + for line in l[1:]: + if line == ".": + f.write("\t\"\\n\"\n") + else: + f.write("\t\"" + escape_string(line) + "\\n\"\n") + f.write("\t\"\",\n\n") + f.write("};\n\n") + + f.write("#endif\n") + + +if __name__ == '__main__': + subprocess_main(globals()) diff --git a/core/make_binders.py b/core/make_binders.py index 6a7602cd5d..f1a10829a3 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -1,4 +1,5 @@ # -*- coding: ibm850 -*- +from platform_methods import subprocess_main template_typed = """ @@ -265,8 +266,12 @@ def run(target, source, env): else: text += t - with open(target[0].path, "w") as f: + with open(target[0], "w") as f: f.write(text) - with open(target[1].path, "w") as f: + with open(target[1], "w") as f: f.write(text_ext) + + +if __name__ == '__main__': + subprocess_main(globals()) |