You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-10 13:00:37 +00:00
C#: Support for building with the dotnet CLI
By adding a reference to the 'Microsoft.NETFramework.ReferenceAssemblies' nuget package, we can build projects targeting .NET Framework with the dotnet CLI. By referencing this package we also don't need to install Mono on Linux/macOS or .NET Framework on Windows, as the assemblies are taken from the package.
This commit is contained in:
@@ -15,7 +15,7 @@ def build_godot_tools(source, target, env):
|
|||||||
|
|
||||||
from .solution_builder import build_solution
|
from .solution_builder import build_solution
|
||||||
|
|
||||||
build_solution(env, solution_path, build_config, restore=True)
|
build_solution(env, solution_path, build_config)
|
||||||
# No need to copy targets. The GodotTools csproj takes care of copying them.
|
# No need to copy targets. The GodotTools csproj takes care of copying them.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,29 @@ import os
|
|||||||
verbose = False
|
verbose = False
|
||||||
|
|
||||||
|
|
||||||
def find_msbuild_unix(filename):
|
def find_dotnet_cli():
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
if os.name == "nt":
|
||||||
|
windows_exts = os.environ["PATHEXT"]
|
||||||
|
windows_exts = windows_exts.split(os.pathsep) if windows_exts else []
|
||||||
|
|
||||||
|
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||||
|
hint_dir = hint_dir.strip('"')
|
||||||
|
hint_path = os.path.join(hint_dir, "dotnet")
|
||||||
|
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||||
|
return hint_path
|
||||||
|
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||||
|
return hint_path + ".exe"
|
||||||
|
else:
|
||||||
|
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||||
|
hint_dir = hint_dir.strip('"')
|
||||||
|
hint_path = os.path.join(hint_dir, "dotnet")
|
||||||
|
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||||
|
return hint_path
|
||||||
|
|
||||||
|
|
||||||
|
def find_msbuild_unix():
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -86,15 +108,7 @@ def run_command(command, args, env_override=None, name=None):
|
|||||||
raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode))
|
raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode))
|
||||||
|
|
||||||
|
|
||||||
def nuget_restore(env, *args):
|
def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
|
||||||
global verbose
|
|
||||||
verbose = env["verbose"]
|
|
||||||
|
|
||||||
# Do NuGet restore
|
|
||||||
run_command(nuget_path, ["restore"] + list(args), name="nuget restore")
|
|
||||||
|
|
||||||
|
|
||||||
def build_solution(env, solution_path, build_config, extra_msbuild_args=[], restore=False):
|
|
||||||
global verbose
|
global verbose
|
||||||
verbose = env["verbose"]
|
verbose = env["verbose"]
|
||||||
|
|
||||||
@@ -104,6 +118,14 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[], rest
|
|||||||
if "PLATFORM" in msbuild_env:
|
if "PLATFORM" in msbuild_env:
|
||||||
del msbuild_env["PLATFORM"]
|
del msbuild_env["PLATFORM"]
|
||||||
|
|
||||||
|
msbuild_args = []
|
||||||
|
|
||||||
|
dotnet_cli = find_dotnet_cli()
|
||||||
|
|
||||||
|
if dotnet_cli:
|
||||||
|
msbuild_path = dotnet_cli
|
||||||
|
msbuild_args += ["msbuild"] # `dotnet msbuild` command
|
||||||
|
else:
|
||||||
# Find MSBuild
|
# Find MSBuild
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
msbuild_info = find_msbuild_windows(env)
|
msbuild_info = find_msbuild_windows(env)
|
||||||
@@ -112,7 +134,7 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[], rest
|
|||||||
msbuild_path = msbuild_info[0]
|
msbuild_path = msbuild_info[0]
|
||||||
msbuild_env.update(msbuild_info[1])
|
msbuild_env.update(msbuild_info[1])
|
||||||
else:
|
else:
|
||||||
msbuild_path = find_msbuild_unix("msbuild")
|
msbuild_path = find_msbuild_unix()
|
||||||
if msbuild_path is None:
|
if msbuild_path is None:
|
||||||
raise RuntimeError("Cannot find MSBuild executable")
|
raise RuntimeError("Cannot find MSBuild executable")
|
||||||
|
|
||||||
@@ -120,11 +142,9 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[], rest
|
|||||||
|
|
||||||
# Build solution
|
# Build solution
|
||||||
|
|
||||||
targets = ["Build"]
|
targets = ["Restore", "Build"]
|
||||||
if restore:
|
|
||||||
targets.insert(0, "Restore")
|
|
||||||
|
|
||||||
msbuild_args = [solution_path, "/t:%s" % ",".join(targets), "/p:Configuration=" + build_config]
|
msbuild_args += [solution_path, "/t:%s" % ",".join(targets), "/p:Configuration=" + build_config]
|
||||||
msbuild_args += extra_msbuild_args
|
msbuild_args += extra_msbuild_args
|
||||||
|
|
||||||
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")
|
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")
|
||||||
|
|||||||
@@ -6,18 +6,18 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Build" Version="16.5.0" />
|
<PackageReference Include="Microsoft.Build" Version="16.5.0" />
|
||||||
<PackageReference Include="Microsoft.Build.Runtime" Version="16.5.0" />
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<ItemGroup>
|
||||||
<!--
|
<!--
|
||||||
The 'Microsoft.Build.Runtime' package includes an mscorlib reference assembly in contentFiles.
|
The Microsoft.Build.Runtime package is too problematic so we create a MSBuild.exe stub. The workaround described
|
||||||
This causes our project build to fail. As a workaround, we remove {CandidateAssemblyFiles}
|
here doesn't work with Microsoft.NETFramework.ReferenceAssemblies: https://github.com/microsoft/msbuild/issues/3486
|
||||||
from AssemblySearchPaths as described here: https://github.com/microsoft/msbuild/issues/3486.
|
We need a MSBuild.exe file as there's an issue in Microsoft.Build where it executes platform dependent code when
|
||||||
|
searching for MSBuild.exe before the fallback to not using it. A stub is fine as it should never be executed.
|
||||||
-->
|
-->
|
||||||
<AssemblySearchPaths>$([System.String]::Copy('$(AssemblySearchPaths)').Replace('{CandidateAssemblyFiles}', ''))</AssemblySearchPaths>
|
<None Include="MSBuild.exe" CopyToOutputDirectory="Always" />
|
||||||
<AssemblySearchPaths Condition=" '$(MSBuildRuntimeVersion)' != '' ">$(AssemblySearchPaths.Split(';'))</AssemblySearchPaths>
|
</ItemGroup>
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -125,6 +125,12 @@ namespace GodotTools.ProjectEditor
|
|||||||
// References
|
// References
|
||||||
var referenceGroup = root.AddItemGroup();
|
var referenceGroup = root.AddItemGroup();
|
||||||
referenceGroup.AddItem("Reference", "System");
|
referenceGroup.AddItem("Reference", "System");
|
||||||
|
var frameworkRefAssembliesItem = referenceGroup.AddItem("PackageReference", "Microsoft.NETFramework.ReferenceAssemblies");
|
||||||
|
|
||||||
|
// Use metadata (child nodes) instead of attributes for the PackageReference.
|
||||||
|
// This is for compatibility with 3.2, where GodotTools uses an old Microsoft.Build.
|
||||||
|
frameworkRefAssembliesItem.AddMetadata("Version", "1.0.0");
|
||||||
|
frameworkRefAssembliesItem.AddMetadata("PrivateAssets", "All");
|
||||||
|
|
||||||
root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\"));
|
root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\"));
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ 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.Trim() == condition) &&
|
.Any(g => (string.IsNullOrEmpty(g.Condition) || g.Condition.Trim() == condition) &&
|
||||||
g.Properties
|
g.Properties
|
||||||
.Any(p => p.Name == name &&
|
.Any(p => p.Name == name &&
|
||||||
p.Value == value &&
|
p.Value == value &&
|
||||||
@@ -264,7 +264,7 @@ namespace GodotTools.ProjectEditor
|
|||||||
bool hasGodotProjectGeneratorVersion = false;
|
bool hasGodotProjectGeneratorVersion = false;
|
||||||
bool foundOldConfiguration = false;
|
bool foundOldConfiguration = false;
|
||||||
|
|
||||||
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition == string.Empty))
|
foreach (var propertyGroup in root.PropertyGroups.Where(g => string.IsNullOrEmpty(g.Condition)))
|
||||||
{
|
{
|
||||||
if (!hasGodotProjectGeneratorVersion && propertyGroup.Properties.Any(p => p.Name == "GodotProjectGeneratorVersion"))
|
if (!hasGodotProjectGeneratorVersion && propertyGroup.Properties.Any(p => p.Name == "GodotProjectGeneratorVersion"))
|
||||||
hasGodotProjectGeneratorVersion = true;
|
hasGodotProjectGeneratorVersion = true;
|
||||||
@@ -280,7 +280,7 @@ namespace GodotTools.ProjectEditor
|
|||||||
|
|
||||||
if (!hasGodotProjectGeneratorVersion)
|
if (!hasGodotProjectGeneratorVersion)
|
||||||
{
|
{
|
||||||
root.PropertyGroups.First(g => g.Condition == string.Empty)?
|
root.PropertyGroups.First(g => string.IsNullOrEmpty(g.Condition))?
|
||||||
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||||
project.HasUnsavedChanges = true;
|
project.HasUnsavedChanges = true;
|
||||||
}
|
}
|
||||||
@@ -348,5 +348,25 @@ namespace GodotTools.ProjectEditor
|
|||||||
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
|
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EnsureHasNugetNetFrameworkRefAssemblies(MSBuildProject project)
|
||||||
|
{
|
||||||
|
var root = project.Root;
|
||||||
|
|
||||||
|
bool found = root.ItemGroups.Any(g => string.IsNullOrEmpty(g.Condition) && g.Items.Any(
|
||||||
|
item => item.ItemType == "PackageReference" && item.Include == "Microsoft.NETFramework.ReferenceAssemblies"));
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var frameworkRefAssembliesItem = root.AddItem("PackageReference", "Microsoft.NETFramework.ReferenceAssemblies");
|
||||||
|
|
||||||
|
// Use metadata (child nodes) instead of attributes for the PackageReference.
|
||||||
|
// This is for compatibility with 3.2, where GodotTools uses an old Microsoft.Build.
|
||||||
|
frameworkRefAssembliesItem.AddMetadata("Version", "1.0.0");
|
||||||
|
frameworkRefAssembliesItem.AddMetadata("PrivateAssets", "All");
|
||||||
|
|
||||||
|
project.HasUnsavedChanges = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,6 @@ namespace GodotTools.Build
|
|||||||
{
|
{
|
||||||
public static class BuildSystem
|
public static class BuildSystem
|
||||||
{
|
{
|
||||||
private static string GetMsBuildPath()
|
|
||||||
{
|
|
||||||
string msbuildPath = MsBuildFinder.FindMsBuild();
|
|
||||||
|
|
||||||
if (msbuildPath == null)
|
|
||||||
throw new FileNotFoundException("Cannot find the MSBuild executable.");
|
|
||||||
|
|
||||||
return msbuildPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string MonoWindowsBinDir
|
private static string MonoWindowsBinDir
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -46,8 +36,8 @@ namespace GodotTools.Build
|
|||||||
{
|
{
|
||||||
if (OS.IsWindows)
|
if (OS.IsWindows)
|
||||||
{
|
{
|
||||||
return (BuildManager.BuildTool)EditorSettings.GetSetting("mono/builds/build_tool")
|
return (BuildTool)EditorSettings.GetSetting("mono/builds/build_tool")
|
||||||
== BuildManager.BuildTool.MsBuildMono;
|
== BuildTool.MsBuildMono;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -57,16 +47,21 @@ namespace GodotTools.Build
|
|||||||
private static bool PrintBuildOutput =>
|
private static bool PrintBuildOutput =>
|
||||||
(bool)EditorSettings.GetSetting("mono/builds/print_build_output");
|
(bool)EditorSettings.GetSetting("mono/builds/print_build_output");
|
||||||
|
|
||||||
private static Process LaunchBuild(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
private static Process LaunchBuild(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
||||||
{
|
{
|
||||||
|
(string msbuildPath, BuildTool buildTool) = MsBuildFinder.FindMsBuild();
|
||||||
|
|
||||||
|
if (msbuildPath == null)
|
||||||
|
throw new FileNotFoundException("Cannot find the MSBuild executable.");
|
||||||
|
|
||||||
var customPropertiesList = new List<string>();
|
var customPropertiesList = new List<string>();
|
||||||
|
|
||||||
if (customProperties != null)
|
if (customProperties != null)
|
||||||
customPropertiesList.AddRange(customProperties);
|
customPropertiesList.AddRange(customProperties);
|
||||||
|
|
||||||
string compilerArgs = BuildArguments(solution, config, loggerOutputDir, customPropertiesList);
|
string compilerArgs = BuildArguments(buildTool, solution, targets, config, loggerOutputDir, customPropertiesList);
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo(GetMsBuildPath(), compilerArgs);
|
var startInfo = new ProcessStartInfo(msbuildPath, compilerArgs);
|
||||||
|
|
||||||
bool redirectOutput = !IsDebugMsBuildRequested() && !PrintBuildOutput;
|
bool redirectOutput = !IsDebugMsBuildRequested() && !PrintBuildOutput;
|
||||||
|
|
||||||
@@ -90,7 +85,7 @@ namespace GodotTools.Build
|
|||||||
// Needed when running from Developer Command Prompt for VS
|
// Needed when running from Developer Command Prompt for VS
|
||||||
RemovePlatformVariable(startInfo.EnvironmentVariables);
|
RemovePlatformVariable(startInfo.EnvironmentVariables);
|
||||||
|
|
||||||
var process = new Process { StartInfo = startInfo };
|
var process = new Process {StartInfo = startInfo};
|
||||||
|
|
||||||
process.Start();
|
process.Start();
|
||||||
|
|
||||||
@@ -105,19 +100,19 @@ namespace GodotTools.Build
|
|||||||
|
|
||||||
public static int Build(BuildInfo buildInfo)
|
public static int Build(BuildInfo buildInfo)
|
||||||
{
|
{
|
||||||
return Build(buildInfo.Solution, buildInfo.Configuration,
|
return Build(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration,
|
||||||
buildInfo.LogsDirPath, buildInfo.CustomProperties);
|
buildInfo.LogsDirPath, buildInfo.CustomProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<int> BuildAsync(BuildInfo buildInfo)
|
public static Task<int> BuildAsync(BuildInfo buildInfo)
|
||||||
{
|
{
|
||||||
return BuildAsync(buildInfo.Solution, buildInfo.Configuration,
|
return BuildAsync(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration,
|
||||||
buildInfo.LogsDirPath, buildInfo.CustomProperties);
|
buildInfo.LogsDirPath, buildInfo.CustomProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Build(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
public static int Build(string solution, string[] targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
||||||
{
|
{
|
||||||
using (var process = LaunchBuild(solution, config, loggerOutputDir, customProperties))
|
using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties))
|
||||||
{
|
{
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
|
|
||||||
@@ -125,9 +120,9 @@ namespace GodotTools.Build
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<int> BuildAsync(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
public static async Task<int> BuildAsync(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null)
|
||||||
{
|
{
|
||||||
using (var process = LaunchBuild(solution, config, loggerOutputDir, customProperties))
|
using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties))
|
||||||
{
|
{
|
||||||
await process.WaitForExitAsync();
|
await process.WaitForExitAsync();
|
||||||
|
|
||||||
@@ -135,9 +130,14 @@ namespace GodotTools.Build
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildArguments(string solution, string config, string loggerOutputDir, List<string> customProperties)
|
private static string BuildArguments(BuildTool buildTool, string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties)
|
||||||
{
|
{
|
||||||
string arguments = $@"""{solution}"" /v:normal /t:Build ""/p:{"Configuration=" + config}"" " +
|
string arguments = string.Empty;
|
||||||
|
|
||||||
|
if (buildTool == BuildTool.DotnetCli)
|
||||||
|
arguments += "msbuild "; // `dotnet msbuild` command
|
||||||
|
|
||||||
|
arguments += $@"""{solution}"" /v:normal /t:{string.Join(",", targets)} ""/p:{"Configuration=" + config}"" " +
|
||||||
$@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}""";
|
$@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}""";
|
||||||
|
|
||||||
foreach (string customProperty in customProperties)
|
foreach (string customProperty in customProperties)
|
||||||
|
|||||||
10
modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs
Normal file
10
modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace GodotTools.Build
|
||||||
|
{
|
||||||
|
public enum BuildTool
|
||||||
|
{
|
||||||
|
MsBuildMono,
|
||||||
|
MsBuildVs,
|
||||||
|
JetBrainsMsBuild,
|
||||||
|
DotnetCli
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,16 +17,24 @@ namespace GodotTools.Build
|
|||||||
private static string _msbuildToolsPath = string.Empty;
|
private static string _msbuildToolsPath = string.Empty;
|
||||||
private static string _msbuildUnixPath = string.Empty;
|
private static string _msbuildUnixPath = string.Empty;
|
||||||
|
|
||||||
public static string FindMsBuild()
|
public static (string, BuildTool) FindMsBuild()
|
||||||
{
|
{
|
||||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||||
var buildTool = (BuildManager.BuildTool)editorSettings.GetSetting("mono/builds/build_tool");
|
var buildTool = (BuildTool)editorSettings.GetSetting("mono/builds/build_tool");
|
||||||
|
|
||||||
if (OS.IsWindows)
|
if (OS.IsWindows)
|
||||||
{
|
{
|
||||||
switch (buildTool)
|
switch (buildTool)
|
||||||
{
|
{
|
||||||
case BuildManager.BuildTool.MsBuildVs:
|
case BuildTool.DotnetCli:
|
||||||
|
{
|
||||||
|
string dotnetCliPath = OS.PathWhich("dotnet");
|
||||||
|
if (!string.IsNullOrEmpty(dotnetCliPath))
|
||||||
|
return (dotnetCliPath, BuildTool.DotnetCli);
|
||||||
|
GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Visual Studio.");
|
||||||
|
goto case BuildTool.MsBuildVs;
|
||||||
|
}
|
||||||
|
case BuildTool.MsBuildVs:
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_msbuildToolsPath) || !File.Exists(_msbuildToolsPath))
|
if (string.IsNullOrEmpty(_msbuildToolsPath) || !File.Exists(_msbuildToolsPath))
|
||||||
{
|
{
|
||||||
@@ -40,18 +48,18 @@ namespace GodotTools.Build
|
|||||||
if (!_msbuildToolsPath.EndsWith("\\"))
|
if (!_msbuildToolsPath.EndsWith("\\"))
|
||||||
_msbuildToolsPath += "\\";
|
_msbuildToolsPath += "\\";
|
||||||
|
|
||||||
return Path.Combine(_msbuildToolsPath, "MSBuild.exe");
|
return (Path.Combine(_msbuildToolsPath, "MSBuild.exe"), BuildTool.MsBuildVs);
|
||||||
}
|
}
|
||||||
case BuildManager.BuildTool.MsBuildMono:
|
case BuildTool.MsBuildMono:
|
||||||
{
|
{
|
||||||
string msbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "msbuild.bat");
|
string msbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "msbuild.bat");
|
||||||
|
|
||||||
if (!File.Exists(msbuildPath))
|
if (!File.Exists(msbuildPath))
|
||||||
throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildMono}'. Tried with path: {msbuildPath}");
|
throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildMono}'. Tried with path: {msbuildPath}");
|
||||||
|
|
||||||
return msbuildPath;
|
return (msbuildPath, BuildTool.MsBuildMono);
|
||||||
}
|
}
|
||||||
case BuildManager.BuildTool.JetBrainsMsBuild:
|
case BuildTool.JetBrainsMsBuild:
|
||||||
{
|
{
|
||||||
var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName);
|
var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName);
|
||||||
|
|
||||||
@@ -65,7 +73,7 @@ namespace GodotTools.Build
|
|||||||
if (!File.Exists(msbuildPath))
|
if (!File.Exists(msbuildPath))
|
||||||
throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildJetBrains}'. Tried with path: {msbuildPath}");
|
throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildJetBrains}'. Tried with path: {msbuildPath}");
|
||||||
|
|
||||||
return msbuildPath;
|
return (msbuildPath, BuildTool.JetBrainsMsBuild);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
||||||
@@ -74,7 +82,17 @@ namespace GodotTools.Build
|
|||||||
|
|
||||||
if (OS.IsUnixLike)
|
if (OS.IsUnixLike)
|
||||||
{
|
{
|
||||||
if (buildTool == BuildManager.BuildTool.MsBuildMono)
|
switch (buildTool)
|
||||||
|
{
|
||||||
|
case BuildTool.DotnetCli:
|
||||||
|
{
|
||||||
|
string dotnetCliPath = OS.PathWhich("dotnet");
|
||||||
|
if (!string.IsNullOrEmpty(dotnetCliPath))
|
||||||
|
return (dotnetCliPath, BuildTool.DotnetCli);
|
||||||
|
GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Mono.");
|
||||||
|
goto case BuildTool.MsBuildMono;
|
||||||
|
}
|
||||||
|
case BuildTool.MsBuildMono:
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_msbuildUnixPath) || !File.Exists(_msbuildUnixPath))
|
if (string.IsNullOrEmpty(_msbuildUnixPath) || !File.Exists(_msbuildUnixPath))
|
||||||
{
|
{
|
||||||
@@ -85,11 +103,12 @@ namespace GodotTools.Build
|
|||||||
if (string.IsNullOrEmpty(_msbuildUnixPath))
|
if (string.IsNullOrEmpty(_msbuildUnixPath))
|
||||||
throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMSBuildMono}'");
|
throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMSBuildMono}'");
|
||||||
|
|
||||||
return _msbuildUnixPath;
|
return (_msbuildUnixPath, BuildTool.MsBuildMono);
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace GodotTools
|
|||||||
public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization
|
public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization
|
||||||
{
|
{
|
||||||
public string Solution { get; }
|
public string Solution { get; }
|
||||||
|
public string[] Targets { get; }
|
||||||
public string Configuration { get; }
|
public string Configuration { get; }
|
||||||
public Array<string> CustomProperties { get; } = new Array<string>(); // TODO Use List once we have proper serialization
|
public Array<string> CustomProperties { get; } = new Array<string>(); // TODO Use List once we have proper serialization
|
||||||
|
|
||||||
@@ -38,9 +39,10 @@ namespace GodotTools
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuildInfo(string solution, string configuration)
|
public BuildInfo(string solution, string[] targets, string configuration)
|
||||||
{
|
{
|
||||||
Solution = solution;
|
Solution = solution;
|
||||||
|
Targets = targets;
|
||||||
Configuration = configuration;
|
Configuration = configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,11 @@ namespace GodotTools
|
|||||||
public const string PropNameMSBuildMono = "MSBuild (Mono)";
|
public const string PropNameMSBuildMono = "MSBuild (Mono)";
|
||||||
public const string PropNameMSBuildVs = "MSBuild (VS Build Tools)";
|
public const string PropNameMSBuildVs = "MSBuild (VS Build Tools)";
|
||||||
public const string PropNameMSBuildJetBrains = "MSBuild (JetBrains Rider)";
|
public const string PropNameMSBuildJetBrains = "MSBuild (JetBrains Rider)";
|
||||||
|
public const string PropNameDotnetCli = "dotnet CLI";
|
||||||
|
|
||||||
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
|
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
|
||||||
public const string MsBuildLogFileName = "msbuild_log.txt";
|
public const string MsBuildLogFileName = "msbuild_log.txt";
|
||||||
|
|
||||||
public enum BuildTool
|
|
||||||
{
|
|
||||||
MsBuildMono,
|
|
||||||
MsBuildVs,
|
|
||||||
JetBrainsMsBuild
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
|
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
|
||||||
{
|
{
|
||||||
var issuesFile = GetIssuesFilePath(buildInfo);
|
var issuesFile = GetIssuesFilePath(buildInfo);
|
||||||
@@ -181,10 +175,12 @@ namespace GodotTools
|
|||||||
{
|
{
|
||||||
pr.Step("Building project solution", 0);
|
pr.Step("Building project solution", 0);
|
||||||
|
|
||||||
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, config);
|
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets: new[] {"Restore", "Build"}, config);
|
||||||
|
|
||||||
|
bool escapeNeedsDoubleBackslash = buildTool == BuildTool.MsBuildMono || buildTool == BuildTool.DotnetCli;
|
||||||
|
|
||||||
// Add Godot defines
|
// Add Godot defines
|
||||||
string constants = buildTool != BuildTool.MsBuildMono ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
|
string constants = !escapeNeedsDoubleBackslash ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
|
||||||
|
|
||||||
foreach (var godotDefine in godotDefines)
|
foreach (var godotDefine in godotDefines)
|
||||||
constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};";
|
constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};";
|
||||||
@@ -192,7 +188,7 @@ namespace GodotTools
|
|||||||
if (Internal.GodotIsRealTDouble())
|
if (Internal.GodotIsRealTDouble())
|
||||||
constants += "GODOT_REAL_T_IS_DOUBLE;";
|
constants += "GODOT_REAL_T_IS_DOUBLE;";
|
||||||
|
|
||||||
constants += buildTool != BuildTool.MsBuildMono ? "\"" : "\\\"";
|
constants += !escapeNeedsDoubleBackslash ? "\"" : "\\\"";
|
||||||
|
|
||||||
buildInfo.CustomProperties.Add(constants);
|
buildInfo.CustomProperties.Add(constants);
|
||||||
|
|
||||||
@@ -250,20 +246,44 @@ namespace GodotTools
|
|||||||
{
|
{
|
||||||
// Build tool settings
|
// Build tool settings
|
||||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||||
var msbuild = BuildTool.MsBuildMono;
|
|
||||||
if (OS.IsWindows)
|
|
||||||
msbuild = RiderPathManager.IsExternalEditorSetToRider(editorSettings) ? BuildTool.JetBrainsMsBuild : BuildTool.MsBuildVs;
|
|
||||||
|
|
||||||
EditorDef("mono/builds/build_tool", msbuild);
|
BuildTool msbuildDefault;
|
||||||
|
|
||||||
|
if (OS.IsWindows)
|
||||||
|
{
|
||||||
|
if (RiderPathManager.IsExternalEditorSetToRider(editorSettings))
|
||||||
|
msbuildDefault = BuildTool.JetBrainsMsBuild;
|
||||||
|
else
|
||||||
|
msbuildDefault = !string.IsNullOrEmpty(OS.PathWhich("dotnet")) ? BuildTool.DotnetCli : BuildTool.MsBuildVs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msbuildDefault = !string.IsNullOrEmpty(OS.PathWhich("dotnet")) ? BuildTool.DotnetCli : BuildTool.MsBuildMono;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorDef("mono/builds/build_tool", msbuildDefault);
|
||||||
|
|
||||||
|
string hintString;
|
||||||
|
|
||||||
|
if (OS.IsWindows)
|
||||||
|
{
|
||||||
|
hintString = $"{PropNameMSBuildMono}:{(int)BuildTool.MsBuildMono}," +
|
||||||
|
$"{PropNameMSBuildVs}:{(int)BuildTool.MsBuildVs}," +
|
||||||
|
$"{PropNameMSBuildJetBrains}:{(int)BuildTool.JetBrainsMsBuild}," +
|
||||||
|
$"{PropNameDotnetCli}:{(int)BuildTool.DotnetCli}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hintString = $"{PropNameMSBuildMono}:{(int)BuildTool.MsBuildMono}," +
|
||||||
|
$"{PropNameDotnetCli}:{(int)BuildTool.DotnetCli}";
|
||||||
|
}
|
||||||
|
|
||||||
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||||
{
|
{
|
||||||
["type"] = Godot.Variant.Type.Int,
|
["type"] = Godot.Variant.Type.Int,
|
||||||
["name"] = "mono/builds/build_tool",
|
["name"] = "mono/builds/build_tool",
|
||||||
["hint"] = Godot.PropertyHint.Enum,
|
["hint"] = Godot.PropertyHint.Enum,
|
||||||
["hint_string"] = OS.IsWindows ?
|
["hint_string"] = hintString
|
||||||
$"{PropNameMSBuildMono},{PropNameMSBuildVs},{PropNameMSBuildJetBrains}" :
|
|
||||||
$"{PropNameMSBuildMono}"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EditorDef("mono/builds/print_build_output", false);
|
EditorDef("mono/builds/print_build_output", false);
|
||||||
|
|||||||
@@ -461,6 +461,9 @@ namespace GodotTools
|
|||||||
// Make sure the existing project has Api assembly references configured correctly
|
// Make sure the existing project has Api assembly references configured correctly
|
||||||
ProjectUtils.FixApiHintPath(msbuildProject);
|
ProjectUtils.FixApiHintPath(msbuildProject);
|
||||||
|
|
||||||
|
// Make sure the existing project references the Microsoft.NETFramework.ReferenceAssemblies nuget package
|
||||||
|
ProjectUtils.EnsureHasNugetNetFrameworkRefAssemblies(msbuildProject);
|
||||||
|
|
||||||
if (msbuildProject.HasUnsavedChanges)
|
if (msbuildProject.HasUnsavedChanges)
|
||||||
{
|
{
|
||||||
// Save a copy of the project before replacing it
|
// Save a copy of the project before replacing it
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<Reference Include="GodotSharp">
|
<Reference Include="GodotSharp">
|
||||||
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
<ConsolePause>false</ConsolePause>
|
<ConsolePause>false</ConsolePause>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
<ConsolePause>false</ConsolePause>
|
<ConsolePause>false</ConsolePause>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user