diff --git a/src/Build/Construction/Solution/SolutionProjectGenerator.cs b/src/Build/Construction/Solution/SolutionProjectGenerator.cs index c40de4d8294..d1fec03c77d 100644 --- a/src/Build/Construction/Solution/SolutionProjectGenerator.cs +++ b/src/Build/Construction/Solution/SolutionProjectGenerator.cs @@ -418,6 +418,7 @@ private static void AddTasksToCopyAllDependenciesIntoBinDir( string copyLocalFilesItemName = referenceItemName + "_CopyLocalFiles"; string targetFrameworkDirectoriesName = GenerateSafePropertyName(project, "_TargetFrameworkDirectories"); string fullFrameworkRefAssyPathName = GenerateSafePropertyName(project, "_FullFrameworkReferenceAssemblyPaths"); + string dependsOnNetStandardPropertyName = GenerateSafePropertyName(project, "_DependsOnNETStandard"); string destinationFolder = String.Format(CultureInfo.InvariantCulture, @"$({0})\Bin\", GenerateSafePropertyName(project, "AspNetPhysicalPath")); // This is a bit of a hack. We're actually calling the "Copy" task on all of @@ -443,6 +444,7 @@ private static void AddTasksToCopyAllDependenciesIntoBinDir( // files need to be copy-localed. ProjectTaskInstance rarTask = target.AddTask("ResolveAssemblyReference", String.Format(CultureInfo.InvariantCulture, "Exists('%({0}.Identity)')", referenceItemName), null); rarTask.SetParameter("Assemblies", "@(" + referenceItemName + "->'%(FullPath)')"); + rarTask.SetParameter("AppConfigFile", "$(WebConfigFileName)"); rarTask.SetParameter("TargetFrameworkDirectories", "$(" + targetFrameworkDirectoriesName + ")"); rarTask.SetParameter("FullFrameworkFolders", "$(" + fullFrameworkRefAssyPathName + ")"); rarTask.SetParameter("SearchPaths", "{RawFileName};{TargetFrameworkDirectory};{GAC}"); @@ -451,15 +453,29 @@ private static void AddTasksToCopyAllDependenciesIntoBinDir( rarTask.SetParameter("FindSerializationAssemblies", "true"); rarTask.SetParameter("FindRelatedFiles", "true"); rarTask.SetParameter("TargetFrameworkMoniker", project.TargetFrameworkMoniker); + rarTask.SetParameter("TargetFrameworkVersion", $"v{new FrameworkName(project.TargetFrameworkMoniker).Version}"); rarTask.AddOutputItem("CopyLocalFiles", copyLocalFilesItemName, null); + // Capture whether RAR detected a dependency on netstandard + rarTask.AddOutputProperty("DependsOnNETStandard", dependsOnNetStandardPropertyName, null); + // Copy all the copy-local files (reported by RAR) to the web project's "bin" // directory. ProjectTaskInstance copyTask = target.AddTask("Copy", conditionDescribingValidConfigurations, null); copyTask.SetParameter("SourceFiles", "@(" + copyLocalFilesItemName + ")"); + copyTask.SetParameter("SkipUnchangedFiles", "true"); copyTask.SetParameter( "DestinationFiles", String.Format(CultureInfo.InvariantCulture, @"@({0}->'{1}%(DestinationSubDirectory)%(Filename)%(Extension)')", copyLocalFilesItemName, destinationFolder)); + + // If any references depend on netstandard, copy netstandard.dll from the Facades folder. + // .NET Framework 4.7.1+ has netstandard 2.0 support in the Facades folder. + string netstandardFacadePath = String.Format(CultureInfo.InvariantCulture, @"$({0})Facades\netstandard.dll", targetFrameworkDirectoriesName); + string copyFacadesCondition = String.Format(CultureInfo.InvariantCulture, "'$({0})' == 'True' AND Exists('{1}')", dependsOnNetStandardPropertyName, netstandardFacadePath); + ProjectTaskInstance copyFacadesTask = target.AddTask("Copy", copyFacadesCondition, null); + copyFacadesTask.SetParameter("SourceFiles", netstandardFacadePath); + copyFacadesTask.SetParameter("SkipUnchangedFiles", "true"); + copyFacadesTask.SetParameter("DestinationFolder", destinationFolder); } /// @@ -1242,6 +1258,16 @@ private ProjectInstance CreateMetaproject(ProjectInstance traversalProject, Proj "AspNetCompiler.UnsupportedMSBuildVersion", project.ProjectName); #else + + if (File.Exists(Path.Combine(project.AbsolutePath, "web.config"))) + { + metaprojectInstance.SetProperty("WebConfigFileName", Path.Combine(project.AbsolutePath, "web.config")); + } + else if (File.Exists(Path.Combine(project.AbsolutePath, "Web.config"))) + { + metaprojectInstance.SetProperty("WebConfigFileName", Path.Combine(project.AbsolutePath, "Web.config")); + } + AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, null); AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Clean"); AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Rebuild"); @@ -1537,12 +1563,14 @@ private void AddTaskForAspNetCompiler( newTask.SetParameter("TargetPath", "$(" + GenerateSafePropertyName(project, "AspNetTargetPath") + ")"); newTask.SetParameter("Force", "$(" + GenerateSafePropertyName(project, "AspNetForce") + ")"); newTask.SetParameter("Updateable", "$(" + GenerateSafePropertyName(project, "AspNetUpdateable") + ")"); + newTask.SetParameter("Clean", "true"); newTask.SetParameter("Debug", "$(" + GenerateSafePropertyName(project, "AspNetDebug") + ")"); newTask.SetParameter("KeyFile", "$(" + GenerateSafePropertyName(project, "AspNetKeyFile") + ")"); newTask.SetParameter("KeyContainer", "$(" + GenerateSafePropertyName(project, "AspNetKeyContainer") + ")"); newTask.SetParameter("DelaySign", "$(" + GenerateSafePropertyName(project, "AspNetDelaySign") + ")"); newTask.SetParameter("AllowPartiallyTrustedCallers", "$(" + GenerateSafePropertyName(project, "AspNetAPTCA") + ")"); newTask.SetParameter("FixedNames", "$(" + GenerateSafePropertyName(project, "AspNetFixedNames") + ")"); + newTask.SetParameter("Clean", "true"); ValidateTargetFrameworkForWebProject(project); diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs index da0ac9603d0..32f894c4fda 100644 --- a/src/Build/Instance/ProjectInstance.cs +++ b/src/Build/Instance/ProjectInstance.cs @@ -2398,8 +2398,10 @@ public ProjectRootElement ToProjectRootElement() if (!_globalProperties.Contains(property.Name) || !String.Equals(_globalProperties[property.Name].EvaluatedValue, property.EvaluatedValue, StringComparison.OrdinalIgnoreCase)) { if ((!_environmentVariableProperties.Contains(property.Name) || !String.Equals(_environmentVariableProperties[property.Name].EvaluatedValue, property.EvaluatedValue, StringComparison.OrdinalIgnoreCase)) - && _sdkResolvedEnvironmentVariableProperties is not null - && (!_sdkResolvedEnvironmentVariableProperties.Contains(property.Name) || !String.Equals(_sdkResolvedEnvironmentVariableProperties[property.Name].EvaluatedValue, property.EvaluatedValue, StringComparison.OrdinalIgnoreCase))) + && (!Toolset.Properties.ContainsKey(property.Name) || !String.Equals(Toolset.Properties[property.Name].EvaluatedValue, property.EvaluatedValue, StringComparison.OrdinalIgnoreCase)) + && (_sdkResolvedEnvironmentVariableProperties is null + || !_sdkResolvedEnvironmentVariableProperties.Contains(property.Name) + || !String.Equals(_sdkResolvedEnvironmentVariableProperties[property.Name].EvaluatedValue, property.EvaluatedValue, StringComparison.OrdinalIgnoreCase))) { property.ToProjectPropertyElement(propertyGroupElement); } diff --git a/src/Tasks/AspNetCompiler.cs b/src/Tasks/AspNetCompiler.cs index 8beb3fc3a9f..0a8fd31b90a 100644 --- a/src/Tasks/AspNetCompiler.cs +++ b/src/Tasks/AspNetCompiler.cs @@ -246,6 +246,7 @@ public override bool Execute() /// command line builder class to add arguments to protected internal override void AddCommandLineCommands(CommandLineBuilderExtension commandLine) { + commandLine.AppendSwitch("-errorstack"); commandLine.AppendSwitchIfNotNull("-m ", MetabasePath); commandLine.AppendSwitchIfNotNull("-v ", VirtualPath); commandLine.AppendSwitchIfNotNull("-p ", PhysicalPath);