227 lines
7.9 KiB
Python
227 lines
7.9 KiB
Python
"""Functions used to generate source files during build time"""
|
|
|
|
from collections import OrderedDict
|
|
from io import TextIOWrapper
|
|
|
|
import methods
|
|
|
|
|
|
def make_certs_header(target, source, env):
|
|
buffer = methods.get_buffer(str(source[0]))
|
|
decomp_size = len(buffer)
|
|
buffer = methods.compress_buffer(buffer)
|
|
|
|
with methods.generated_wrapper(str(target[0])) as file:
|
|
# System certs path. Editor will use them if defined. (for package maintainers)
|
|
file.write('#define _SYSTEM_CERTS_PATH "{}"\n'.format(env["system_certs_path"]))
|
|
if env["builtin_certs"]:
|
|
# Defined here and not in env so changing it does not trigger a full rebuild.
|
|
file.write(f"""\
|
|
#define BUILTIN_CERTS_ENABLED
|
|
|
|
inline constexpr int _certs_compressed_size = {len(buffer)};
|
|
inline constexpr int _certs_uncompressed_size = {decomp_size};
|
|
inline constexpr unsigned char _certs_compressed[] = {{
|
|
{methods.format_buffer(buffer, 1)}
|
|
}};
|
|
""")
|
|
|
|
|
|
def make_authors_header(target, source, env):
|
|
SECTIONS = {
|
|
"Project Founders": "AUTHORS_FOUNDERS",
|
|
"Lead Developer": "AUTHORS_LEAD_DEVELOPERS",
|
|
"Project Manager": "AUTHORS_PROJECT_MANAGERS",
|
|
"Developers": "AUTHORS_DEVELOPERS",
|
|
}
|
|
buffer = methods.get_buffer(str(source[0]))
|
|
reading = False
|
|
|
|
with methods.generated_wrapper(str(target[0])) as file:
|
|
|
|
def close_section():
|
|
file.write("\tnullptr,\n};\n\n")
|
|
|
|
for line in buffer.decode().splitlines():
|
|
if line.startswith(" ") and reading:
|
|
file.write(f'\t"{methods.to_escaped_cstring(line).strip()}",\n')
|
|
elif line.startswith("## "):
|
|
if reading:
|
|
close_section()
|
|
reading = False
|
|
section = SECTIONS[line[3:].strip()]
|
|
if section:
|
|
file.write(f"inline constexpr const char *{section}[] = {{\n")
|
|
reading = True
|
|
|
|
if reading:
|
|
close_section()
|
|
|
|
|
|
def make_donors_header(target, source, env):
|
|
SECTIONS = {
|
|
"Patrons": "DONORS_PATRONS",
|
|
"Platinum sponsors": "DONORS_SPONSORS_PLATINUM",
|
|
"Gold sponsors": "DONORS_SPONSORS_GOLD",
|
|
"Silver sponsors": "DONORS_SPONSORS_SILVER",
|
|
"Diamond members": "DONORS_MEMBERS_DIAMOND",
|
|
"Titanium members": "DONORS_MEMBERS_TITANIUM",
|
|
"Platinum members": "DONORS_MEMBERS_PLATINUM",
|
|
"Gold members": "DONORS_MEMBERS_GOLD",
|
|
}
|
|
buffer = methods.get_buffer(str(source[0]))
|
|
reading = False
|
|
|
|
with methods.generated_wrapper(str(target[0])) as file:
|
|
|
|
def close_section():
|
|
file.write("\tnullptr,\n};\n\n")
|
|
|
|
for line in buffer.decode().splitlines():
|
|
if line.startswith(" ") and reading:
|
|
file.write(f'\t"{methods.to_escaped_cstring(line).strip()}",\n')
|
|
elif line.startswith("## "):
|
|
if reading:
|
|
close_section()
|
|
reading = False
|
|
section = SECTIONS.get(line[3:].strip())
|
|
if section:
|
|
file.write(f"inline constexpr const char *{section}[] = {{\n")
|
|
reading = True
|
|
|
|
if reading:
|
|
close_section()
|
|
|
|
|
|
def make_license_header(target, source, env):
|
|
src_copyright = str(source[0])
|
|
src_license = str(source[1])
|
|
|
|
class LicenseReader:
|
|
def __init__(self, license_file: TextIOWrapper):
|
|
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)
|
|
|
|
projects = OrderedDict()
|
|
license_list = []
|
|
|
|
with open(src_copyright, "r", encoding="utf-8") 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" and part:
|
|
# attach non-empty 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 "Files" not 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 iter(projects.values()):
|
|
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(src_license, "r", encoding="utf-8") as file:
|
|
license_text = file.read()
|
|
|
|
with methods.generated_wrapper(str(target[0])) as file:
|
|
file.write(f"""\
|
|
inline constexpr const char *GODOT_LICENSE_TEXT = {{
|
|
{methods.to_raw_cstring(license_text)}
|
|
}};
|
|
|
|
struct ComponentCopyrightPart {{
|
|
const char *license;
|
|
const char *const *files;
|
|
const char *const *copyright_statements;
|
|
int file_count;
|
|
int copyright_count;
|
|
}};
|
|
|
|
struct ComponentCopyright {{
|
|
const char *name;
|
|
const ComponentCopyrightPart *parts;
|
|
int part_count;
|
|
}};
|
|
|
|
""")
|
|
|
|
file.write("inline constexpr const char *COPYRIGHT_INFO_DATA[] = {\n")
|
|
for line in data_list:
|
|
file.write(f'\t"{methods.to_escaped_cstring(line)}",\n')
|
|
file.write("};\n\n")
|
|
|
|
file.write("inline constexpr ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
|
|
part_index = 0
|
|
part_indexes = {}
|
|
for project_name, project in iter(projects.items()):
|
|
part_indexes[project_name] = part_index
|
|
for part in project:
|
|
file.write(
|
|
f'\t{{ "{methods.to_escaped_cstring(part["License"][0])}", '
|
|
+ f"©RIGHT_INFO_DATA[{part['file_index']}], "
|
|
+ f"©RIGHT_INFO_DATA[{part['copyright_index']}], "
|
|
+ f"{len(part['Files'])}, {len(part['Copyright'])} }},\n"
|
|
)
|
|
part_index += 1
|
|
file.write("};\n\n")
|
|
|
|
file.write(f"inline constexpr int COPYRIGHT_INFO_COUNT = {len(projects)};\n")
|
|
|
|
file.write("inline constexpr ComponentCopyright COPYRIGHT_INFO[] = {\n")
|
|
for project_name, project in iter(projects.items()):
|
|
file.write(
|
|
f'\t{{ "{methods.to_escaped_cstring(project_name)}", '
|
|
+ f"©RIGHT_PROJECT_PARTS[{part_indexes[project_name]}], "
|
|
+ f"{len(project)} }},\n"
|
|
)
|
|
file.write("};\n\n")
|
|
|
|
file.write(f"inline constexpr int LICENSE_COUNT = {len(license_list)};\n")
|
|
|
|
file.write("inline constexpr const char *LICENSE_NAMES[] = {\n")
|
|
for license in license_list:
|
|
file.write(f'\t"{methods.to_escaped_cstring(license[0])}",\n')
|
|
file.write("};\n\n")
|
|
|
|
file.write("inline constexpr const char *LICENSE_BODIES[] = {\n\n")
|
|
for license in license_list:
|
|
to_raw = []
|
|
for line in license[1:]:
|
|
if line == ".":
|
|
to_raw += [""]
|
|
else:
|
|
to_raw += [line]
|
|
file.write(f"{methods.to_raw_cstring(to_raw)},\n\n")
|
|
file.write("};\n\n")
|