diff --git a/src/generate-frameworks-constants/generate-frameworks-constants.csproj b/src/generate-frameworks-constants/generate-frameworks-constants.csproj
index d0edfe68ae18..43e3b74d9191 100644
--- a/src/generate-frameworks-constants/generate-frameworks-constants.csproj
+++ b/src/generate-frameworks-constants/generate-frameworks-constants.csproj
@@ -9,6 +9,7 @@
generate-frameworks-constants
v4.7.2
bin\$(Configuration)
+ default
true
diff --git a/tests/mtouch/Cache.cs b/tests/mtouch/Cache.cs
index 75e6fd655faa..5ce3bfa21cef 100644
--- a/tests/mtouch/Cache.cs
+++ b/tests/mtouch/Cache.cs
@@ -4,6 +4,8 @@
using System.Runtime.InteropServices;
using System.Threading;
+#nullable disable
+
namespace Xamarin
{
// A class that creates temporary directories next to the test assembly, and cleans the output on startup
diff --git a/tools/common/Execution.cs b/tools/common/Execution.cs
index 040bdb79f005..472ad106df86 100644
--- a/tools/common/Execution.cs
+++ b/tools/common/Execution.cs
@@ -16,6 +16,8 @@
using System.Threading;
using System.Threading.Tasks;
+#nullable disable
+
namespace Xamarin.Utils {
public class Execution {
public string FileName;
diff --git a/tools/common/StringUtils.cs b/tools/common/StringUtils.cs
index baf9fef5df31..8b09d4913111 100644
--- a/tools/common/StringUtils.cs
+++ b/tools/common/StringUtils.cs
@@ -3,6 +3,8 @@
using System.Linq;
using System.Text;
+#nullable disable
+
namespace Xamarin.Utils {
internal class StringUtils {
static StringUtils ()
diff --git a/tools/nnyeah/nnyeah.sln b/tools/nnyeah/nnyeah.sln
index 0aa4738a4944..0e798d57cb1e 100644
--- a/tools/nnyeah/nnyeah.sln
+++ b/tools/nnyeah/nnyeah.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.810.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nnyeah", "nnyeah\nnyeah.csproj", "{772B2205-5CFA-41A0-ACB5-A98301BC86FD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nnyeah-tests", "tests\nnyeah-tests.csproj", "{0CDCFD15-98C0-4669-A00B-E5287086D606}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{772B2205-5CFA-41A0-ACB5-A98301BC86FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CDCFD15-98C0-4669-A00B-E5287086D606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CDCFD15-98C0-4669-A00B-E5287086D606}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CDCFD15-98C0-4669-A00B-E5287086D606}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CDCFD15-98C0-4669-A00B-E5287086D606}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/tools/nnyeah/tests/CompileALibrary.cs b/tools/nnyeah/tests/CompileALibrary.cs
new file mode 100644
index 000000000000..41ac1e669cd9
--- /dev/null
+++ b/tools/nnyeah/tests/CompileALibrary.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+using Xamarin;
+
+namespace Microsoft.MaciOS.Nnyeah.Tests.SmokeTests {
+ [TestFixture]
+ public class CompileALibrary {
+ [Test]
+ public async Task BasicLibrary ()
+ {
+ var dir = Cache.CreateTemporaryDirectory ("BasicLibrary");
+ var code = @"
+using System;
+public class Foo {
+ public nint Ident (nint e) => e;
+}
+";
+ var output = await TestRunning.BuildLibrary (code, "NoName", dir);
+ var expectedOutputFile = Path.Combine (dir, "NoName.dll");
+ Assert.IsTrue (File.Exists (expectedOutputFile));
+ }
+
+ [Test]
+ public void BasicExecutable ()
+ {
+ var dir = Cache.CreateTemporaryDirectory ("BasicExecutable");
+ }
+ }
+}
diff --git a/tools/nnyeah/tests/nnyeah-tests.csproj b/tools/nnyeah/tests/nnyeah-tests.csproj
new file mode 100644
index 000000000000..fb76a5e54e38
--- /dev/null
+++ b/tools/nnyeah/tests/nnyeah-tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net6.0
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/nnyeah/tests/utils/Compiler.cs b/tools/nnyeah/tests/utils/Compiler.cs
new file mode 100644
index 000000000000..34548f277b9d
--- /dev/null
+++ b/tools/nnyeah/tests/utils/Compiler.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Text;
+using System.IO;
+using System.Threading.Tasks;
+
+using Xamarin;
+using Xamarin.Utils;
+using System.Collections.Generic;
+
+namespace Microsoft.MaciOS.Nnyeah.Tests {
+
+ public enum PlatformName {
+ None, // desktop managed executable
+ macOS, // Xamarin.Mac app
+ iOS,
+ watchOS,
+ tvOS,
+ }
+
+ public class Compiler {
+ const string MonoCompiler = "/Library/Frameworks/Mono.framework/Versions/Current/Commands/csc";
+
+ public static async Task CompileText (string text, string outputFile, PlatformName platformName, bool isLibrary)
+ {
+ var dir = Cache.CreateTemporaryDirectory ();
+ var outputCSFile = Path.Combine (dir, "LibraryFile.cs");
+ File.WriteAllText (outputCSFile, text);
+ return await Compile (outputFile, platformName, isLibrary, dir, outputCSFile);
+ }
+
+ public static async Task Compile (string outputFile, PlatformName platformName, bool isLibrary, string workingDirectory, params string[] sourceFiles)
+ {
+ var compilerArgs = BuildCompilerArgs (sourceFiles, outputFile, platformName, isLibrary);
+ Execution execution = await Execution.RunAsync(MonoCompiler, compilerArgs, mergeOutput: true, workingDirectory: workingDirectory);
+ return execution!.StandardOutput.ToString()!;
+ }
+
+ static List BuildCompilerArgs (string[] sourceFiles, string outputFile, PlatformName platformName,
+ bool isLibrary)
+ {
+ var args = new List();
+
+ args.Add ("/unsafe");
+ args.Add ("/nostdlib+");
+ AppendPlatformReference (args, platformName, "mscorlib");
+ AppendPlatformReference (args, platformName, XamarinLibName (platformName));
+ args.Add ("/debug+");
+ args.Add ("/debug:full");
+ args.Add ("/optimize-");
+ args.Add ("/out:" + outputFile);
+ args.Add ("/target:" + (isLibrary ? "library" : "exe"));
+
+ foreach (var file in sourceFiles) {
+ args.Add (file);
+ }
+
+ return args;
+ }
+
+ static void AppendPlatformReference (List args, PlatformName platformName, string libName)
+ {
+ args.Add("/reference:" + PlatformLibPath (platformName, libName));
+ }
+
+ static string PlatformLibPath (PlatformName platformName, string libName)
+ {
+ return Path.Combine (PlatformLibDirectory (platformName), $"{libName}.dll");
+ }
+
+ static string PlatformLibDirectory (PlatformName platformName) =>
+ platformName switch {
+ PlatformName.macOS => "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac/",
+ PlatformName.iOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS",
+ PlatformName.tvOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS",
+ PlatformName.watchOS => "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.WatchOS",
+ _ => throw new NotImplementedException (),
+ };
+
+ static string XamarinLibName (PlatformName platformName) =>
+ platformName switch {
+ PlatformName.macOS => "Xamarin.Mac",
+ PlatformName.iOS => "Xamarin.iOS",
+ PlatformName.tvOS => "Xamarin.TVOS",
+ PlatformName.watchOS => "Xamarin.WatchOS",
+ _ => throw new NotImplementedException (),
+ };
+ }
+}
diff --git a/tools/nnyeah/tests/utils/TestRunning.cs b/tools/nnyeah/tests/utils/TestRunning.cs
new file mode 100644
index 000000000000..94a86d50f105
--- /dev/null
+++ b/tools/nnyeah/tests/utils/TestRunning.cs
@@ -0,0 +1,46 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using Xamarin;
+
+namespace Microsoft.MaciOS.Nnyeah.Tests {
+ public class TestRunning {
+ static string GetInvokingTestName (out string callingMethodClass, string callingMethodName)
+ {
+ var stackTrace = new System.Diagnostics.StackTrace ();
+ var callingMethod = stackTrace.GetFrame (2)!.GetMethod ();
+ Assert.NotNull (callingMethod, "unable to get calling test from stack frame.");
+
+ if (string.IsNullOrEmpty (callingMethodName)) {
+ if (!callingMethod!.CustomAttributes.Any (x => x.AttributeType.Name == "TestAttribute")) {
+ Assert.Fail ("TestRunning expect invocations without an explicit `testName` parameter to be invoked from the [Test] method directly. Consider passing an explicit `testName`.");
+ }
+ callingMethodName = callingMethod.Name;
+ }
+ callingMethodClass = callingMethod!.DeclaringType!.Name;
+ return callingMethodName;
+ }
+
+ public static async Task TestAndExecute (string libraryCode, string callingCode, string expectedOutput,
+ string callingMethodName = "")
+ {
+ var testName = GetInvokingTestName (out var nameSpace, callingMethodName);
+ var testClassName = "NnyeahTest" + testName;
+
+ var initialLibraryDir = Cache.CreateTemporaryDirectory ();
+ var finalLibraryDir = Cache.CreateTemporaryDirectory ();
+
+ var libCompilerOutput = await BuildLibrary (libraryCode, testName, initialLibraryDir);
+ }
+
+ public static Task BuildLibrary (string libraryCode, string libName, string outputDirectory, PlatformName platformName = PlatformName.macOS)
+ {
+ var outputPath = Path.Combine (outputDirectory, $"{libName}.dll");
+ return Compiler.CompileText (libraryCode, outputPath, platformName, isLibrary: true);
+ }
+ }
+}
diff --git a/tools/xibuild/xibuild.csproj b/tools/xibuild/xibuild.csproj
index af31fa48891c..70e07f2f606e 100644
--- a/tools/xibuild/xibuild.csproj
+++ b/tools/xibuild/xibuild.csproj
@@ -8,6 +8,7 @@
xibuild
xibuild
v4.7
+ default
true