diff --git a/src/Microsoft.DotNet.Build.Tasks/PackageFiles/FrameworkTargeting.targets b/src/Microsoft.DotNet.Build.Tasks/PackageFiles/FrameworkTargeting.targets
index 9a461dbdaf..19630c5a45 100644
--- a/src/Microsoft.DotNet.Build.Tasks/PackageFiles/FrameworkTargeting.targets
+++ b/src/Microsoft.DotNet.Build.Tasks/PackageFiles/FrameworkTargeting.targets
@@ -49,6 +49,22 @@
.NETCoreApp,Version=v1.0
+
+
+
true
true
@@ -61,11 +77,10 @@
Include="netstandard" />
-
+
+ BeforeTargets="AddReferencesDynamically">
@@ -146,6 +161,10 @@
+
+ AddProjectReferencesDynamically;
+ $(PrepareProjectReferencesDependsOn);
+
AddProjectReferencesDynamically;
$(ResolveReferencesDependsOn);
diff --git a/src/Microsoft.DotNet.Build.Tasks/PackageFiles/partialfacades.task.targets b/src/Microsoft.DotNet.Build.Tasks/PackageFiles/partialfacades.task.targets
index 24657ee66b..232f63751c 100644
--- a/src/Microsoft.DotNet.Build.Tasks/PackageFiles/partialfacades.task.targets
+++ b/src/Microsoft.DotNet.Build.Tasks/PackageFiles/partialfacades.task.targets
@@ -8,7 +8,7 @@
of the assembly compilation process.
-->
-
+
$(TargetsTriggeredByCompilation);FillPartialFacadeUsingTask
diff --git a/src/Microsoft.DotNet.Build.Tasks/UpdateVSConfigurations.cs b/src/Microsoft.DotNet.Build.Tasks/UpdateVSConfigurations.cs
index 0f042d275f..f3ae84079a 100644
--- a/src/Microsoft.DotNet.Build.Tasks/UpdateVSConfigurations.cs
+++ b/src/Microsoft.DotNet.Build.Tasks/UpdateVSConfigurations.cs
@@ -19,7 +19,7 @@ public class UpdateVSConfigurations : BuildTask
private const string ConfigurationPropsFilename = "Configurations.props";
private static Regex s_configurationConditionRegex = new Regex(@"'\$\(Configuration\)\|\$\(Platform\)' ?== ?'(?.*)'");
- private static string[] s_configurationSuffixes = new [] { "Debug|AnyCPU", "Release|AnyCPU" };
+ private static string[] s_configurationSuffixes = new [] { "Debug", "Release" };
public override bool Execute()
{
@@ -40,14 +40,14 @@ public override bool Execute()
Log.LogMessage($"Updating {projectFile}");
var project = ProjectRootElement.Open(projectFile);
- ICollection propertyGroups;
- var actualConfigurations = GetConfigurationFromPropertyGroups(project, out propertyGroups);
+ ICollection propertyGroups = GetPropertyGroupsToRemove(project);
+ var actualConfigurations = GetConfigurationsFromProperty(project);
bool addedGuid = EnsureProjectGuid(project);
if (!actualConfigurations.SequenceEqual(expectedConfigurations))
{
- ReplaceConfigurationPropertyGroups(project, propertyGroups, expectedConfigurations);
+ ReplaceConfigurationsProperty(project, propertyGroups, expectedConfigurations);
}
if (addedGuid || !actualConfigurations.SequenceEqual(expectedConfigurations))
@@ -92,15 +92,13 @@ private static string[] GetConfigurationStrings(string configurationProjectFile,
}
///
- /// Gets a sorted list of configuration strings from a project file's PropertyGroups
+ /// Gets a collection of a project file's configuration PropertyGroups in the legacy format.
///
/// Project
- /// collection that accepts the list of property groups representing configuration strings
- /// Sorted list of configuration strings
- private static string[] GetConfigurationFromPropertyGroups(ProjectRootElement project, out ICollection propertyGroups)
+ /// Collection of PropertyGroups that should be removed from the project.
+ private static ICollection GetPropertyGroupsToRemove(ProjectRootElement project)
{
- propertyGroups = new List();
- var configurations = new SortedSet(StringComparer.OrdinalIgnoreCase);
+ List propertyGroups = new List();
foreach (var propertyGroup in project.PropertyGroups)
{
@@ -108,78 +106,52 @@ private static string[] GetConfigurationFromPropertyGroups(ProjectRootElement pr
if (match.Success)
{
- configurations.Add(match.Groups["config"].Value);
propertyGroups.Add(propertyGroup);
}
}
- return configurations.ToArray();
+ return propertyGroups;
+ }
+
+ private string[] GetConfigurationsFromProperty(ProjectRootElement project)
+ {
+ return project.PropertyGroups
+ .SelectMany(g => g.Properties)
+ .FirstOrDefault(p => p.Name == "Configurations")?.Value
+ .Split(';')
+ ?? Array.Empty();
}
///
- /// Replaces all configuration propertygroups with empty property groups corresponding to the expected configurations.
+ /// Replaces the configurations property with the expected configurations.
/// Doesn't attempt to preserve any content since it can all be regenerated.
/// Does attempt to preserve the ordering in the project file.
///
/// Project
/// PropertyGroups to remove
///
- private static void ReplaceConfigurationPropertyGroups(ProjectRootElement project, IEnumerable oldPropertyGroups, IEnumerable newConfigurations)
+ private static void ReplaceConfigurationsProperty(ProjectRootElement project, IEnumerable oldPropertyGroups, IEnumerable newConfigurations)
{
- ProjectElement insertAfter = null, insertBefore = null;
-
foreach (var oldPropertyGroup in oldPropertyGroups)
{
- insertBefore = oldPropertyGroup.NextSibling;
project.RemoveChild(oldPropertyGroup);
}
- if (insertBefore == null)
+ string configurationsValue = string.Join(";", newConfigurations);
+ var configurationsProperty = project.Properties.FirstOrDefault(p => p.Name == "Configurations");
+ if (configurationsProperty == null)
{
- // find first itemgroup after imports
- var insertAt = project.Imports.FirstOrDefault()?.NextSibling;
-
- while (insertAt != null)
+ var firstPropertyGroup = project.PropertyGroups.FirstOrDefault();
+ if (firstPropertyGroup == null)
{
- if (insertAt is ProjectItemGroupElement)
- {
- insertBefore = insertAt;
- break;
- }
-
- insertAt = insertAt.NextSibling;
+ firstPropertyGroup = project.CreatePropertyGroupElement();
}
- }
-
- if (insertBefore == null)
- {
- // find last propertygroup after imports, defaulting to after imports
- insertAfter = project.Imports.FirstOrDefault();
- while (insertAfter?.NextSibling != null && insertAfter.NextSibling is ProjectPropertyGroupElement)
- {
- insertAfter = insertAfter.NextSibling;
- }
+ configurationsProperty = firstPropertyGroup.AddProperty("Configurations", configurationsValue);
}
-
- foreach (var newConfiguration in newConfigurations)
+ else
{
- var newPropertyGroup = project.CreatePropertyGroupElement();
- newPropertyGroup.Condition = $"'$(Configuration)|$(Platform)' == '{newConfiguration}'";
- if (insertBefore != null)
- {
- project.InsertBeforeChild(newPropertyGroup, insertBefore);
- }
- else if (insertAfter != null)
- {
- project.InsertAfterChild(newPropertyGroup, insertAfter);
- }
- else
- {
- project.AppendChild(newPropertyGroup);
- }
- insertBefore = null;
- insertAfter = newPropertyGroup;
+ configurationsProperty.Value = configurationsValue;
}
}
@@ -280,10 +252,14 @@ private void UpdateSolution(ITaskItem solutionRootItem)
Log.LogMessage($"Generating solution for '{solutionRootPath}'...");
+ string solutionName = GetNameForSolution(solutionRootPath);
+ string slnFile = Path.Combine(solutionRootPath, solutionName + ".sln");
+ Solution solution = new Solution(slnFile);
+
StringBuilder slnBuilder = new StringBuilder();
slnBuilder.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
- slnBuilder.AppendLine("# Visual Studio 14");
- slnBuilder.AppendLine("VisualStudioVersion = 14.0.25420.1");
+ slnBuilder.AppendLine("# Visual Studio 15");
+ slnBuilder.AppendLine("VisualStudioVersion = 15.0.27213.1");
slnBuilder.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
@@ -376,10 +352,13 @@ private void UpdateSolution(ITaskItem solutionRootItem)
}
slnBuilder.AppendLine("\tEndGlobalSection");
+ // Output the extensibility globals
+ slnBuilder.AppendLine("\tGlobalSection(ExtensibilityGlobals) = postSolution");
+ slnBuilder.AppendLine($"\t\tSolutionGuid = {solution.Guid}");
+ slnBuilder.AppendLine("\tEndGlobalSection");
+
slnBuilder.AppendLine("EndGlobal");
- string solutionName = GetNameForSolution(solutionRootPath);
- string slnFile = Path.Combine(solutionRootPath, solutionName + ".sln");
File.WriteAllText(slnFile, slnBuilder.ToString());
}
@@ -440,6 +419,41 @@ public ProjectFolder(string basePath, string relPath, string projectId, string p
}
}
+ internal class Solution
+ {
+ public string Path { get; }
+ public string Guid { get; }
+
+ public Solution(string path)
+ {
+ Path = path;
+ Guid = ReadSolutionGuid(path);
+ }
+
+ private static string ReadSolutionGuid(string path)
+ {
+ string solutionGuid = null;
+ if (File.Exists(path))
+ {
+ foreach (string line in File.ReadLines(path))
+ {
+ if (line.StartsWith("\t\tSolutionGuid = "))
+ {
+ solutionGuid = line.Substring("\t\tSolutionGuid = ".Length);
+ break;
+ }
+ }
+ }
+
+ if (solutionGuid == null)
+ {
+ solutionGuid = System.Guid.NewGuid().ToString("B").ToUpper();
+ }
+
+ return solutionGuid;
+ }
+ }
+
internal class SolutionProject
{
public string ProjectPath { get; }
@@ -507,10 +521,10 @@ public string SolutionGuid
{
//ProjectTypeGuids for different projects, pulled from the Visual Studio regkeys
//TODO: Clean up or map these to actual projects, this is fragile
- string slnGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; // Windows (C#)
+ string slnGuid = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"; // Windows (C#) Managed/CPS
if (ProjectPath.Contains("VisualBasic.vbproj"))
{
- slnGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"; //Windows (VB.NET)
+ slnGuid = "{778DAE3C-4631-46EA-AA77-85C1314464D9}"; //Windows (VB.NET) Managed/CPS
}
if (ProjectPath.Contains("TestNativeService")) //Windows (Visual C++)
{