|
1 | 1 | // Copyright (c) .NET Foundation. All rights reserved. |
2 | 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. |
3 | 3 |
|
4 | | -using System.Runtime.InteropServices; |
5 | 4 | using System.Text; |
6 | 5 | using System.Text.RegularExpressions; |
7 | 6 | using Azure.Functions.Cli.Common; |
@@ -39,52 +38,62 @@ public static void EnsureDotnet() |
39 | 38 | /// Function that determines TargetFramework of a project even when it's defined outside of the .csproj file, |
40 | 39 | /// e.g. in Directory.Build.props. |
41 | 40 | /// </summary> |
42 | | - /// <param name="projectDirectory">Directory containing the .csproj file.</param> |
43 | | - /// <param name="projectFilename">Name of the .csproj file.</param> |
| 41 | + /// <param name="workingDirectory">Directory containing the .csproj file.</param> |
44 | 42 | /// <returns>Target framework, e.g. net8.0.</returns> |
45 | 43 | /// <exception cref="CliException">Unable to determine target framework.</exception> |
46 | | - public static async Task<string> DetermineTargetFramework(string projectDirectory, string projectFilename = null) |
| 44 | + public static async Task<string> DetermineTargetFrameworkAsync(string workingDirectory) |
47 | 45 | { |
48 | 46 | EnsureDotnet(); |
49 | | - if (projectFilename == null) |
50 | | - { |
51 | | - var projectFilePath = ProjectHelpers.FindProjectFile(projectDirectory); |
52 | | - if (projectFilePath != null) |
53 | | - { |
54 | | - projectFilename = Path.GetFileName(projectFilePath); |
55 | | - } |
56 | | - } |
| 47 | + |
| 48 | + string projectFilePath = ProjectHelpers.FindProjectFile(workingDirectory); |
| 49 | + |
| 50 | + string args = |
| 51 | + $"msbuild \"{projectFilePath}\" " + |
| 52 | + "-nologo -v:q -restore:false " + |
| 53 | + "-getProperty:TargetFrameworks " + |
| 54 | + "-getProperty:TargetFramework"; |
57 | 55 |
|
58 | 56 | var exe = new Executable( |
59 | 57 | "dotnet", |
60 | | - $"build {projectFilename} -getproperty:TargetFramework", |
61 | | - workingDirectory: projectDirectory, |
62 | | - environmentVariables: new Dictionary<string, string> |
63 | | - { |
64 | | - // https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables |
65 | | - ["DOTNET_NOLOGO"] = "1", // do not write disclaimer to stdout |
66 | | - ["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1", // just in case |
67 | | - }); |
| 58 | + args, |
| 59 | + workingDirectory: workingDirectory, |
| 60 | + environmentVariables: new Dictionary<string, string> { ["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1" }); |
68 | 61 |
|
69 | | - StringBuilder output = new(); |
70 | | - var exitCode = await exe.RunAsync(o => output.Append(o), e => ColoredConsole.Error.WriteLine(ErrorColor(e))); |
71 | | - if (exitCode != 0) |
| 62 | + var stdOut = new StringBuilder(); |
| 63 | + var stdErr = new StringBuilder(); |
| 64 | + |
| 65 | + int exit = await exe.RunAsync(s => stdOut.Append(s), s => stdErr.Append(s)); |
| 66 | + if (exit != 0) |
72 | 67 | { |
73 | | - throw new CliException($"Can not determine target framework for dotnet project at ${projectDirectory}"); |
| 68 | + throw new CliException( |
| 69 | + $"Unable to evaluate target framework for '{projectFilePath}'.\nError output:\n{stdErr}"); |
74 | 70 | } |
75 | 71 |
|
76 | | - // Extract the target framework moniker (TFM) from the output using regex pattern matching |
77 | | - var outputString = output.ToString(); |
| 72 | + string output = stdOut.ToString(); |
| 73 | + |
| 74 | + var uniqueTfms = new HashSet<string>(StringComparer.OrdinalIgnoreCase); |
| 75 | + foreach (Match m in TargetFrameworkHelper.TfmRegex.Matches(output)) |
| 76 | + { |
| 77 | + if (m.Success && !string.IsNullOrEmpty(m.Value)) |
| 78 | + { |
| 79 | + uniqueTfms.Add(m.Value); |
| 80 | + } |
| 81 | + } |
78 | 82 |
|
79 | | - // Look for a line that looks like a target framework moniker |
80 | | - var tfm = TargetFrameworkHelper.TfmRegex.Match(outputString); |
| 83 | + if (uniqueTfms.Count == 0) |
| 84 | + { |
| 85 | + throw new CliException( |
| 86 | + $"Could not parse target framework from msbuild output for '{projectFilePath}'.\nStdout:\n{output}\nStderr:\n{stdErr}"); |
| 87 | + } |
81 | 88 |
|
82 | | - if (!tfm.Success) |
| 89 | + if (uniqueTfms.Count == 1) |
83 | 90 | { |
84 | | - throw new CliException($"Could not parse target framework from output: {outputString}"); |
| 91 | + return uniqueTfms.First(); |
85 | 92 | } |
86 | 93 |
|
87 | | - return tfm.Value; |
| 94 | + ColoredConsole.WriteLine("Multiple target frameworks detected."); |
| 95 | + SelectionMenuHelper.DisplaySelectionWizardPrompt("target framework"); |
| 96 | + return SelectionMenuHelper.DisplaySelectionWizard(uniqueTfms.ToArray()); |
88 | 97 | } |
89 | 98 |
|
90 | 99 | public static async Task DeployDotnetProject(string name, bool force, WorkerRuntime workerRuntime, string targetFramework = "") |
|
0 commit comments