From fd00549168c2a95551d7d53d703254e1900f83fd Mon Sep 17 00:00:00 2001 From: Farhad Alizada Date: Wed, 24 Jan 2024 10:30:46 +0100 Subject: [PATCH 1/3] Respect response files (ignoreProjectExtensions) property --- src/MSBuild.UnitTests/XMake_Tests.cs | 38 ++++++++++++++++++++++ src/MSBuild/XMake.cs | 48 ++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/src/MSBuild.UnitTests/XMake_Tests.cs b/src/MSBuild.UnitTests/XMake_Tests.cs index d92d9cdf5e2..3e497c7e409 100644 --- a/src/MSBuild.UnitTests/XMake_Tests.cs +++ b/src/MSBuild.UnitTests/XMake_Tests.cs @@ -1524,6 +1524,44 @@ public void ResponseFileInProjectDirectoryButCommandLineNoAutoResponseSwitch() } } + /// + /// Directory.Build.rsp in the directory of the specified project/solution should be respected when searching the files (solution/proj) to build. + /// + [Fact] + public void ResponseFileInProjectDirectoryWithSolutionProjectDifferentNamesShouldBeRespected() + { + string directory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + string projectPath = Path.Combine(directory, "projectFile.proj"); + string solutionPath = Path.Combine(directory, "solutionFile.sln"); + string rspPath = Path.Combine(directory, "Directory.Build.rsp"); + + try + { + Directory.CreateDirectory(directory); + + string content = ObjectModelHelpers.CleanupFileContents(""); + File.WriteAllText(projectPath, content); + + string rspContent = "-ignoreProjectExtensions:.sln"; + File.WriteAllText(rspPath, rspContent); + + // Incorrect sln file format, which will result fail if picked by msbuild for building + File.WriteAllText(solutionPath, string.Empty); + + var msbuildParameters = "\"" + directory + "\""; + + string output = RunnerUtilities.ExecMSBuild(msbuildParameters, out var successfulExit, _output); + successfulExit.ShouldBeTrue(); + } + finally + { + File.Delete(projectPath); + File.Delete(solutionPath); + File.Delete(rspPath); + FileUtilities.DeleteWithoutTrailingBackslash(directory); + } + } + /// /// Any msbuild.rsp in the directory of the specified project/solution should be read, and should /// take priority over any other response files. Sanity test when there isn't one. diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index 2e4733340a5..48359da7d70 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -307,11 +307,11 @@ private static bool CanRunServerBasedOnCommandLineSwitches( { GatherAllSwitches(commandLine, out var switchesFromAutoResponseFile, out var switchesNotFromAutoResponseFile, out string fullCommandLine); CommandLineSwitches commandLineSwitches = CombineSwitchesRespectingPriority(switchesFromAutoResponseFile, switchesNotFromAutoResponseFile, fullCommandLine); - if (CheckAndGatherProjectAutoResponseFile(switchesFromAutoResponseFile, commandLineSwitches, false, fullCommandLine, out string projectFile)) + if (CheckAndGatherProjectAutoResponseFile(switchesFromAutoResponseFile, commandLineSwitches, false, fullCommandLine)) { commandLineSwitches = CombineSwitchesRespectingPriority(switchesFromAutoResponseFile, switchesNotFromAutoResponseFile, fullCommandLine); } - + string projectFile = ProcessProjectSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project], commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions], Directory.GetFiles); if (commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.Help] || commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.NodeMode) || commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.Version] || @@ -2503,7 +2503,7 @@ private static bool ProcessCommandLineSwitches( } else { - bool foundProjectAutoResponseFile = CheckAndGatherProjectAutoResponseFile(switchesFromAutoResponseFile, commandLineSwitches, recursing, commandLine, out projectFile); + bool foundProjectAutoResponseFile = CheckAndGatherProjectAutoResponseFile(switchesFromAutoResponseFile, commandLineSwitches, recursing, commandLine); if (foundProjectAutoResponseFile) { @@ -2556,6 +2556,9 @@ private static bool ProcessCommandLineSwitches( commandLine); } + // why not process the project parameter here? + projectFile = ProcessProjectSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project], commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions], Directory.GetFiles); + // figure out which targets we are building targets = ProcessTargetSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Target]); @@ -2912,18 +2915,43 @@ private static CommandLineSwitches CombineSwitchesRespectingPriority(CommandLine return commandLineSwitches; } - private static bool CheckAndGatherProjectAutoResponseFile(CommandLineSwitches switchesFromAutoResponseFile, CommandLineSwitches commandLineSwitches, bool recursing, string commandLine, out string projectFile) + private static string GetProjectDirectory(string[] projectSwitchParameters) { - bool found = false; + string projectDirectory = "."; + ErrorUtilities.VerifyThrow(projectSwitchParameters.Length <= 1, "It should not be possible to specify more than 1 project at a time."); - // figure out what project we are building - projectFile = ProcessProjectSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project], commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions], Directory.GetFiles); + if (projectSwitchParameters.Length == 1) + { + var projectFile = FileUtilities.FixFilePath(projectSwitchParameters[0]); + + if (FileSystems.Default.DirectoryExists(projectFile)) + { + // the provided argument value is actually the directory + projectDirectory = projectFile; + } + else + { + InitializationException.VerifyThrow(FileSystems.Default.FileExists(projectFile), "ProjectNotFoundError", projectFile); + projectDirectory = Path.GetDirectoryName(Path.GetFullPath(projectFile)); + } + } + + return projectDirectory; + } + + + /// + /// Identifies if there is rsp files near the project file + /// + /// true if there autoresponse file was found + private static bool CheckAndGatherProjectAutoResponseFile(CommandLineSwitches switchesFromAutoResponseFile, CommandLineSwitches commandLineSwitches, bool recursing, string commandLine) + { + bool found = false; + + var projectDirectory = GetProjectDirectory(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project]); if (!recursing && !commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.NoAutoResponse]) { - // gather any switches from an msbuild.rsp that is next to the project or solution file itself - string projectDirectory = Path.GetDirectoryName(Path.GetFullPath(projectFile)); - // gather any switches from the first Directory.Build.rsp found in the project directory or above string directoryResponseFile = FileUtilities.GetPathOfFileAbove(directoryResponseFileName, projectDirectory); From 291800f449ed4530449f66c006def8dc3fcf4acd Mon Sep 17 00:00:00 2001 From: Farhad Alizada Date: Thu, 25 Jan 2024 09:23:39 +0100 Subject: [PATCH 2/3] Address PR review --- src/MSBuild.UnitTests/XMake_Tests.cs | 37 ++++++---------------------- src/MSBuild/XMake.cs | 1 - 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/MSBuild.UnitTests/XMake_Tests.cs b/src/MSBuild.UnitTests/XMake_Tests.cs index 3e497c7e409..f76211ebf87 100644 --- a/src/MSBuild.UnitTests/XMake_Tests.cs +++ b/src/MSBuild.UnitTests/XMake_Tests.cs @@ -1530,36 +1530,15 @@ public void ResponseFileInProjectDirectoryButCommandLineNoAutoResponseSwitch() [Fact] public void ResponseFileInProjectDirectoryWithSolutionProjectDifferentNamesShouldBeRespected() { - string directory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); - string projectPath = Path.Combine(directory, "projectFile.proj"); - string solutionPath = Path.Combine(directory, "solutionFile.sln"); - string rspPath = Path.Combine(directory, "Directory.Build.rsp"); - - try - { - Directory.CreateDirectory(directory); - - string content = ObjectModelHelpers.CleanupFileContents(""); - File.WriteAllText(projectPath, content); - - string rspContent = "-ignoreProjectExtensions:.sln"; - File.WriteAllText(rspPath, rspContent); - - // Incorrect sln file format, which will result fail if picked by msbuild for building - File.WriteAllText(solutionPath, string.Empty); - - var msbuildParameters = "\"" + directory + "\""; + var directory = _env.CreateFolder(); + var content = ObjectModelHelpers.CleanupFileContents(""); + directory.CreateFile("projectFile.proj", content); + directory.CreateFile("solutionFile.sln", string.Empty); + directory.CreateFile("Directory.Build.rsp", "-ignoreProjectExtensions:.sln"); - string output = RunnerUtilities.ExecMSBuild(msbuildParameters, out var successfulExit, _output); - successfulExit.ShouldBeTrue(); - } - finally - { - File.Delete(projectPath); - File.Delete(solutionPath); - File.Delete(rspPath); - FileUtilities.DeleteWithoutTrailingBackslash(directory); - } + var msbuildParameters = "\"" + directory.Path + "\""; + RunnerUtilities.ExecMSBuild(msbuildParameters, out var successfulExit, _output); + successfulExit.ShouldBeTrue(); } /// diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index 48359da7d70..138350d29ab 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -2556,7 +2556,6 @@ private static bool ProcessCommandLineSwitches( commandLine); } - // why not process the project parameter here? projectFile = ProcessProjectSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project], commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions], Directory.GetFiles); // figure out which targets we are building From 56d360a17a3cc32b4c5b3074e5b5ac2b25a8d6ff Mon Sep 17 00:00:00 2001 From: Farhad Alizada Date: Mon, 5 Feb 2024 09:59:04 +0100 Subject: [PATCH 3/3] Address PR comments --- src/MSBuild.UnitTests/XMake_Tests.cs | 2 +- src/MSBuild/XMake.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MSBuild.UnitTests/XMake_Tests.cs b/src/MSBuild.UnitTests/XMake_Tests.cs index 49088803d0a..ceaf38e0326 100644 --- a/src/MSBuild.UnitTests/XMake_Tests.cs +++ b/src/MSBuild.UnitTests/XMake_Tests.cs @@ -1449,7 +1449,7 @@ public void ResponseFileInProjectDirectoryButCommandLineNoAutoResponseSwitch() public void ResponseFileInProjectDirectoryWithSolutionProjectDifferentNamesShouldBeRespected() { var directory = _env.CreateFolder(); - var content = ObjectModelHelpers.CleanupFileContents(""); + var content = ObjectModelHelpers.CleanupFileContents(""); directory.CreateFile("projectFile.proj", content); directory.CreateFile("solutionFile.sln", string.Empty); directory.CreateFile("Directory.Build.rsp", "-ignoreProjectExtensions:.sln"); diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index 138350d29ab..773bd785a7e 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -2917,7 +2917,7 @@ private static CommandLineSwitches CombineSwitchesRespectingPriority(CommandLine private static string GetProjectDirectory(string[] projectSwitchParameters) { string projectDirectory = "."; - ErrorUtilities.VerifyThrow(projectSwitchParameters.Length <= 1, "It should not be possible to specify more than 1 project at a time."); + ErrorUtilities.VerifyThrow(projectSwitchParameters.Length <= 1, "Expect exactly one project at a time."); if (projectSwitchParameters.Length == 1) { @@ -3404,7 +3404,7 @@ internal static string ProcessProjectSwitch( string[] projectsExtensionsToIgnore, DirectoryGetFiles getFiles) { - ErrorUtilities.VerifyThrow(parameters.Length <= 1, "It should not be possible to specify more than 1 project at a time."); + ErrorUtilities.VerifyThrow(parameters.Length <= 1, "Expect exactly one project at a time."); string projectFile = null; string projectDirectory = null;