C#: Replace uses of old Configuration and update old csprojs

This commit is contained in:
Ignacio Etcheverry 2020-03-14 19:01:29 +01:00
parent ce01b83c4a
commit 1b634785b5
8 changed files with 171 additions and 52 deletions

View File

@ -121,15 +121,30 @@ EndProject";
@" {{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU @" {{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU
{{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU"; {{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU";
public static void FixConfigurations(string slnPath) public static void MigrateFromOldConfigNames(string slnPath)
{ {
if (!File.Exists(slnPath)) if (!File.Exists(slnPath))
return; return;
var input = File.ReadAllText(slnPath); var input = File.ReadAllText(slnPath);
if (!Regex.IsMatch(input, Regex.Escape("Tools|Any CPU")))
return;
// This method renames old configurations in solutions to the new ones.
//
// This is the order configs appear in the solution and what we want to rename them to:
// Debug|Any CPU = Debug|Any CPU -> ExportDebug|Any CPU = ExportDebug|Any CPU
// Tools|Any CPU = Tools|Any CPU -> Debug|Any CPU = Debug|Any CPU
//
// But we want to move Tools (now Debug) to the top, so it's easier to rename like this:
// Debug|Any CPU = Debug|Any CPU -> Debug|Any CPU = Debug|Any CPU
// Release|Any CPU = Release|Any CPU -> ExportDebug|Any CPU = ExportDebug|Any CPU
// Tools|Any CPU = Tools|Any CPU -> ExportRelease|Any CPU = ExportRelease|Any CPU
var dict = new Dictionary<string, string> var dict = new Dictionary<string, string>
{ {
{"Debug|Any CPU", "Tools|Any CPU"}, {"Debug|Any CPU", "Debug|Any CPU"},
{"Release|Any CPU", "ExportDebug|Any CPU"}, {"Release|Any CPU", "ExportDebug|Any CPU"},
{"Tools|Any CPU", "ExportRelease|Any CPU"} {"Tools|Any CPU", "ExportRelease|Any CPU"}
}; };

View File

@ -17,30 +17,30 @@ namespace GodotTools.ProjectEditor
string path = Path.Combine(dir, name + ".csproj"); string path = Path.Combine(dir, name + ".csproj");
ProjectPropertyGroupElement mainGroup; ProjectPropertyGroupElement mainGroup;
var root = CreateLibraryProject(name, "Tools", out mainGroup); var root = CreateLibraryProject(name, "Debug", out mainGroup);
mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)")); mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)"));
mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj")); mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj"));
mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)")); mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)"));
mainGroup.SetProperty("ApiConfiguration", "Debug").Condition = " '$(Configuration)' != 'Release' "; mainGroup.SetProperty("ApiConfiguration", "Debug").Condition = " '$(Configuration)' != 'ExportRelease' ";
mainGroup.SetProperty("ApiConfiguration", "Release").Condition = " '$(Configuration)' == 'Release' "; mainGroup.SetProperty("ApiConfiguration", "Release").Condition = " '$(Configuration)' == 'ExportRelease' ";
var toolsGroup = root.AddPropertyGroup(); var debugGroup = root.AddPropertyGroup();
toolsGroup.Condition = " '$(Configuration)|$(Platform)' == 'Tools|AnyCPU' "; debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";
toolsGroup.AddProperty("DebugSymbols", "true"); debugGroup.AddProperty("DebugSymbols", "true");
toolsGroup.AddProperty("DebugType", "portable"); debugGroup.AddProperty("DebugType", "portable");
toolsGroup.AddProperty("Optimize", "false"); debugGroup.AddProperty("Optimize", "false");
toolsGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;TOOLS;"); debugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;TOOLS;");
toolsGroup.AddProperty("ErrorReport", "prompt"); debugGroup.AddProperty("ErrorReport", "prompt");
toolsGroup.AddProperty("WarningLevel", "4"); debugGroup.AddProperty("WarningLevel", "4");
toolsGroup.AddProperty("ConsolePause", "false"); debugGroup.AddProperty("ConsolePause", "false");
var coreApiRef = root.AddItem("Reference", CoreApiProjectName); var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", CoreApiProjectName + ".dll")); coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", CoreApiProjectName + ".dll"));
coreApiRef.AddMetadata("Private", "False"); coreApiRef.AddMetadata("Private", "False");
var editorApiRef = root.AddItem("Reference", EditorApiProjectName); var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
editorApiRef.Condition = " '$(Configuration)' == 'Tools' "; editorApiRef.Condition = " '$(Configuration)' == 'Debug' ";
editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", EditorApiProjectName + ".dll")); editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", EditorApiProjectName + ".dll"));
editorApiRef.AddMetadata("Private", "False"); editorApiRef.AddMetadata("Private", "False");
@ -103,24 +103,24 @@ namespace GodotTools.ProjectEditor
mainGroup.AddProperty("TargetFrameworkVersion", "v4.7"); mainGroup.AddProperty("TargetFrameworkVersion", "v4.7");
mainGroup.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString()); mainGroup.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
var debugGroup = root.AddPropertyGroup(); var exportDebugGroup = root.AddPropertyGroup();
debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "; exportDebugGroup.Condition = " '$(Configuration)|$(Platform)' == 'ExportDebug|AnyCPU' ";
debugGroup.AddProperty("DebugSymbols", "true"); exportDebugGroup.AddProperty("DebugSymbols", "true");
debugGroup.AddProperty("DebugType", "portable"); exportDebugGroup.AddProperty("DebugType", "portable");
debugGroup.AddProperty("Optimize", "false"); exportDebugGroup.AddProperty("Optimize", "false");
debugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;"); exportDebugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;");
debugGroup.AddProperty("ErrorReport", "prompt"); exportDebugGroup.AddProperty("ErrorReport", "prompt");
debugGroup.AddProperty("WarningLevel", "4"); exportDebugGroup.AddProperty("WarningLevel", "4");
debugGroup.AddProperty("ConsolePause", "false"); exportDebugGroup.AddProperty("ConsolePause", "false");
var releaseGroup = root.AddPropertyGroup(); var exportReleaseGroup = root.AddPropertyGroup();
releaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "; exportReleaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'ExportRelease|AnyCPU' ";
releaseGroup.AddProperty("DebugType", "portable"); exportReleaseGroup.AddProperty("DebugType", "portable");
releaseGroup.AddProperty("Optimize", "true"); exportReleaseGroup.AddProperty("Optimize", "true");
releaseGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;"); exportReleaseGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;");
releaseGroup.AddProperty("ErrorReport", "prompt"); exportReleaseGroup.AddProperty("ErrorReport", "prompt");
releaseGroup.AddProperty("WarningLevel", "4"); exportReleaseGroup.AddProperty("WarningLevel", "4");
releaseGroup.AddProperty("ConsolePause", "false"); exportReleaseGroup.AddProperty("ConsolePause", "false");
// References // References
var referenceGroup = root.AddItemGroup(); var referenceGroup = root.AddItemGroup();

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using DotNet.Globbing; using DotNet.Globbing;
using Microsoft.Build.Construction; using Microsoft.Build.Construction;
@ -44,6 +45,7 @@ namespace GodotTools.ProjectEditor
globOptions.Evaluation.CaseInsensitive = false; globOptions.Evaluation.CaseInsensitive = false;
var root = ProjectRootElement.Open(projectPath); var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
foreach (var itemGroup in root.ItemGroups) foreach (var itemGroup in root.ItemGroups)
{ {
@ -85,35 +87,35 @@ namespace GodotTools.ProjectEditor
void AddPropertyIfNotPresent(string name, string condition, string value) void AddPropertyIfNotPresent(string name, string condition, string value)
{ {
if (root.PropertyGroups if (root.PropertyGroups
.Any(g => (g.Condition == string.Empty || g.Condition == condition) && .Any(g => (g.Condition == string.Empty || g.Condition.Trim() == condition) &&
g.Properties g.Properties
.Any(p => p.Name == name && .Any(p => p.Name == name &&
p.Value == value && p.Value == value &&
(p.Condition == condition || g.Condition == condition)))) (p.Condition.Trim() == condition || g.Condition.Trim() == condition))))
{ {
return; return;
} }
root.AddProperty(name, value).Condition = condition; root.AddProperty(name, value).Condition = " " + condition + " ";
dirty = true; dirty = true;
} }
AddPropertyIfNotPresent(name: "ApiConfiguration", AddPropertyIfNotPresent(name: "ApiConfiguration",
condition: " '$(Configuration)' != 'Release' ", condition: "'$(Configuration)' != 'ExportRelease'",
value: "Debug"); value: "Debug");
AddPropertyIfNotPresent(name: "ApiConfiguration", AddPropertyIfNotPresent(name: "ApiConfiguration",
condition: " '$(Configuration)' == 'Release' ", condition: "'$(Configuration)' == 'ExportRelease'",
value: "Release"); value: "Release");
void SetReferenceHintPath(string referenceName, string condition, string hintPath) void SetReferenceHintPath(string referenceName, string condition, string hintPath)
{ {
foreach (var itemGroup in root.ItemGroups.Where(g => foreach (var itemGroup in root.ItemGroups.Where(g =>
g.Condition == string.Empty || g.Condition == condition)) g.Condition.Trim() == string.Empty || g.Condition.Trim() == condition))
{ {
var references = itemGroup.Items.Where(item => var references = itemGroup.Items.Where(item =>
item.ItemType == "Reference" && item.ItemType == "Reference" &&
item.Include == referenceName && item.Include == referenceName &&
(item.Condition == condition || itemGroup.Condition == condition)); (item.Condition.Trim() == condition || itemGroup.Condition.Trim() == condition));
var referencesWithHintPath = references.Where(reference => var referencesWithHintPath = references.Where(reference =>
reference.Metadata.Any(m => m.Name == "HintPath")); reference.Metadata.Any(m => m.Name == "HintPath"));
@ -152,7 +154,7 @@ namespace GodotTools.ProjectEditor
} }
// Found no Reference item at all. Add it. // Found no Reference item at all. Add it.
root.AddItem("Reference", referenceName).Condition = condition; root.AddItem("Reference", referenceName).Condition = " " + condition + " ";
dirty = true; dirty = true;
} }
@ -160,7 +162,7 @@ namespace GodotTools.ProjectEditor
const string editorProjectName = "GodotSharpEditor"; const string editorProjectName = "GodotSharpEditor";
const string coreCondition = ""; const string coreCondition = "";
const string editorCondition = " '$(Configuration)' == 'Tools' "; const string editorCondition = "'$(Configuration)' == 'Debug'";
var coreHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{coreProjectName}.dll"; var coreHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{coreProjectName}.dll";
var editorHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{editorProjectName}.dll"; var editorHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{editorProjectName}.dll";
@ -168,6 +170,105 @@ namespace GodotTools.ProjectEditor
SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath); SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath);
SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath); SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath);
if (dirty)
root.Save();
}
public static void MigrateFromOldConfigNames(string projectPath)
{
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
bool dirty = false;
bool hasGodotProjectGeneratorVersion = false;
bool foundOldConfiguration = false;
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition == string.Empty))
{
if (!hasGodotProjectGeneratorVersion && propertyGroup.Properties.Any(p => p.Name == "GodotProjectGeneratorVersion"))
hasGodotProjectGeneratorVersion = true;
foreach (var configItem in propertyGroup.Properties
.Where(p => p.Condition.Trim() == "'$(Configuration)' == ''" && p.Value == "Tools"))
{
configItem.Value = "Debug";
foundOldConfiguration = true;
dirty = true;
}
}
if (!hasGodotProjectGeneratorVersion)
{
root.PropertyGroups.First(g => g.Condition == string.Empty)?
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
dirty = true;
}
if (!foundOldConfiguration)
{
var toolsConditions = new[]
{
"'$(Configuration)|$(Platform)' == 'Tools|AnyCPU'",
"'$(Configuration)|$(Platform)' != 'Tools|AnyCPU'",
"'$(Configuration)' == 'Tools'",
"'$(Configuration)' != 'Tools'"
};
foundOldConfiguration = root.PropertyGroups
.Any(g => toolsConditions.Any(c => c == g.Condition.Trim()));
}
if (foundOldConfiguration)
{
void MigrateConfigurationConditions(string oldConfiguration, string newConfiguration)
{
void MigrateConditions(string oldCondition, string newCondition)
{
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition))
{
propertyGroup.Condition = " " + newCondition + " ";
dirty = true;
}
foreach (var propertyGroup in root.PropertyGroups)
{
foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition))
{
prop.Condition = " " + newCondition + " ";
dirty = true;
}
}
foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition))
{
itemGroup.Condition = " " + newCondition + " ";
dirty = true;
}
foreach (var itemGroup in root.ItemGroups)
{
foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition))
{
item.Condition = " " + newCondition + " ";
dirty = true;
}
}
}
foreach (var op in new[] {"==", "!="})
{
MigrateConditions($"'$(Configuration)|$(Platform)' {op} '{oldConfiguration}|AnyCPU'", $"'$(Configuration)|$(Platform)' {op} '{newConfiguration}|AnyCPU'");
MigrateConditions($"'$(Configuration)' {op} '{oldConfiguration}'", $"'$(Configuration)' {op} '{newConfiguration}'");
}
}
MigrateConfigurationConditions("Debug", "ExportDebug");
MigrateConfigurationConditions("Release", "ExportRelease");
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
}
if (dirty) if (dirty)
root.Save(); root.Save();
} }

