diff --git a/Directory.Packages.props b/Directory.Packages.props
index 2de8bea8769..c9e4f410687 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -17,6 +17,7 @@
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 48a73f73a64..505b10b7793 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -77,6 +77,7 @@
When updating the version make sure to add the new version to source-build-reference-packages first. -->
5.0.0-1.25277.114
5.0.0-1.25277.114
+ 5.0.0-1.25277.114
5.0.0-1.25277.114
diff --git a/src/Utilities.UnitTests/Microsoft.Build.Utilities.UnitTests.csproj b/src/Utilities.UnitTests/Microsoft.Build.Utilities.UnitTests.csproj
index 971c9183beb..e89afdcfdcd 100644
--- a/src/Utilities.UnitTests/Microsoft.Build.Utilities.UnitTests.csproj
+++ b/src/Utilities.UnitTests/Microsoft.Build.Utilities.UnitTests.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/Utilities.UnitTests/TrackedDependencies/FileTrackerTests.cs b/src/Utilities.UnitTests/TrackedDependencies/FileTrackerTests.cs
index f5cdd7f1e79..ea41864cc4d 100644
--- a/src/Utilities.UnitTests/TrackedDependencies/FileTrackerTests.cs
+++ b/src/Utilities.UnitTests/TrackedDependencies/FileTrackerTests.cs
@@ -15,9 +15,9 @@
using Microsoft.Build.Shared;
using Microsoft.Build.Utilities;
-#if ENABLE_TRACKER_TESTS // https://github.com/dotnet/msbuild/issues/12063
-using Microsoft.CodeAnalysis.BuildTasks;
-#endif
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Emit;
using Xunit;
using BackEndNativeMethods = Microsoft.Build.BackEnd.NativeMethods;
@@ -92,6 +92,39 @@ public void Dispose()
FileTrackerTestHelper.CleanTlogs();
}
+ [Fact]
+ public void CompileCSharpExecutable_CompilesSimpleProgram()
+ {
+ if (NativeMethodsShared.IsUnixLike)
+ {
+ return; // This test is Windows-only
+ }
+
+ string outputFile = Path.Combine(Path.GetTempPath(), $"TestCompile_{Guid.NewGuid()}.exe");
+ try
+ {
+ string codeContent = @"
+using System;
+class Program
+{
+ static void Main()
+ {
+ Console.WriteLine(""Hello from compiled code!"");
+ }
+}";
+ bool compileSucceeded = FileTrackerTestHelper.CompileCSharpExecutable(codeContent, outputFile);
+ Assert.True(compileSucceeded, "Compilation should succeed");
+ Assert.True(File.Exists(outputFile), "Output executable should exist");
+ }
+ finally
+ {
+ if (File.Exists(outputFile))
+ {
+ File.Delete(outputFile);
+ }
+ }
+ }
+
[Fact(Skip = "FileTracker tests require VS2015 Update 3 or a packaged version of Tracker.exe https://github.com/dotnet/msbuild/issues/649")]
public void FileTrackerHelp()
{
@@ -286,8 +319,6 @@ public void FileTrackerFindStrInOperationsExtended_AttributesOnly()
Assert.True(foundCreateFileW || foundCreateFileA);
}
-
-#if ENABLE_TRACKER_TESTS // https://github.com/dotnet/msbuild/issues/12063
[Fact(Skip = "FileTracker tests require VS2015 Update 3 or a packaged version of Tracker.exe https://github.com/dotnet/msbuild/issues/649")]
public void FileTrackerExtendedDirectoryTracking()
{
@@ -296,7 +327,6 @@ public void FileTrackerExtendedDirectoryTracking()
File.Delete("directoryattributes.read.1.tlog");
File.Delete("directoryattributes.write.1.tlog");
- string codeFile = null;
string outputFile = Path.Combine(Path.GetTempPath(), "directoryattributes.exe");
string codeContent = @"
using System.IO;
@@ -321,13 +351,8 @@ static void Main(string[] args)
try
{
- codeFile = FileUtilities.GetTemporaryFileName();
- File.WriteAllText(codeFile, codeContent);
- Csc csc = new Csc();
- csc.BuildEngine = new MockEngine3();
- csc.Sources = new ITaskItem[] { new TaskItem(codeFile) };
- csc.OutputAssembly = new TaskItem(outputFile);
- csc.Execute();
+ bool compileSucceeded = FileTrackerTestHelper.CompileCSharpExecutable(codeContent, outputFile);
+ Assert.True(compileSucceeded);
string trackerPath = FileTracker.GetTrackerPath(ExecutableType.ManagedIL);
string fileTrackerPath = FileTracker.GetFileTrackerPath(ExecutableType.ManagedIL);
@@ -405,7 +430,6 @@ static void Main(string[] args)
}
finally
{
- File.Delete(codeFile);
File.Delete(outputFile);
}
}
@@ -418,21 +442,15 @@ public void FileTrackerFindStrInIncludeDuplicates()
File.Delete("findstr.read.1.tlog");
FileTrackerTestHelper.WriteAll("test.in", "foo");
- string codeFile = null;
string outputFile = Path.Combine(Path.GetTempPath(), "readtwice.exe");
File.Delete(outputFile);
try
{
string inputPath = Path.GetFullPath("test.in");
- codeFile = FileUtilities.GetTemporaryFileName();
string codeContent = @"using System.IO; class X { static void Main() { File.ReadAllText(@""" + inputPath + @"""); File.ReadAllText(@""" + inputPath + @"""); }}";
- File.WriteAllText(codeFile, codeContent);
- Csc csc = new Csc();
- csc.BuildEngine = new MockEngine3();
- csc.Sources = new[] { new TaskItem(codeFile) };
- csc.OutputAssembly = new TaskItem(outputFile);
- csc.Execute();
+ bool compileSucceeded = FileTrackerTestHelper.CompileCSharpExecutable(codeContent, outputFile);
+ Assert.True(compileSucceeded);
string trackerPath = FileTracker.GetTrackerPath(ExecutableType.ManagedIL);
string fileTrackerPath = FileTracker.GetFileTrackerPath(ExecutableType.ManagedIL);
@@ -444,7 +462,6 @@ public void FileTrackerFindStrInIncludeDuplicates()
}
finally
{
- File.Delete(codeFile);
File.Delete(outputFile);
}
@@ -474,7 +491,6 @@ public void FileTrackerDoNotRecordWriteAsRead()
try
{
writeFile = Path.Combine(testDirectory, "test.out");
- string codeFile = Path.Combine(testDirectory, "code.cs");
string codeContent = @"
using System.IO;
using System.Runtime.InteropServices;
@@ -488,14 +504,8 @@ static void Main()
}
}";
- File.WriteAllText(codeFile, codeContent);
- Csc csc = new Csc();
- csc.BuildEngine = new MockEngine3();
- csc.Sources = new[] { new TaskItem(codeFile) };
- csc.OutputAssembly = new TaskItem(outputFile);
- bool success = csc.Execute();
-
- Assert.True(success);
+ bool compileSucceeded = FileTrackerTestHelper.CompileCSharpExecutable(codeContent, outputFile);
+ Assert.True(compileSucceeded);
string trackerPath = FileTracker.GetTrackerPath(ExecutableType.ManagedIL);
string fileTrackerPath = FileTracker.GetFileTrackerPath(ExecutableType.ManagedIL);
@@ -516,7 +526,6 @@ static void Main()
FileTrackerTestHelper.AssertDidntFindStringInTLog("CreateFileW, Desired Access=0xc0000000, Creation Disposition=0x1:" + writeFile.ToUpperInvariant(), "writenoread.read.1.tlog");
FileTrackerTestHelper.AssertFoundStringInTLog("CreateFileW, Desired Access=0xc0000000, Creation Disposition=0x1:" + writeFile.ToUpperInvariant(), "writenoread.write.1.tlog");
}
-#endif // ENABLE_TRACKER_TESTS
[Fact(Skip = "FileTracker tests require VS2015 Update 3 or a packaged version of Tracker.exe https://github.com/dotnet/msbuild/issues/649")]
public void FileTrackerFindStrInCommandLine()
@@ -2232,7 +2241,6 @@ public void LaunchMultipleOfSameTool_DifferentContexts()
}
}
-#if ENABLE_TRACKER_TESTS // https://github.com/dotnet/msbuild/issues/12063
[Fact(Skip = "Needs investigation")]
public void LaunchMultipleOfSameTool_ToolLaunchesOthers()
{
@@ -2277,15 +2285,7 @@ static void Main(string[] args)
File.Delete(outputFile);
- string codeFile = Path.Combine(testDir, "Program.cs");
- File.WriteAllText(codeFile, codeContent);
- Csc csc = new Csc();
- csc.BuildEngine = new MockEngine3();
- csc.Sources = new ITaskItem[] { new TaskItem(codeFile) };
- csc.OutputAssembly = new TaskItem(outputFile);
- csc.Platform = "x86";
- bool compileSucceeded = csc.Execute();
-
+ bool compileSucceeded = FileTrackerTestHelper.CompileCSharpExecutable(codeContent, outputFile, "x86");
Assert.True(compileSucceeded);
// Item1: appname
@@ -2318,7 +2318,6 @@ static void Main(string[] args)
}
}
}
-#endif // ENABLE_TRACKER_TESTS
private static void InProcTrackingSpawnsToolWithTracker(bool useTrackerResponseFile)
{
@@ -2563,6 +2562,80 @@ public static void AssertFoundStringInTLog(string file, string tlog, int timesFo
}
public static void AssertFoundStringInTLog(string file, string tlog) => AssertFoundStringInTLog(file, tlog, 1);
+
+ ///
+ /// Compiles C# source code into an executable using Roslyn.
+ ///
+ /// The C# source code to compile.
+ /// The path where the executable will be written.
+ /// Optional platform target (e.g., "x86", "x64", "AnyCpu"). Defaults to AnyCpu.
+ /// True if compilation succeeded, false otherwise.
+ public static bool CompileCSharpExecutable(string sourceCode, string outputPath, string platform = null)
+ {
+ SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
+
+ string assemblyName = Path.GetFileNameWithoutExtension(outputPath);
+
+ // Add references to required assemblies
+ var references = new List
+ {
+ MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(System.IO.File).Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(System.Diagnostics.Process).Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(System.Runtime.InteropServices.DllImportAttribute).Assembly.Location),
+ };
+
+ // Add reference to System.Runtime for core types
+ string runtimePath = Path.GetDirectoryName(typeof(object).Assembly.Location);
+ string systemRuntimePath = Path.Combine(runtimePath, "System.Runtime.dll");
+ if (File.Exists(systemRuntimePath))
+ {
+ references.Add(MetadataReference.CreateFromFile(systemRuntimePath));
+ }
+
+ // Determine platform
+ Platform targetPlatform = Platform.AnyCpu;
+ if (!string.IsNullOrEmpty(platform))
+ {
+ switch (platform.ToLowerInvariant())
+ {
+ case "x86":
+ targetPlatform = Platform.X86;
+ break;
+ case "x64":
+ targetPlatform = Platform.X64;
+ break;
+ case "anycpu":
+ default:
+ targetPlatform = Platform.AnyCpu;
+ break;
+ }
+ }
+
+ CSharpCompilationOptions options = new CSharpCompilationOptions(
+ OutputKind.ConsoleApplication,
+ optimizationLevel: OptimizationLevel.Release,
+ platform: targetPlatform);
+
+ CSharpCompilation compilation = CSharpCompilation.Create(
+ assemblyName,
+ syntaxTrees: new[] { syntaxTree },
+ references: references,
+ options: options);
+
+ EmitResult result = compilation.Emit(outputPath);
+
+ if (!result.Success)
+ {
+ foreach (Diagnostic diagnostic in result.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error))
+ {
+ Console.WriteLine($"Compilation error: {diagnostic.GetMessage()}");
+ }
+ }
+
+ return result.Success;
+ }
}
}
#endif