Browse Source

[3.2] 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.
Ignacio Etcheverry 5 years ago
parent
commit
3928fe200f
22 changed files with 231 additions and 435 deletions
  1. 1 1
      modules/mono/build_scripts/godot_tools_build.py
  2. 44 24
      modules/mono/build_scripts/solution_builder.py
  3. 4 49
      modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj
  4. 0 35
      modules/mono/editor/GodotTools/GodotTools.BuildLogger/Properties/AssemblyInfo.cs
  5. 3 32
      modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
  6. 0 26
      modules/mono/editor/GodotTools/GodotTools.Core/Properties/AssemblyInfo.cs
  7. 5 46
      modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
  8. 6 0
      modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
  9. 23 3
      modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
  10. 0 27
      modules/mono/editor/GodotTools/GodotTools.ProjectEditor/Properties/AssemblyInfo.cs
  11. 0 4
      modules/mono/editor/GodotTools/GodotTools.ProjectEditor/packages.config
  12. 26 26
      modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
  13. 10 0
      modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs
  14. 48 24
      modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
  15. 3 1
      modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs
  16. 39 21
      modules/mono/editor/GodotTools/GodotTools/BuildManager.cs
  17. 3 0
      modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
  18. 14 84
      modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
  19. 0 26
      modules/mono/editor/GodotTools/GodotTools/Properties/AssemblyInfo.cs
  20. 0 6
      modules/mono/editor/GodotTools/GodotTools/packages.config
  21. 1 0
      modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
  22. 1 0
      modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj

+ 1 - 1
modules/mono/build_scripts/godot_tools_build.py

@@ -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.
 
 
 
 

+ 44 - 24
modules/mono/build_scripts/solution_builder.py

@@ -5,7 +5,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):
-    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):
+def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
     global verbose
     global verbose
     verbose = env['verbose']
     verbose = env['verbose']
 
 
@@ -104,27 +118,33 @@ 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']
 
 
-    # Find MSBuild
-    if os.name == 'nt':
-        msbuild_info = find_msbuild_windows(env)
-        if msbuild_info is None:
-            raise RuntimeError('Cannot find MSBuild executable')
-        msbuild_path = msbuild_info[0]
-        msbuild_env.update(msbuild_info[1])
+    msbuild_args = []
+
+    dotnet_cli = find_dotnet_cli()
+
+    if dotnet_cli:
+        msbuild_path = dotnet_cli
+        msbuild_args += ["msbuild"] # `dotnet msbuild` command
     else:
     else:
-        msbuild_path = find_msbuild_unix('msbuild')
-        if msbuild_path is None:
-            raise RuntimeError("Cannot find MSBuild executable")
+        # Find MSBuild
+        if os.name == "nt":
+            msbuild_info = find_msbuild_windows(env)
+            if msbuild_info is None:
+                raise RuntimeError("Cannot find MSBuild executable")
+            msbuild_path = msbuild_info[0]
+            msbuild_env.update(msbuild_info[1])
+        else:
+            msbuild_path = find_msbuild_unix()
+            if msbuild_path is None:
+                raise RuntimeError("Cannot find MSBuild executable")
 
 
     print('MSBuild path: ' + msbuild_path)
     print('MSBuild path: ' + msbuild_path)
 
 
     # Build solution
     # Build solution
 
 
-    targets = ["Build"]
-    if restore:
-        targets.insert(0, "Restore")
+    targets = ["Restore", "Build"]
 
 
-    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')

+ 4 - 49
modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj

@@ -1,60 +1,15 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid>
     <ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid>
     <OutputType>Library</OutputType>
     <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>GodotTools.BuildLogger</RootNamespace>
-    <AssemblyName>GodotTools.BuildLogger</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
+    <TargetFramework>net472</TargetFramework>
     <LangVersion>7</LangVersion>
     <LangVersion>7</LangVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>portable</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>portable</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="Microsoft.Build.Framework" />
     <Reference Include="Microsoft.Build.Framework" />
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="GodotBuildLogger.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
+    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj">
-      <Project>{639e48bd-44e5-4091-8edd-22d36dc0768d}</Project>
-      <Name>GodotTools.Core</Name>
-    </ProjectReference>
+    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
   </ItemGroup>
   </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
-         Other similar extension points exist, see Microsoft.Common.targets.
-    <Target Name="BeforeBuild">
-    </Target>
-    <Target Name="AfterBuild">
-    </Target>
-    -->
 </Project>
 </Project>

+ 0 - 35
modules/mono/editor/GodotTools/GodotTools.BuildLogger/Properties/AssemblyInfo.cs

