VS: Improve performance of parsing project file

VS doesn't handle string parsing very well, so having all the files in one
property slows down VS a lot when loading the projects. Splitting the files
up into per-directory properties brings down project processing times from
20 seconds to 1 second (on my machine).
This commit is contained in:
Andreia Gaita 2024-02-15 13:06:34 +01:00
parent 1d29fb0853
commit d6f2bec890
1 changed files with 43 additions and 20 deletions

View File

@ -1142,6 +1142,11 @@ def generate_vs_project(env, original_args, project_name="godot"):
# This lets projects be regenerated even if there are build errors. # This lets projects be regenerated even if there are build errors.
filtered_args.pop("vsproj_gen_only", None) 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 # The "progress" option is ignored as the current compilation progress indication doesn't work in VS
filtered_args.pop("progress", None) filtered_args.pop("progress", None)
@ -1334,27 +1339,30 @@ def generate_vs_project(env, original_args, project_name="godot"):
set_sources = set(sources_active) set_sources = set(sources_active)
set_others = set(others_active) set_others = set(others_active)
for file in headers: for file in headers:
base_path = os.path.dirname(file).replace("\\", "_")
all_items.append(f'<ClInclude Include="{file}">') all_items.append(f'<ClInclude Include="{file}">')
all_items.append( 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>") all_items.append("</ClInclude>")
if file in set_headers: if file in set_headers:
activeItems.append(file) activeItems.append(file)
for file in sources: for file in sources:
base_path = os.path.dirname(file).replace("\\", "_")
all_items.append(f'<ClCompile Include="{file}">') all_items.append(f'<ClCompile Include="{file}">')
all_items.append( 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>") all_items.append("</ClCompile>")
if file in set_sources: if file in set_sources:
activeItems.append(file) activeItems.append(file)
for file in others: for file in others:
base_path = os.path.dirname(file).replace("\\", "_")
all_items.append(f'<None Include="{file}">') all_items.append(f'<None Include="{file}">')
all_items.append( 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>") all_items.append("</None>")
if file in set_others: if file in set_others:
@ -1368,7 +1376,18 @@ def generate_vs_project(env, original_args, project_name="godot"):
break break
condition = "'$(GodotConfiguration)|$(GodotPlatform)'=='" + vsconf + "'" 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"]}' output = f'bin\\godot{env["PROGSUFFIX"]}'
props_template = open("misc/msvs/props.template", "r").read() props_template = open("misc/msvs/props.template", "r").read()
@ -1406,6 +1425,8 @@ def generate_vs_project(env, original_args, project_name="godot"):
cmd_rebuild = [ cmd_rebuild = [
"vsproj=yes", "vsproj=yes",
"vsproj_props_only=yes",
"vsproj_gen_only=no",
f"vsproj_name={project_name}", f"vsproj_name={project_name}",
] + common_build_postfix ] + common_build_postfix
@ -1523,25 +1544,27 @@ def generate_vs_project(env, original_args, project_name="godot"):
section1 = sorted(section1) section1 = sorted(section1)
section2 = sorted(section2) section2 = sorted(section2)
proj_template = open("misc/msvs/vcxproj.template", "r").read() if not get_bool(original_args, "vsproj_props_only", False):
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))
proj_template = proj_template.replace("%%UUID%%", proj_uuid) with open(f"{project_name}.vcxproj", "w") as f:
proj_template = proj_template.replace("%%CONFS%%", "\n ".join(configurations)) f.write(proj_template)
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: if not get_bool(original_args, "vsproj_props_only", False):
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))
sln_template = open("misc/msvs/sln.template", "r").read() with open(f"{project_name}.sln", "w") as f:
sln_template = sln_template.replace("%%NAME%%", project_name) f.write(sln_template)
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 get_bool(original_args, "vsproj_gen_only", True): if get_bool(original_args, "vsproj_gen_only", True):
sys.exit() sys.exit()