diff options
Diffstat (limited to 'methods.py')
-rw-r--r-- | methods.py | 219 |
1 files changed, 133 insertions, 86 deletions
diff --git a/methods.py b/methods.py index 69d8df1d72..c0d129f93e 100644 --- a/methods.py +++ b/methods.py @@ -179,12 +179,14 @@ def get_version_info(module_version_string="", silent=False): gitfolder = ".git" if os.path.isfile(".git"): - module_folder = open(".git", "r").readline().strip() + with open(".git", "r", encoding="utf-8") as file: + module_folder = file.readline().strip() if module_folder.startswith("gitdir: "): gitfolder = module_folder[8:] if os.path.isfile(os.path.join(gitfolder, "HEAD")): - head = open(os.path.join(gitfolder, "HEAD"), "r", encoding="utf8").readline().strip() + with open(os.path.join(gitfolder, "HEAD"), "r", encoding="utf8") as file: + head = file.readline().strip() if head.startswith("ref: "): ref = head[5:] # If this directory is a Git worktree instead of a root clone. @@ -194,11 +196,12 @@ def get_version_info(module_version_string="", silent=False): head = os.path.join(gitfolder, ref) packedrefs = os.path.join(gitfolder, "packed-refs") if os.path.isfile(head): - githash = open(head, "r").readline().strip() + with open(head, "r", encoding="utf-8") as file: + githash = file.readline().strip() elif os.path.isfile(packedrefs): # Git may pack refs into a single file. This code searches .git/packed-refs file for the current ref's hash. # https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-pack-refs.html - for line in open(packedrefs, "r").read().splitlines(): + for line in open(packedrefs, "r", encoding="utf-8").read().splitlines(): if line.startswith("#"): continue (line_hash, line_ref) = line.split(" ") @@ -209,6 +212,18 @@ def get_version_info(module_version_string="", silent=False): githash = head version_info["git_hash"] = githash + # Fallback to 0 as a timestamp (will be treated as "unknown" in the engine). + version_info["git_timestamp"] = 0 + + # Get the UNIX timestamp of the build commit. + if os.path.exists(".git"): + try: + version_info["git_timestamp"] = subprocess.check_output( + ["git", "log", "-1", "--pretty=format:%ct", githash] + ).decode("utf-8") + except (subprocess.CalledProcessError, OSError): + # `git` not found in PATH. + pass return version_info @@ -218,9 +233,10 @@ def generate_version_header(module_version_string=""): # NOTE: It is safe to generate these files here, since this is still executed serially. - f = open("core/version_generated.gen.h", "w") - f.write( - """/* THIS FILE IS GENERATED DO NOT EDIT */ + with open("core/version_generated.gen.h", "w", encoding="utf-8", newline="\n") as f: + f.write( + """\ +/* THIS FILE IS GENERATED DO NOT EDIT */ #ifndef VERSION_GENERATED_GEN_H #define VERSION_GENERATED_GEN_H #define VERSION_SHORT_NAME "{short_name}" @@ -236,51 +252,49 @@ def generate_version_header(module_version_string=""): #define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH #endif // VERSION_GENERATED_GEN_H """.format( - **version_info + **version_info + ) ) - ) - f.close() - fhash = open("core/version_hash.gen.cpp", "w") - fhash.write( - """/* THIS FILE IS GENERATED DO NOT EDIT */ + with open("core/version_hash.gen.cpp", "w", encoding="utf-8", newline="\n") as fhash: + fhash.write( + """\ +/* THIS FILE IS GENERATED DO NOT EDIT */ #include "core/version.h" const char *const VERSION_HASH = "{git_hash}"; +const uint64_t VERSION_TIMESTAMP = {git_timestamp}; """.format( - **version_info + **version_info + ) ) - ) - fhash.close() def parse_cg_file(fname, uniforms, sizes, conditionals): - fs = open(fname, "r") - line = fs.readline() + with open(fname, "r", encoding="utf-8") as fs: + line = fs.readline() - while line: - if re.match(r"^\s*uniform", line): - res = re.match(r"uniform ([\d\w]*) ([\d\w]*)") - type = res.groups(1) - name = res.groups(2) + while line: + if re.match(r"^\s*uniform", line): + res = re.match(r"uniform ([\d\w]*) ([\d\w]*)") + type = res.groups(1) + name = res.groups(2) - uniforms.append(name) + uniforms.append(name) - if type.find("texobj") != -1: - sizes.append(1) - else: - t = re.match(r"float(\d)x(\d)", type) - if t: - sizes.append(int(t.groups(1)) * int(t.groups(2))) + if type.find("texobj") != -1: + sizes.append(1) else: - t = re.match(r"float(\d)", type) - sizes.append(int(t.groups(1))) + t = re.match(r"float(\d)x(\d)", type) + if t: + sizes.append(int(t.groups(1)) * int(t.groups(2))) + else: + t = re.match(r"float(\d)", type) + sizes.append(int(t.groups(1))) - if line.find("[branch]") != -1: - conditionals.append(name) + if line.find("[branch]") != -1: + conditionals.append(name) - line = fs.readline() - - fs.close() + line = fs.readline() def get_cmdline_bool(option, default): @@ -371,15 +385,15 @@ def is_module(path): def write_disabled_classes(class_list): - f = open("core/disabled_classes.gen.h", "w") - f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - f.write("#ifndef DISABLED_CLASSES_GEN_H\n") - f.write("#define DISABLED_CLASSES_GEN_H\n\n") - for c in class_list: - cs = c.strip() - if cs != "": - f.write("#define ClassDB_Disable_" + cs + " 1\n") - f.write("\n#endif\n") + with open("core/disabled_classes.gen.h", "w", encoding="utf-8", newline="\n") as f: + f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + f.write("#ifndef DISABLED_CLASSES_GEN_H\n") + f.write("#define DISABLED_CLASSES_GEN_H\n\n") + for c in class_list: + cs = c.strip() + if cs != "": + f.write("#define ClassDB_Disable_" + cs + " 1\n") + f.write("\n#endif\n") def write_modules(modules): @@ -422,7 +436,7 @@ void uninitialize_modules(ModuleInitializationLevel p_level) { ) # NOTE: It is safe to generate this file here, since this is still executed serially - with open("modules/register_module_types.gen.cpp", "w") as f: + with open("modules/register_module_types.gen.cpp", "w", encoding="utf-8", newline="\n") as f: f.write(modules_cpp) @@ -594,6 +608,12 @@ def no_verbose(sys, env): java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format( colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] ) + compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + generated_file_message = "{}Generating {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) env.Append(CXXCOMSTR=[compile_source_message]) env.Append(CCCOMSTR=[compile_source_message]) @@ -605,6 +625,8 @@ def no_verbose(sys, env): env.Append(LINKCOMSTR=[link_program_message]) env.Append(JARCOMSTR=[java_library_message]) env.Append(JAVACCOMSTR=[java_compile_source_message]) + env.Append(RCCOMSTR=[compiled_resource_message]) + env.Append(GENCOMSTR=[generated_file_message]) def detect_visual_c_compiler_version(tools_env): @@ -736,7 +758,7 @@ def generate_cpp_hint_file(filename): pass else: try: - with open(filename, "w") as fd: + with open(filename, "w", encoding="utf-8", newline="\n") as fd: fd.write("#define GDCLASS(m_class, m_inherits)\n") except OSError: print("Could not write cpp.hint file.") @@ -804,15 +826,10 @@ def CommandNoCache(env, target, sources, command, **args): return result -def Run(env, function, short_message, subprocess=True): +def Run(env, function): from SCons.Script import Action - from platform_methods import run_in_subprocess - output_print = short_message if not env["verbose"] else "" - if not subprocess: - return Action(function, output_print) - else: - return Action(run_in_subprocess(function), output_print) + return Action(function, "$GENCOMSTR") def detect_darwin_sdk_path(platform, env): @@ -1042,7 +1059,7 @@ def show_progress(env): def progress_finish(target, source, env): nonlocal node_count, progressor try: - with open(node_count_fname, "w") as f: + with open(node_count_fname, "w", encoding="utf-8", newline="\n") as f: f.write("%d\n" % node_count) progressor.delete(progressor.file_list()) except Exception: @@ -1072,7 +1089,7 @@ def dump(env): def non_serializable(obj): return "<<non-serializable: %s>>" % (type(obj).__qualname__) - with open(".scons_env.json", "w") as f: + with open(".scons_env.json", "w", encoding="utf-8", newline="\n") as f: dump(env.Dictionary(), f, indent=4, default=non_serializable) @@ -1142,6 +1159,11 @@ def generate_vs_project(env, original_args, project_name="godot"): # This lets projects be regenerated even if there are build errors. filtered_args.pop("vsproj_gen_only", None) + # This flag allows users to regenerate only the props file without touching the sln or vcxproj files. + # This preserves any customizations users have done to the solution, while still updating the file list + # and build commands. + filtered_args.pop("vsproj_props_only", None) + # The "progress" option is ignored as the current compilation progress indication doesn't work in VS filtered_args.pop("progress", None) @@ -1221,7 +1243,8 @@ def generate_vs_project(env, original_args, project_name="godot"): ).hexdigest() if os.path.exists(f"{project_name}.vcxproj.filters"): - existing_filters = open(f"{project_name}.vcxproj.filters", "r").read() + with open(f"{project_name}.vcxproj.filters", "r", encoding="utf-8") as file: + existing_filters = file.read() match = re.search(r"(?ms)^<!-- CHECKSUM$.([0-9a-f]{32})", existing_filters) if match is not None and md5 == match.group(1): skip_filters = True @@ -1232,7 +1255,8 @@ def generate_vs_project(env, original_args, project_name="godot"): if not skip_filters: print(f"Regenerating {project_name}.vcxproj.filters") - filters_template = open("misc/msvs/vcxproj.filters.template", "r").read() + with open("misc/msvs/vcxproj.filters.template", "r", encoding="utf-8") as file: + filters_template = file.read() for i in range(1, 10): filters_template = filters_template.replace(f"%%UUID{i}%%", str(uuid.uuid4())) @@ -1269,7 +1293,7 @@ def generate_vs_project(env, original_args, project_name="godot"): filters_template = filters_template.replace("%%HASH%%", md5) - with open(f"{project_name}.vcxproj.filters", "w") as f: + with open(f"{project_name}.vcxproj.filters", "w", encoding="utf-8", newline="\n") as f: f.write(filters_template) envsources = [] @@ -1334,27 +1358,30 @@ def generate_vs_project(env, original_args, project_name="godot"): set_sources = set(sources_active) set_others = set(others_active) for file in headers: + base_path = os.path.dirname(file).replace("\\", "_") all_items.append(f'<ClInclude Include="{file}">') all_items.append( - f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList.Contains(';{file};'))\">true</ExcludedFromBuild>" + f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList_{base_path}.Contains(';{file};'))\">true</ExcludedFromBuild>" ) all_items.append("</ClInclude>") if file in set_headers: activeItems.append(file) for file in sources: + base_path = os.path.dirname(file).replace("\\", "_") all_items.append(f'<ClCompile Include="{file}">') all_items.append( - f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList.Contains(';{file};'))\">true</ExcludedFromBuild>" + f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList_{base_path}.Contains(';{file};'))\">true</ExcludedFromBuild>" ) all_items.append("</ClCompile>") if file in set_sources: activeItems.append(file) for file in others: + base_path = os.path.dirname(file).replace("\\", "_") all_items.append(f'<None Include="{file}">') all_items.append( - f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList.Contains(';{file};'))\">true</ExcludedFromBuild>" + f" <ExcludedFromBuild Condition=\"!$(ActiveProjectItemList_{base_path}.Contains(';{file};'))\">true</ExcludedFromBuild>" ) all_items.append("</None>") if file in set_others: @@ -1368,10 +1395,22 @@ def generate_vs_project(env, original_args, project_name="godot"): break condition = "'$(GodotConfiguration)|$(GodotPlatform)'=='" + vsconf + "'" - properties.append("<ActiveProjectItemList>;" + ";".join(activeItems) + ";</ActiveProjectItemList>") + itemlist = {} + for item in activeItems: + key = os.path.dirname(item).replace("\\", "_") + if not key in itemlist: + itemlist[key] = [item] + else: + itemlist[key] += [item] + + for x in itemlist.keys(): + properties.append( + "<ActiveProjectItemList_%s>;%s;</ActiveProjectItemList_%s>" % (x, ";".join(itemlist[x]), x) + ) output = f'bin\\godot{env["PROGSUFFIX"]}' - props_template = open("misc/msvs/props.template", "r").read() + with open("misc/msvs/props.template", "r", encoding="utf-8") as file: + props_template = file.read() props_template = props_template.replace("%%VSCONF%%", vsconf) props_template = props_template.replace("%%CONDITION%%", condition) @@ -1406,6 +1445,8 @@ def generate_vs_project(env, original_args, project_name="godot"): cmd_rebuild = [ "vsproj=yes", + "vsproj_props_only=yes", + "vsproj_gen_only=no", f"vsproj_name={project_name}", ] + common_build_postfix @@ -1428,14 +1469,16 @@ def generate_vs_project(env, original_args, project_name="godot"): cmd = " ^& ".join(common_build_prefix + [" ".join([commands] + cmd_clean)]) props_template = props_template.replace("%%CLEAN%%", cmd) - with open(f"{project_name}.{platform}.{target}.{arch}.generated.props", "w") as f: + with open( + f"{project_name}.{platform}.{target}.{arch}.generated.props", "w", encoding="utf-8", newline="\n" + ) as f: f.write(props_template) proj_uuid = str(uuid.uuid4()) sln_uuid = str(uuid.uuid4()) if os.path.exists(f"{project_name}.sln"): - for line in open(f"{project_name}.sln", "r").read().splitlines(): + for line in open(f"{project_name}.sln", "r", encoding="utf-8").read().splitlines(): if line.startswith('Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")'): proj_uuid = re.search( r"\"{(\b[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-\b[0-9a-fA-F]{12}\b)}\"$", @@ -1523,25 +1566,29 @@ def generate_vs_project(env, original_args, project_name="godot"): section1 = sorted(section1) section2 = sorted(section2) - proj_template = open("misc/msvs/vcxproj.template", "r").read() - - proj_template = proj_template.replace("%%UUID%%", proj_uuid) - proj_template = proj_template.replace("%%CONFS%%", "\n ".join(configurations)) - proj_template = proj_template.replace("%%IMPORTS%%", "\n ".join(imports)) - proj_template = proj_template.replace("%%DEFAULT_ITEMS%%", "\n ".join(all_items)) - proj_template = proj_template.replace("%%PROPERTIES%%", "\n ".join(properties)) - - with open(f"{project_name}.vcxproj", "w") as f: - f.write(proj_template) - - sln_template = open("misc/msvs/sln.template", "r").read() - sln_template = sln_template.replace("%%NAME%%", project_name) - sln_template = sln_template.replace("%%UUID%%", proj_uuid) - sln_template = sln_template.replace("%%SLNUUID%%", sln_uuid) - sln_template = sln_template.replace("%%SECTION1%%", "\n ".join(section1)) - sln_template = sln_template.replace("%%SECTION2%%", "\n ".join(section2)) - with open(f"{project_name}.sln", "w") as f: - f.write(sln_template) + if not get_bool(original_args, "vsproj_props_only", False): + with open("misc/msvs/vcxproj.template", "r", encoding="utf-8") as file: + proj_template = file.read() + proj_template = proj_template.replace("%%UUID%%", proj_uuid) + proj_template = proj_template.replace("%%CONFS%%", "\n ".join(configurations)) + proj_template = proj_template.replace("%%IMPORTS%%", "\n ".join(imports)) + proj_template = proj_template.replace("%%DEFAULT_ITEMS%%", "\n ".join(all_items)) + proj_template = proj_template.replace("%%PROPERTIES%%", "\n ".join(properties)) + + with open(f"{project_name}.vcxproj", "w", encoding="utf-8", newline="\n") as f: + f.write(proj_template) + + if not get_bool(original_args, "vsproj_props_only", False): + with open("misc/msvs/sln.template", "r", encoding="utf-8") as file: + sln_template = file.read() + sln_template = sln_template.replace("%%NAME%%", project_name) + sln_template = sln_template.replace("%%UUID%%", proj_uuid) + sln_template = sln_template.replace("%%SLNUUID%%", sln_uuid) + sln_template = sln_template.replace("%%SECTION1%%", "\n ".join(section1)) + sln_template = sln_template.replace("%%SECTION2%%", "\n ".join(section2)) + + with open(f"{project_name}.sln", "w", encoding="utf-8", newline="\n") as f: + f.write(sln_template) if get_bool(original_args, "vsproj_gen_only", True): sys.exit() |