From 8bd7a93433ebbd80dafe587f2cda34f0328f50a5 Mon Sep 17 00:00:00 2001 From: huulinh99 Date: Fri, 23 Jan 2026 10:34:23 +0700 Subject: [PATCH 1/2] Replace Csc task with Roslyn API in FileTrackerTests --- Directory.Packages.props | 1 + eng/Versions.props | 1 + ...Microsoft.Build.Utilities.UnitTests.csproj | 1 + .../TrackedDependencies/FileTrackerTests.cs | 161 +++++++++++++----- 4 files changed, 120 insertions(+), 44 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 117d0ddf276..ddc84167718 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -17,6 +17,7 @@ + diff --git a/eng/Versions.props b/eng/Versions.props index fb60b6444c5..43cf5c58c34 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -76,6 +76,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 + 4.12.0 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 d41e3cbf049..13eade9980f 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 From 86867019b0715f0bf1570f84785043a6cc2406f8 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> Date: Fri, 30 Jan 2026 12:13:09 +0100 Subject: [PATCH 2/2] Update MicrosoftCodeAnalysisCSharpVersion to 5.0.0-1.25277.114 --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index b65ca9610cd..505b10b7793 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -77,7 +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 - 4.12.0 + 5.0.0-1.25277.114 5.0.0-1.25277.114