@@ -1,35 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("GodotTools.BuildLogger")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("Godot Engine contributors")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("6CE9A984-37B1-4F8A-8FE9-609F05F071B3")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 3 - 32
modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj

@@ -1,40 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
     <ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
     <OutputType>Library</OutputType>
     <OutputType>Library</OutputType>
-    <RootNamespace>GodotTools.Core</RootNamespace>
-    <AssemblyName>GodotTools.Core</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
+    <TargetFramework>net472</TargetFramework>
     <LangVersion>7</LangVersion>
     <LangVersion>7</LangVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-  </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <Compile Include="FileUtils.cs" />
-    <Compile Include="ProcessExtensions.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="StringExtensions.cs" />
+    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
 </Project>

+ 0 - 26
modules/mono/editor/GodotTools/GodotTools.Core/Properties/AssemblyInfo.cs

@@ -1,26 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-
-[assembly: AssemblyTitle("GodotTools.Core")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("Godot Engine contributors")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-
-[assembly: AssemblyVersion("1.0.*")]
-
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]

+ 5 - 46
modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj

@@ -1,57 +1,16 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
     <ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
     <OutputType>Library</OutputType>
     <OutputType>Library</OutputType>
-    <RootNamespace>GodotTools.ProjectEditor</RootNamespace>
-    <AssemblyName>GodotTools.ProjectEditor</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <BaseIntermediateOutputPath>obj</BaseIntermediateOutputPath>
+    <TargetFramework>net472</TargetFramework>
     <LangVersion>7</LangVersion>
     <LangVersion>7</LangVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>portable</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
-    <Reference Include="System" />
     <Reference Include="Microsoft.Build" />
     <Reference Include="Microsoft.Build" />
-    <Reference Include="DotNet.Glob, Version=2.1.1.0, Culture=neutral, PublicKeyToken=b68cc888b4f632d1, processorArchitecture=MSIL">
-      <HintPath>$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="ApiAssembliesInfo.cs" />
-    <Compile Include="DotNetSolution.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="IdentifierUtils.cs" />
-    <Compile Include="ProjectExtensions.cs" />
-    <Compile Include="ProjectGenerator.cs" />
-    <Compile Include="ProjectUtils.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
+    <PackageReference Include="DotNet.Glob" Version="2.1.1" />
+    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj">
-      <Project>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</Project>
-      <Name>GodotTools.Core</Name>
-    </ProjectReference>
+    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
   </ItemGroup>
   </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
 </Project>

+ 6 - 0
modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs

@@ -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("/", "\\"));
 
 

+ 23 - 3
modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs

@@ -176,7 +176,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 &&
@@ -267,7 +267,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;
@@ -283,7 +283,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;
             }
             }
@@ -351,5 +351,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;
+        }
     }
     }
 }
 }

+ 0 - 27
modules/mono/editor/GodotTools/GodotTools.ProjectEditor/Properties/AssemblyInfo.cs

@@ -1,27 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-
-[assembly: AssemblyTitle("GodotTools.ProjectEditor")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("Godot Engine contributors")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-
-[assembly: AssemblyVersion("1.0.*")]
-
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-

+ 0 - 4
modules/mono/editor/GodotTools/GodotTools.ProjectEditor/packages.config

@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="DotNet.Glob" version="2.1.1" targetFramework="net45" />
-</packages>

+ 26 - 26
modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs

@@ -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")
-                           == BuildManager.BuildTool.MsBuildMono;
+                    return (BuildTool)EditorSettings.GetSetting("mono/builds/build_tool")
+                           == 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 async Task<int> BuildAsync(BuildInfo buildInfo)
+        public static Task<int> BuildAsync(BuildInfo buildInfo)
         {
         {
-            return await 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,10 +130,15 @@ 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}"" " +
-                               $@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}""";
+            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}""";
 
 
             foreach (string customProperty in customProperties)
             foreach (string customProperty in customProperties)
             {
             {

+ 10 - 0
modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs

@@ -0,0 +1,10 @@
+namespace GodotTools.Build
+{
+    public enum BuildTool
+    {
+        MsBuildMono,
+        MsBuildVs,
+        JetBrainsMsBuild,
+        DotnetCli
+    }
+}

+ 48 - 24
modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs

@@ -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 (_msbuildToolsPath.Empty() || !File.Exists(_msbuildToolsPath))
                         if (_msbuildToolsPath.Empty() || !File.Exists(_msbuildToolsPath))
                         {
                         {
@@ -35,32 +43,41 @@ namespace GodotTools.Build
 
 
                             if (_msbuildToolsPath.Empty())
                             if (_msbuildToolsPath.Empty())
                             {
                             {
-                                throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMsbuildVs}'.");
+                                throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildVs}'.");
                             }
                             }
                         }
                         }
 
 
                         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);
                         if (!File.Exists(editorPath))
                         if (!File.Exists(editorPath))
                             throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}");
                             throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}");
