From 86adc961fedefef300b6273b22611410ac87270b Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 2 May 2017 01:37:33 -0400 Subject: [PATCH] Handle unix slashes in project file paths in a .sln file Given a .sln with: Projects A, B and C. A has a ProjectReference to B B depends on C, specified in the .sln file ``` Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibB", "LibB\LibB.csproj", "{34ED4F6B-145E-467E-AFFB-48B3237878D3}" ProjectSection(ProjectDependencies) = postProject {9C743F94-9DA8-422B-8FB8-DEB139216381} = {9C743F94-9DA8-422B-8FB8-DEB139216381} EndProjectSection EndProject ``` Building this with msbuild: ``` "/Users/ankit/Projects/SlnProjectDepsBug/SlnProjectDepsBug.sln" (default target) (1) -> "/Users/ankit/Projects/SlnProjectDepsBug/LibB/LibB.csproj.metaproj" (default target) (5) -> /Users/ankit/Projects/SlnProjectDepsBug/LibB/LibB.csproj.metaproj : error MSB4025: The project file could not be loaded. Could not find file "/Users/ankit/Projects/SlnProjectDepsBug/LibB/LibB.csproj.metaproj". ``` The solution project generator creates a Project and ProjectInstance for `LibB.csproj.metaproj`, and a `BuildRequestConfiguration` gets added to `BuilderManager._configCache` from `LoadSolutionIntoConfiguration`. But it has a property: CurrentSolutionConfigurationContents= Debug|x86 Debug|AnyCPU Debug|AnyCPU .. with `LibB\LibB.csproj`. And at a later point the instance gets looked up from `BuildRequestEngine.IssueBuildRequests`, and at this point the build request has the same property but with fixed paths, which causes the `GetMatchingConfiguration` to fail trying to match the property. IOW, it fails to find the `ProjectInstance` for `LibB.csproj.metaproj` and so tries to load the project file instead, which doesn't exist on disk! `ProjectInSolution.RelativePath` should fix up the project path being read from the sln file. `ParentSolution.SolutionFileDirectory` is built correctly, and it's setter is used only by tests. So `ProjectInSolution.AbsolutePath` doesn't need to be updated. FIXME: Added a test project but it is not integrated in the build. It should probably be added in SolutionProjectGenerator_Tests. (https://github.com/Microsoft/msbuild/issues/1957) --- mono/tests/SlnProjectDepsBug/LibB/LibB.csproj | 37 +++++++++++++++ mono/tests/SlnProjectDepsBug/LibB/MyClass.cs | 10 +++++ .../LibB/Properties/AssemblyInfo.cs | 26 +++++++++++ mono/tests/SlnProjectDepsBug/LibC/LibC.csproj | 37 +++++++++++++++ mono/tests/SlnProjectDepsBug/LibC/MyClass.cs | 10 +++++ .../LibC/Properties/AssemblyInfo.cs | 26 +++++++++++ .../SlnProjectDepsBug/SlnProjectDepsBug.sln | 32 +++++++++++++ .../SlnProjectDepsBug/Program.cs | 12 +++++ .../Properties/AssemblyInfo.cs | 26 +++++++++++ .../SlnProjectDepsBug.csproj | 45 +++++++++++++++++++ .../Solution/ProjectInSolution.cs | 7 ++- 11 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 mono/tests/SlnProjectDepsBug/LibB/LibB.csproj create mode 100644 mono/tests/SlnProjectDepsBug/LibB/MyClass.cs create mode 100644 mono/tests/SlnProjectDepsBug/LibB/Properties/AssemblyInfo.cs create mode 100644 mono/tests/SlnProjectDepsBug/LibC/LibC.csproj create mode 100644 mono/tests/SlnProjectDepsBug/LibC/MyClass.cs create mode 100644 mono/tests/SlnProjectDepsBug/LibC/Properties/AssemblyInfo.cs create mode 100644 mono/tests/SlnProjectDepsBug/SlnProjectDepsBug.sln create mode 100644 mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Program.cs create mode 100644 mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Properties/AssemblyInfo.cs create mode 100644 mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/SlnProjectDepsBug.csproj diff --git a/mono/tests/SlnProjectDepsBug/LibB/LibB.csproj b/mono/tests/SlnProjectDepsBug/LibB/LibB.csproj new file mode 100644 index 00000000000..863346ebc8b --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibB/LibB.csproj @@ -0,0 +1,37 @@ + + + + Debug + AnyCPU + {34ED4F6B-145E-467E-AFFB-48B3237878D3} + Library + LibB + LibB + v4.6.2 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + \ No newline at end of file diff --git a/mono/tests/SlnProjectDepsBug/LibB/MyClass.cs b/mono/tests/SlnProjectDepsBug/LibB/MyClass.cs new file mode 100644 index 00000000000..3d310de2982 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibB/MyClass.cs @@ -0,0 +1,10 @@ +using System; +namespace LibB +{ + public class MyClass + { + public MyClass() + { + } + } +} diff --git a/mono/tests/SlnProjectDepsBug/LibB/Properties/AssemblyInfo.cs b/mono/tests/SlnProjectDepsBug/LibB/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..f0f4559a2f6 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibB/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +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("LibB")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[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("")] diff --git a/mono/tests/SlnProjectDepsBug/LibC/LibC.csproj b/mono/tests/SlnProjectDepsBug/LibC/LibC.csproj new file mode 100644 index 00000000000..f8a3bf11a46 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibC/LibC.csproj @@ -0,0 +1,37 @@ + + + + Debug + AnyCPU + {9C743F94-9DA8-422B-8FB8-DEB139216381} + Library + LibC + LibC + v4.6.2 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + \ No newline at end of file diff --git a/mono/tests/SlnProjectDepsBug/LibC/MyClass.cs b/mono/tests/SlnProjectDepsBug/LibC/MyClass.cs new file mode 100644 index 00000000000..1004eb73ba4 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibC/MyClass.cs @@ -0,0 +1,10 @@ +using System; +namespace LibC +{ + public class MyClass + { + public MyClass() + { + } + } +} diff --git a/mono/tests/SlnProjectDepsBug/LibC/Properties/AssemblyInfo.cs b/mono/tests/SlnProjectDepsBug/LibC/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..05147718a0b --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/LibC/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +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("LibC")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[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("")] diff --git a/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug.sln b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug.sln new file mode 100644 index 00000000000..440e0f249cd --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlnProjectDepsBug", "SlnProjectDepsBug\SlnProjectDepsBug.csproj", "{2A45AC7E-98A0-4AA8-84F0-7C02A7469313}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibC", "LibC\LibC.csproj", "{9C743F94-9DA8-422B-8FB8-DEB139216381}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibB", "LibB\LibB.csproj", "{34ED4F6B-145E-467E-AFFB-48B3237878D3}" + ProjectSection(ProjectDependencies) = postProject + {9C743F94-9DA8-422B-8FB8-DEB139216381} = {9C743F94-9DA8-422B-8FB8-DEB139216381} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A45AC7E-98A0-4AA8-84F0-7C02A7469313}.Debug|x86.ActiveCfg = Debug|x86 + {2A45AC7E-98A0-4AA8-84F0-7C02A7469313}.Debug|x86.Build.0 = Debug|x86 + {2A45AC7E-98A0-4AA8-84F0-7C02A7469313}.Release|x86.ActiveCfg = Release|x86 + {2A45AC7E-98A0-4AA8-84F0-7C02A7469313}.Release|x86.Build.0 = Release|x86 + {9C743F94-9DA8-422B-8FB8-DEB139216381}.Debug|x86.ActiveCfg = Debug|Any CPU + {9C743F94-9DA8-422B-8FB8-DEB139216381}.Debug|x86.Build.0 = Debug|Any CPU + {9C743F94-9DA8-422B-8FB8-DEB139216381}.Release|x86.ActiveCfg = Release|Any CPU + {9C743F94-9DA8-422B-8FB8-DEB139216381}.Release|x86.Build.0 = Release|Any CPU + {34ED4F6B-145E-467E-AFFB-48B3237878D3}.Debug|x86.ActiveCfg = Debug|Any CPU + {34ED4F6B-145E-467E-AFFB-48B3237878D3}.Debug|x86.Build.0 = Debug|Any CPU + {34ED4F6B-145E-467E-AFFB-48B3237878D3}.Release|x86.ActiveCfg = Release|Any CPU + {34ED4F6B-145E-467E-AFFB-48B3237878D3}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Program.cs b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Program.cs new file mode 100644 index 00000000000..b779bafa8b8 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace SlnProjectDepsBug +{ + class MainClass + { + public static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Properties/AssemblyInfo.cs b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..ac3f54c54b0 --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +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("SlnProjectDepsBug")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[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("")] diff --git a/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/SlnProjectDepsBug.csproj b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/SlnProjectDepsBug.csproj new file mode 100644 index 00000000000..fc0a83efe9a --- /dev/null +++ b/mono/tests/SlnProjectDepsBug/SlnProjectDepsBug/SlnProjectDepsBug.csproj @@ -0,0 +1,45 @@ + + + + Debug + x86 + {2A45AC7E-98A0-4AA8-84F0-7C02A7469313} + Exe + SlnProjectDepsBug + SlnProjectDepsBug + v4.6.2 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + x86 + + + true + bin\Release + prompt + 4 + true + x86 + + + + + + + + + + + {34ED4F6B-145E-467E-AFFB-48B3237878D3} + LibB + + + + \ No newline at end of file diff --git a/src/Build/Construction/Solution/ProjectInSolution.cs b/src/Build/Construction/Solution/ProjectInSolution.cs index 4cdfa5936eb..ee0133dd28f 100644 --- a/src/Build/Construction/Solution/ProjectInSolution.cs +++ b/src/Build/Construction/Solution/ProjectInSolution.cs @@ -8,6 +8,7 @@ using System.Security; using System.Text; using System.Xml; +using Microsoft.Build.Shared; using XMakeAttributes = Microsoft.Build.Shared.XMakeAttributes; using ProjectFileErrorUtilities = Microsoft.Build.Shared.ProjectFileErrorUtilities; @@ -154,7 +155,11 @@ public string ProjectName public string RelativePath { get { return _relativePath; } - internal set { _relativePath = value; } + internal set + { + _relativePath = FileUtilities.MaybeAdjustFilePath(value, + baseDirectory:this.ParentSolution.SolutionFileDirectory ?? String.Empty); + } } ///