diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs index 556ea8e7850..aa28323ce5a 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs @@ -154,6 +154,11 @@ internal TaskLoggingHelper TaskLogger set { _taskLogger = value; } } + /// + /// Support custom IntermediateOutputPath and BaseIntermediateOutputPath outside the project path + /// + internal bool SupportCustomOutputPaths { get; set; } = false; + // If the xaml has local references, then it could have internal element & properties // but there is no way to determine this until MCPass2. Yet, GeneratedInternalTypeHelper, // which is the class that allows access to legitimate internals, needs to be generated @@ -1575,11 +1580,64 @@ private string ParentFolderPrefix { get { -#if NETFX - return PathInternal.GetRelativePath(TargetPath, SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase) + Path.DirectorySeparatorChar; + if (SupportCustomOutputPaths) + { + // During code generation, ParentFolderPrefix returns the relative path from a .g.cs file to its markup file. + // + // One example is generated #pragmas: #pragma checksum "..\..\..\..\Views\ExportNotificationView.xaml" + // + // The path information for a markup file is represented in SourceFileInfo: + // + // SourceFileInfo.OriginalFilePath: "c:\\greenshot\\src\\Greenshot.Addons\\Views\\ExportNotificationView.xaml" + // SourceFileInfo.TargetPath: "c:\\greenshot\\src\\Greenshot.Addons\\obj\\Debug\\net6.0-windows\\" + // SourceFileInfo.RelativeFilePath: "Views\\ExportNotificationView" + // SourceFileInfo.SourcePath = "c:\\greenshot\\src\\Greenshot.Addons\\" + // + // The path of the generated code file associated with this markup file is: + // + // "c:\greenshot\src\Greenshot.Addons\obj\Debug\net6.0-windows\Views\ExportNotificationView.g.cs" + // + // The markup file path is in SourceFileInfo.OriginalFilePath: + // + // "c:\\greenshot\\src\\Greenshot.Addons\\Views\\ExportNotificationView.xaml" + // + // The relative path calculation must take in to account both the TargetPath and the RelativeFilePath: + // + // "c:\\greenshot\\src\\Greenshot.Addons\\obj\\Debug\\net6.0-windows\\" [SourceFileInfo.TargetPath] + // "Views\\ExportNotificationView" [SourceFileInfo.RelativeTargetPath] + // + // TargetPath concatenated with the directory portion of the RelativeTargetPath is the location to the .g.cs file: + // + // "c:\\greenshot\\src\\Greenshot.Addons\\obj\\Debug\\net6.0-windows\\Views" + // + string pathOfRelativeSourceFilePath = System.IO.Path.GetDirectoryName(SourceFileInfo.RelativeSourceFilePath); + + // Return the parent folder of the target file with a trailing DirectorySeparatorChar. + // Return a relative path if possible. Else, return an absolute path. + #if NETFX + string path = PathInternal.GetRelativePath(TargetPath + pathOfRelativeSourceFilePath, SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase); #else - return Path.GetRelativePath(TargetPath, SourceFileInfo.SourcePath) + Path.DirectorySeparatorChar; + string path = Path.GetRelativePath(TargetPath + pathOfRelativeSourceFilePath, SourceFileInfo.SourcePath); #endif + // Always return a path with a trailing DirectorySeparatorChar. + return path.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; + } + else + { + string parentFolderPrefix = string.Empty; + if (TargetPath.StartsWith(SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase)) + { + string relPath = TargetPath.Substring(SourceFileInfo.SourcePath.Length); + relPath += SourceFileInfo.RelativeSourceFilePath; + string[] dirs = relPath.Split(new Char[] { Path.DirectorySeparatorChar }); + for (int i = 1; i < dirs.Length; i++) + { + parentFolderPrefix += PARENTFOLDER; + } + } + + return parentFolderPrefix; + } } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/CompilerWrapper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/CompilerWrapper.cs index d47c9af6ff0..5ae45bc28d4 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/CompilerWrapper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/CompilerWrapper.cs @@ -201,6 +201,11 @@ internal int ErrorTimes get { return _nErrors; } } + internal bool SupportCustomOutputPaths + { + set { _mc.SupportCustomOutputPaths = value; } + } + // // Start the compilation. // diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/TaskHelper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/TaskHelper.cs index e6808dd1266..527ec58082d 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/TaskHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/Tasks/TaskHelper.cs @@ -223,7 +223,7 @@ internal static string GetWholeExceptionMessage(Exception exception) // // Helper to create CompilerWrapper. // - internal static CompilerWrapper CreateCompilerWrapper(bool fInSeparateDomain, ref AppDomain appDomain) + internal static CompilerWrapper CreateCompilerWrapper() { return new CompilerWrapper(); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets index 32ba51576be..4674f005c9b 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets @@ -244,7 +244,8 @@ ExtraBuildControlFiles="@(ExtraBuildControlFiles)" XamlDebuggingInformation="$(XamlDebuggingInformation)" IsRunningInVisualStudio="$(BuildingInsideVisualStudio)" - OutputPath="$(IntermediateOutputPath)"> + OutputPath="$(IntermediateOutputPath)" + SupportCustomOutputPaths="$(IncludePackageReferencesDuringMarkupCompilation)"> @@ -304,7 +305,8 @@ XamlDebuggingInformation="$(XamlDebuggingInformation)" GeneratedBaml="" OutputPath="$(IntermediateOutputPath)" - ContinueOnError="false" > + ContinueOnError="false" + SupportCustomOutputPaths="$(IncludePackageReferencesDuringMarkupCompilation)"> + + <_SourceGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_ParentProjectName)$(_ParentProjectExtension).nuget.g.props"/> <_SourceGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_ParentProjectName)$(_ParentProjectExtension).nuget.g.targets"/> <_SourceGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_ParentProjectName)$(_ParentProjectExtension).nuget.dgspec.json"/> - <_DestGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_TemporaryTargetAssemblyProjectName).nuget.g.props"/> - <_DestGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_TemporaryTargetAssemblyProjectName).nuget.g.targets"/> - <_DestGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)$(_TemporaryTargetAssemblyProjectName).nuget.dgspec.json"/> + <_DestGeneratedNuGetPropsAndTargets Include="$(BaseIntermediateOutputPath)$(_TemporaryTargetAssemblyProjectName).nuget.g.props"/> + <_DestGeneratedNuGetPropsAndTargets Include="$(BaseIntermediateOutputPath)$(_TemporaryTargetAssemblyProjectName).nuget.g.targets"/> + <_DestGeneratedNuGetPropsAndTargets Include="$(BaseIntermediateOutputPath)$(_TemporaryTargetAssemblyProjectName).nuget.dgspec.json"/> + + + <_SourceGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)project.assets.json"/> + <_SourceGeneratedNuGetPropsAndTargets Include="$(MSBuildProjectExtensionsPath)project.nuget.cache"/> + + <_DestGeneratedNuGetPropsAndTargets Include="$(BaseIntermediateOutputPath)project.assets.json"/> + <_DestGeneratedNuGetPropsAndTargets Include="$(BaseIntermediateOutputPath)project.nuget.cache"/> + + + /// Support custom IntermediateOutputPath and BaseIntermediateOutputPath outside the project path + /// + public bool SupportCustomOutputPaths { get; set; } = false; + /// /// Generated source code files for the given programing language. /// @@ -1215,7 +1220,7 @@ private void DoMarkupCompilation() try { - compilerWrapper = TaskHelper.CreateCompilerWrapper(AlwaysCompileMarkupFilesInSeparateDomain, ref appDomain); + compilerWrapper = TaskHelper.CreateCompilerWrapper(); if (compilerWrapper != null) { @@ -1239,6 +1244,8 @@ private void DoMarkupCompilation() compilerWrapper.ContentFiles = CompilerAnalyzer.ContentFiles; + compilerWrapper.SupportCustomOutputPaths = SupportCustomOutputPaths; + // Process Reference list here. ArrayList referenceList = ProcessReferenceList(); diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft/Build/Tasks/Windows/MarkupCompilePass2.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft/Build/Tasks/Windows/MarkupCompilePass2.cs index b00d05886dd..bc9f6dd0bba 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft/Build/Tasks/Windows/MarkupCompilePass2.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft/Build/Tasks/Windows/MarkupCompilePass2.cs @@ -322,6 +322,11 @@ public bool XamlDebuggingInformation set { _xamlDebuggingInformation = value; } } + /// + /// Support custom IntermediateOutputPath and BaseIntermediateOutputPath outside the project path + /// + public bool SupportCustomOutputPaths { get; set; } = false; + /// /// Known reference paths hold referenced assemblies which are never changed during the build procedure. /// such as references in GAC, in framework directory or framework SDK directory etc. @@ -634,7 +639,7 @@ private void DoLocalReferenceMarkupCompilation(FileUnit localApplicationFile, Fi try { - compilerWrapper = TaskHelper.CreateCompilerWrapper(AlwaysCompileMarkupFilesInSeparateDomain, ref appDomain); + compilerWrapper = TaskHelper.CreateCompilerWrapper(); if (compilerWrapper != null) { @@ -645,6 +650,8 @@ private void DoLocalReferenceMarkupCompilation(FileUnit localApplicationFile, Fi compilerWrapper.UnknownErrorID = UnknownErrorID; compilerWrapper.XamlDebuggingInformation = XamlDebuggingInformation; + compilerWrapper.SupportCustomOutputPaths = SupportCustomOutputPaths; + compilerWrapper.TaskFileService = _taskFileService; if (OutputType.Equals(SharedStrings.Exe) || OutputType.Equals(SharedStrings.WinExe))