-                        var riderDir = new FileInfo(editorPath).Directory.Parent;
-                        return Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe");
+
+                        var riderDir = new FileInfo(editorPath).Directory?.Parent;
+
+                        string msbuildPath = Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe");
+
+                        if (!File.Exists(msbuildPath))
+                            throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildJetBrains}'. Tried with path: {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");
                 }
                 }
@@ -68,24 +85,31 @@ namespace GodotTools.Build
 
 
             if (OS.IsUnixLike())
             if (OS.IsUnixLike())
             {
             {
-                if (buildTool == BuildManager.BuildTool.MsBuildMono)
+                switch (buildTool)
                 {
                 {
-                    if (_msbuildUnixPath.Empty() || !File.Exists(_msbuildUnixPath))
+                    case BuildTool.DotnetCli:
                     {
                     {
-                        // Try to search it again if it wasn't found last time or if it was removed from its location
-                        _msbuildUnixPath = FindBuildEngineOnUnix("msbuild");
+                        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;
                     }
                     }
-
-                    if (_msbuildUnixPath.Empty())
+                    case BuildTool.MsBuildMono:
                     {
                     {
-                        throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMsbuildMono}'");
-                    }
+                        if (string.IsNullOrEmpty(_msbuildUnixPath) || !File.Exists(_msbuildUnixPath))
+                        {
+                            // Try to search it again if it wasn't found last time or if it was removed from its location
+                            _msbuildUnixPath = FindBuildEngineOnUnix("msbuild");
+                        }
 
 
-                    return _msbuildUnixPath;
-                }
-                else
-                {
-                    throw new IndexOutOfRangeException("Invalid build tool in editor settings");
+                        if (string.IsNullOrEmpty(_msbuildUnixPath))
+                            throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMSBuildMono}'");
+
+                        return (_msbuildUnixPath, BuildTool.MsBuildMono);
+                    }
+                    default:
+                        throw new IndexOutOfRangeException("Invalid build tool in editor settings");
                 }
                 }
             }
             }
 
 

+ 3 - 1
modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs

@@ -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;
         }
         }
     }
     }

+ 39 - 21
modules/mono/editor/GodotTools/GodotTools/BuildManager.cs

@@ -15,20 +15,14 @@ namespace GodotTools
     {
     {
         private static readonly List<BuildInfo> BuildsInProgress = new List<BuildInfo>();
         private static readonly List<BuildInfo> BuildsInProgress = new List<BuildInfo>();
 
 
-        public const string PropNameMsbuildMono = "MSBuild (Mono)";
-        public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)";
-        public const string PropNameMsbuildJetBrains = "MSBuild (JetBrains Rider)";
+        public const string PropNameMSBuildMono = "MSBuild (Mono)";
+        public const string PropNameMSBuildVs = "MSBuild (VS Build Tools)";
+        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, 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,22 +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;
+
+            BuildTool msbuildDefault;
+
             if (OS.IsWindows)
             if (OS.IsWindows)
-                msbuild = RiderPathManager.IsExternalEditorSetToRider(editorSettings)
-                        ? BuildTool.JetBrainsMsBuild
-                        : BuildTool.MsBuildVs;
+            {
+                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);
 
 
-            EditorDef("mono/builds/build_tool", msbuild);
+            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 ?
-                    $"{PropNameMsbuildMono},{PropNameMsbuildVs},{PropNameMsbuildJetBrains}" :
-                    $"{PropNameMsbuildMono}"
+                ["hint_string"] = hintString
             });
             });
 
 
             EditorDef("mono/builds/print_build_output", false);
             EditorDef("mono/builds/print_build_output", false);

+ 3 - 0
modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs

@@ -471,6 +471,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

+ 14 - 84
modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj

@@ -1,13 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
     <ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
     <OutputType>Library</OutputType>
     <OutputType>Library</OutputType>
-    <RootNamespace>GodotTools</RootNamespace>
-    <AssemblyName>GodotTools</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
+    <TargetFramework>net472</TargetFramework>
+    <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
+    <DataDirToolsOutputPath>$(GodotSourceRootPath)/bin/GodotSharp/Tools</DataDirToolsOutputPath>
+    <GodotApiConfiguration>Debug</GodotApiConfiguration>
     <LangVersion>7</LangVersion>
     <LangVersion>7</LangVersion>
     <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies -->
     <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies -->
     <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
     <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