View File

@ -166,7 +166,7 @@ namespace GodotTools
Internal.GodotIs32Bits() ? "32" : "64" Internal.GodotIs32Bits() ? "32" : "64"
}; };
bool buildSuccess = BuildManager.BuildProjectBlocking("Tools", godotDefines); bool buildSuccess = BuildManager.BuildProjectBlocking("Debug", godotDefines);
if (!buildSuccess) if (!buildSuccess)
return; return;

View File

@ -166,7 +166,7 @@ namespace GodotTools
// Make sure the API assemblies are up to date before building the project. // Make sure the API assemblies are up to date before building the project.
// We may not have had the chance to update the release API assemblies, and the debug ones // We may not have had the chance to update the release API assemblies, and the debug ones
// may have been deleted by the user at some point after they were loaded by the Godot editor. // may have been deleted by the user at some point after they were loaded by the Godot editor.
string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(config == "Release" ? "Release" : "Debug"); string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(config == "ExportRelease" ? "Release" : "Debug");
if (!string.IsNullOrEmpty(apiAssembliesUpdateError)) if (!string.IsNullOrEmpty(apiAssembliesUpdateError))
{ {
@ -242,7 +242,7 @@ namespace GodotTools
Internal.GodotIs32Bits() ? "32" : "64" Internal.GodotIs32Bits() ? "32" : "64"
}; };
return BuildProjectBlocking("Tools", godotDefines); return BuildProjectBlocking("Debug", godotDefines);
} }
public static void Initialize() public static void Initialize()
@ -256,7 +256,7 @@ namespace GodotTools
: BuildTool.MsBuildVs; : BuildTool.MsBuildVs;
EditorDef("mono/builds/build_tool", msbuild); EditorDef("mono/builds/build_tool", msbuild);
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
{ {
["type"] = Godot.Variant.Type.Int, ["type"] = Godot.Variant.Type.Int,

View File

@ -150,7 +150,7 @@ namespace GodotTools.Export
string outputDir = new FileInfo(path).Directory?.FullName ?? string outputDir = new FileInfo(path).Directory?.FullName ??
throw new FileNotFoundException("Base directory not found"); throw new FileNotFoundException("Base directory not found");
string buildConfig = isDebug ? "Debug" : "Release"; string buildConfig = isDebug ? "ExportDebug" : "ExportRelease";
string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}"); string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}");
CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath); CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath);

View File

@ -61,7 +61,7 @@ namespace GodotTools
{ {
Guid = guid, Guid = guid,
PathRelativeToSolution = name + ".csproj", PathRelativeToSolution = name + ".csproj",
Configs = new List<string> { "Tools", "ExportDebug", "ExportRelease" } Configs = new List<string> { "Debug", "ExportDebug", "ExportRelease" }
}; };
solution.AddNewProject(name, projectInfo); solution.AddNewProject(name, projectInfo);
@ -403,10 +403,15 @@ namespace GodotTools
{ {
try try
{ {
// Migrate solution from old configuration names to: Debug, ExportDebug and ExportRelease
DotNetSolution.MigrateFromOldConfigNames(GodotSharpDirs.ProjectSlnPath);
// Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease
ProjectUtils.MigrateFromOldConfigNames(GodotSharpDirs.ProjectCsProjPath);
// Apply the other fixes after configurations are migrated
// Make sure the existing project has Api assembly references configured correctly // Make sure the existing project has Api assembly references configured correctly
ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath); ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
// Make sure SolutionConfigurations are Tool, ExportDebug and ExportRelease
DotNetSolution.FixConfigurations(GodotSharpDirs.ProjectSlnPath);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -8,8 +8,6 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU