Skip to content

Commit

Permalink
Merge branch 'dev/dianasoltani/MobileAppTargetFrameworks-fix' of http…
Browse files Browse the repository at this point in the history
…s://github.com/dotnet/upgrade-assistant into dev/dianasoltani/MobileAppTargetFrameworks-fix
  • Loading branch information
Diana Soltani committed Mar 16, 2023
2 parents 492dbb8 + 6fe6d91 commit 87faa63
Show file tree
Hide file tree
Showing 40 changed files with 775 additions and 305 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@
<data name="ListExtensionItem" xml:space="preserve">
<value>{Name}: {Source}</value>
</data>
<data name="MacOSWarning" xml:space="preserve">
<value>MacOS support for this tool is limited to migrating Xamarin.Forms to MAUI. Other migration paths are not supported and may or may not work correctly.</value>
</data>
<data name="NonWindowsWarning" xml:space="preserve">
<value>This tool is not supported on non-Windows platforms due to dependencies on Visual Studio.</value>
</data>
Expand Down
6 changes: 5 additions & 1 deletion src/cli/Microsoft.DotNet.UpgradeAssistant.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ public static class Program
{
public static Task<int> Main(string[] args)
{
if (FeatureFlags.IsWindowsCheckEnabled && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Console.WriteLine(LocalizedStrings.MacOSWarning);
}
else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Console.WriteLine(LocalizedStrings.NonWindowsWarning);
return Task.FromResult(ErrorCodes.PlatformNotSupported);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ public static class FeatureFlags
{
private const string AnalyzeBinaries = "ANALYZE_BINARIES";
private const string SolutionWideSdkConversion = "SOLUTION_WIDE_SDK_CONVERSION";
private const string EnableCrossPlatform = "ENABLE_CROSS_PLATFORM";

public static readonly IReadOnlyCollection<string> RegisteredFeatures = new[]
{
SolutionWideSdkConversion,
EnableCrossPlatform,
AnalyzeBinaries
};

Expand All @@ -38,8 +36,6 @@ private static ICollection<string> CreateFeatures()

public static bool IsRegistered(string name) => _features.Contains(name);

public static bool IsWindowsCheckEnabled => !_features.Contains(EnableCrossPlatform);

public static bool IsAnalyzeBinariesEnabled => _features.Contains(AnalyzeBinaries);

public static bool IsSolutionWideSdkConversionEnabled => _features.Contains(SolutionWideSdkConversion);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;

namespace Microsoft.DotNet.UpgradeAssistant
{
public static class PathHelpers
{
public static string GetNativePath(string path)
{
if (Path.DirectorySeparatorChar == '/')
{
return path.Replace('\\', '/');
}

return path;
}

public static string GetIncludePath(string path)
{
if (Path.DirectorySeparatorChar == '/')
{
return path.Replace('/', '\\');
}

return path;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,17 @@ public void AddItem(ProjectItemDescriptor projectItem)
var item = ProjectRoot.CreateItemElement(projectItem.ItemType.Name);
if (projectItem.Include is not null)
{
item.Include = projectItem.Include;
item.Include = PathHelpers.GetIncludePath(projectItem.Include);
}

if (projectItem.Exclude is not null)
{
item.Exclude = projectItem.Remove;
item.Exclude = PathHelpers.GetIncludePath(projectItem.Exclude);
}

if (projectItem.Remove is not null)
{
item.Remove = projectItem.Remove;
item.Remove = PathHelpers.GetIncludePath(projectItem.Remove);
}

itemGroup.AppendChild(item);
Expand Down Expand Up @@ -230,9 +230,11 @@ public void RemoveProperty(string propertyName)
}
}

private static string GetPathRelativeToProject(string path, string projectDir) =>
Path.IsPathFullyQualified(path)
? path
: Path.Combine(projectDir, path);
private static string GetPathRelativeToProject(string path, string projectDir)
{
path = PathHelpers.GetNativePath(path);

return Path.IsPathFullyQualified(path) ? path : Path.Combine(projectDir, path);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Evaluation;
Expand All @@ -18,6 +19,8 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
{
internal sealed class MSBuildWorkspaceUpgradeContext : IUpgradeContext, IDisposable
{
private const string MacOSMonoFrameworkMSBuildExtensionsDir = "/Library/Frameworks/Mono.framework/External/xbuild";

private readonly ILogger<MSBuildWorkspaceUpgradeContext> _logger;
private readonly Dictionary<string, IProject> _projectCache;
private readonly IOptions<WorkspaceOptions> _options;
Expand Down Expand Up @@ -140,20 +143,119 @@ public IEnumerable<IProject> Projects
}
}

private static void CreateSymbolicLinks(string targetDir, string sourceDir)
{
foreach (var entry in Directory.EnumerateFileSystemEntries(sourceDir))
{
var target = Path.Combine(targetDir, Path.GetFileName(entry));

var fileInfo = new FileInfo(target);
if (fileInfo.Exists)
{
if (fileInfo.LinkTarget is not null && fileInfo.LinkTarget.Equals(entry, StringComparison.Ordinal))
{
continue;
}

File.Delete(target);
}
else
{
var dirInfo = new DirectoryInfo(target);
if (dirInfo.Exists)
{
if (dirInfo.LinkTarget is not null && dirInfo.LinkTarget.Equals(entry, StringComparison.Ordinal))
{
continue;
}

Directory.Delete(target);
}
}

File.CreateSymbolicLink(target, entry);
}
}

private static string? GetMacOSMSBuildExtensionsPath(WorkspaceOptions options)
{
const string DefaultDotnetSdkLocation = "/usr/local/share/dotnet/sdk/";

if (options.MSBuildPath == null || !options.MSBuildPath.StartsWith(DefaultDotnetSdkLocation, StringComparison.Ordinal))
{
return null;
}

string? msbuildExtensionsPath = null;

if (Directory.Exists(MacOSMonoFrameworkMSBuildExtensionsDir))
{
// Check to see if the specified MSBuildPath contains the Mono.framework build extensions.
var monoExtensionDirectories = Directory.GetDirectories(MacOSMonoFrameworkMSBuildExtensionsDir);
var createTempExtensionsDir = false;

foreach (var monoExtensionDir in monoExtensionDirectories)
{
var dotnetExtensionDir = Path.Combine(options.MSBuildPath, Path.GetFileName(monoExtensionDir));
if (!Directory.Exists(dotnetExtensionDir))
{
createTempExtensionsDir = true;
break;
}
}

// If the specified MSBuildPath does not contain the Mono.framework build extensions, create a temp
// directory that we'll use to symlink everything.
if (createTempExtensionsDir)
{
var homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var versionDir = Path.GetFileName(options.MSBuildPath.TrimEnd('/'));

msbuildExtensionsPath = Path.Combine(homeDir, ".dotnet-upgrade-assistant", "dotnet-sdk", versionDir);

if (!Directory.Exists(msbuildExtensionsPath))
{
Directory.CreateDirectory(msbuildExtensionsPath);
}

// First, create symbolic links to all of the dotnet MSBuild file system entries.
CreateSymbolicLinks(msbuildExtensionsPath, options.MSBuildPath);

// Then create the symbolic links to the Mono.framework/External/xbuild system entries.
CreateSymbolicLinks(msbuildExtensionsPath, MacOSMonoFrameworkMSBuildExtensionsDir);
}
}

return msbuildExtensionsPath;
}

private static Dictionary<string, string> CreateProperties(WorkspaceOptions options)
{
var properties = new Dictionary<string, string>();

if (options.VisualStudioPath is string vsPath)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
properties.Add("VSINSTALLDIR", vsPath);
properties.Add("MSBuildExtensionsPath32", Path.Combine(vsPath, "MSBuild"));
properties.Add("MSBuildExtensionsPath", Path.Combine(vsPath, "MSBuild"));
}
if (options.VisualStudioPath is string vsPath)
{
properties.Add("VSINSTALLDIR", vsPath);
properties.Add("MSBuildExtensionsPath32", Path.Combine(vsPath, "MSBuild"));
properties.Add("MSBuildExtensionsPath", Path.Combine(vsPath, "MSBuild"));
}

if (options.VisualStudioVersion is int version)
if (options.VisualStudioVersion is int version)
{
properties.Add("VisualStudioVersion", $"{version}.0");
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
properties.Add("VisualStudioVersion", $"{version}.0");
var msbuildExtensionsPath = GetMacOSMSBuildExtensionsPath(options);

if (msbuildExtensionsPath != null)
{
properties.Add("MSBuildExtensionsPath32", msbuildExtensionsPath);
properties.Add("MSBuildExtensionsPath", msbuildExtensionsPath);
}
}

return properties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Linq;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
Expand Down Expand Up @@ -78,7 +79,8 @@ internal static void WorkAroundRoslynIssue36781(this ProjectRootElement rootElem
}

// Skip items that are only included once
if (project.Items.Count(i2 => i2.EvaluatedInclude.Equals(i.EvaluatedInclude, StringComparison.Ordinal)) <= 1)
var path = PathHelpers.GetIncludePath(i.EvaluatedInclude);
if (project.Items.Count(i2 => PathHelpers.GetIncludePath(i2.EvaluatedInclude).Equals(path, StringComparison.OrdinalIgnoreCase)) <= 1)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,16 @@ public VisualStudioFinder(ILogger<VisualStudioFinder> logger)

public void Configure(WorkspaceOptions options)
{
(options.VisualStudioPath, options.VisualStudioVersion) = GetLatestVisualStudioPath(options.VisualStudioPath);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
(options.VisualStudioPath, options.VisualStudioVersion) = GetLatestVisualStudioPath(options.VisualStudioPath);
}
else
{
// MSBuildWorkspaceUpgradeContext.CreateProperties() uses the VS path to set the MSBuildExtensionsPath[32]
// environment variables and there is some logging in UpgraderMsBuildExtensions.AddMsBuild().
_logger.LogInformation("Visual Studio path not required on macOS");
}
}

private (string? Path, int? Version) GetLatestVisualStudioPath(string? suppliedPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,20 @@ private static IEnumerable<Operation<NuGetReference>> UpdatePackageAddition(IDep
var containsService = false;
foreach (var f in files)
{
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(f)).GetRoot();
if (ContainsIdentifier(root, "ChannelFactory") || ContainsIdentifier(root, "ClientBase"))
{
return packages.Additions;
}
var path = PathHelpers.GetNativePath(f);

if (!containsService && ContainsIdentifier(root, "ServiceHost"))
if (File.Exists(path))
{
containsService = true;
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot();
if (ContainsIdentifier(root, "ChannelFactory") || ContainsIdentifier(root, "ClientBase"))
{
return packages.Additions;
}

if (!containsService && ContainsIdentifier(root, "ServiceHost"))
{
containsService = true;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Avoid ID conflicts with the package project. -->
<PackageId>*$(MSBuildProjectFullPath)*</PackageId>
<PackageId>Real.Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers</PackageId>
</PropertyGroup>
<ItemGroup>
<None Remove="DefaultApiAlerts.apitargets" />
Expand Down
Loading

0 comments on commit 87faa63

Please sign in to comment.