@@ -18,36 +16,14 @@
     <!-- The project is part of the Godot source tree -->
     <!-- The project is part of the Godot source tree -->
     <!-- Use the Godot source tree output folder instead of '$(ProjectDir)/bin' -->
     <!-- Use the Godot source tree output folder instead of '$(ProjectDir)/bin' -->
     <OutputPath>$(GodotOutputDataDir)/Tools</OutputPath>
     <OutputPath>$(GodotOutputDataDir)/Tools</OutputPath>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>portable</DebugType>
-    <Optimize>false</Optimize>
-    <DefineConstants>DEBUG;</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <Optimize>true</Optimize>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
+    <!-- Must not append '$(TargetFramework)' to the output path in this case -->
+    <AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
-    <Reference Include="GodotTools.IdeMessaging, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\packages\GodotTools.IdeMessaging.1.1.0\lib\netstandard2.0\GodotTools.IdeMessaging.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="JetBrains.Annotations, Version=2019.1.3.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325">
-      <HintPath>..\packages\JetBrains.Annotations.2019.1.3\lib\net20\JetBrains.Annotations.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
-      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System" />
+    <PackageReference Include="GodotTools.IdeMessaging" Version="1.1.0" />
+    <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" />
     <Reference Include="GodotSharp">
     <Reference Include="GodotSharp">
       <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
       <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
       <Private>False</Private>
       <Private>False</Private>
@@ -58,54 +34,8 @@
     </Reference>
     </Reference>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <Compile Include="Build\MsBuildFinder.cs" />
-    <Compile Include="Export\AotBuilder.cs" />
-    <Compile Include="Export\ExportPlugin.cs" />
-    <Compile Include="Export\XcodeHelper.cs" />
-    <Compile Include="ExternalEditorId.cs" />
-    <Compile Include="Ides\GodotIdeManager.cs" />
-    <Compile Include="Ides\MessagingServer.cs" />
-    <Compile Include="Ides\MonoDevelop\EditorId.cs" />
-    <Compile Include="Ides\MonoDevelop\Instance.cs" />
-    <Compile Include="Ides\Rider\RiderPathLocator.cs" />
-    <Compile Include="Ides\Rider\RiderPathManager.cs" />
-    <Compile Include="Internals\EditorProgress.cs" />
-    <Compile Include="Internals\GodotSharpDirs.cs" />
-    <Compile Include="Internals\Internal.cs" />
-    <Compile Include="Internals\ScriptClassParser.cs" />
-    <Compile Include="Internals\Globals.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Build\BuildSystem.cs" />
-    <Compile Include="Utils\Directory.cs" />
-    <Compile Include="Utils\File.cs" />
-    <Compile Include="Utils\OS.cs" />
-    <Compile Include="GodotSharpEditor.cs" />
-    <Compile Include="BuildManager.cs" />
-    <Compile Include="HotReloadAssemblyWatcher.cs" />
-    <Compile Include="BuildInfo.cs" />
-    <Compile Include="BuildTab.cs" />
-    <Compile Include="BottomPanel.cs" />
-    <Compile Include="CsProjOperations.cs" />
-    <Compile Include="PlaySettings.cs" />
-    <Compile Include="Utils\CollectionExtensions.cs" />
-    <Compile Include="Utils\User32Dll.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj">
-      <Project>{6ce9a984-37b1-4f8a-8fe9-609f05f071b3}</Project>
-      <Name>GodotTools.BuildLogger</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj">
-      <Project>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</Project>
-      <Name>GodotTools.ProjectEditor</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj">
-      <Project>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</Project>
-      <Name>GodotTools.Core</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
+    <ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj" />
+    <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" />
+    <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
   </ItemGroup>
   </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
 </Project>

+ 0 - 26
modules/mono/editor/GodotTools/GodotTools/Properties/AssemblyInfo.cs

@@ -1,26 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-
-[assembly: AssemblyTitle("GodotTools")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("Godot Engine contributors")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-
-[assembly: AssemblyVersion("1.0.*")]
-
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]

+ 0 - 6
modules/mono/editor/GodotTools/GodotTools/packages.config

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="GodotTools.IdeMessaging" version="1.1.0" targetFramework="net47" />
-  <package id="JetBrains.Annotations" version="2019.1.3" targetFramework="net45" />
-  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
-</packages>

+ 1 - 0
modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj

@@ -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>

+ 1 - 0
modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj

@@ -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>