Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion documentation/general/dotnet-run-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Additionally, the implicit project file has the following customizations:

- `PublishAot` is set to `true`, see [`dotnet publish file.cs`](#other-commands) for more details.

- `PackAsTool` is set to `true`, see [`dotnet pack file.cs`](#other-commands) for more details.

- `UserSecretsId` is set to a hash of the entry point file path.

- [File-level directives](#directives-for-project-metadata) are applied.
Expand Down Expand Up @@ -102,8 +104,14 @@ and working directory is not changed (e.g., `cd /x/ && dotnet run /y/file.cs` ru
If a dash (`-`) is given instead of the target path (i.e., `dotnet run -`), the C# file to be executed is read from the standard input.
In this case, the current working directory is not used to search for other files (launch profiles, other sources in case of multi-file apps);
the compilation consists solely of the single file read from the standard input.
However, the current working directory is still used as the working directory for building and executing the program.
To reference projects relative to the current working directory (instead of relative to the temporary directory the file is isolated in),
you can use something like `#:project $(MSBuildStartupDirectory)/relative/path`.

`dotnet path.cs` is a shortcut for `dotnet run --file path.cs` provided that `path.cs` is a valid [target path](#target-path) (`dotnet -` is currently not supported).
`dotnet path.cs` is a shortcut for `dotnet run --file path.cs` provided that `path.cs` is a valid [target path](#target-path) (`dotnet -` is currently not supported)
and it is not a DLL path, built-in command, or a NuGet tool (e.g., `dotnet watch` invokes the `dotnet-watch` tool
even if a valid `watch` file-based app exists in the current directory;
one can use `dotnet ./watch` to run the file-based app).

### Other commands

Expand All @@ -112,6 +120,8 @@ Commands `dotnet restore file.cs` and `dotnet build file.cs` are needed for IDE
Commands `dotnet publish file.cs` and `dotnet pack file.cs` are also supported for file-based programs.
Note that file-based apps have implicitly set `PublishAot=true`, so publishing uses Native AOT (and building reports AOT warnings).
To opt out, use `#:property PublishAot=false` directive in your `.cs` file.
Additionally, file-based apps have implicitly set `PackAsTool=true` because file-based apps are usually tools;
again, you can opt out via `#:property PackAsTool=false`.

Command `dotnet clean file.cs` can be used to clean build artifacts of the file-based program.

Expand Down
16 changes: 8 additions & 8 deletions github-merge-flow.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,42 @@
// Automate opening PRs to merge cli release/8.0.1xx to 8.0.3xx
"release/8.0.1xx":{
"MergeToBranch": "release/8.0.3xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Versions.props;eng/common/*"
},
// Automate opening PRs to merge cli release/8.0.3xx to 8.0.4xx
"release/8.0.3xx":{
"MergeToBranch": "release/8.0.4xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Versions.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from release/8.0.4xx to 9.0.1xx
"release/8.0.4xx":{
"MergeToBranch": "release/9.0.1xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Versions.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from release/9.0.1xx to release/9.0.3xx
"release/9.0.1xx":{
"MergeToBranch": "release/9.0.3xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Versions.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from release/9.0.3xx to release/10.0.1xx
"release/9.0.3xx":{
"MergeToBranch": "release/10.0.1xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Version.Details.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from release/10.0.1xx to release/10.0.2xx
"release/10.0.1xx":{
"MergeToBranch": "release/10.0.2xx",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Version.Details.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from release/10.0.2xx to main
"release/10.0.2xx":{
"MergeToBranch": "main",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Version.Details.props;eng/common/*"
},
// Automate opening PRs to merge sdk repos from dnup to release/dnup
"dnup":{
"MergeToBranch": "release/dnup",
"ExtraSwitches": "-QuietComments"
"ExtraSwitches": "-QuietComments -ResetToTargetPaths global.json;NuGet.config;eng/Version.Details.xml;eng/Versions.props;eng/common/*"
}
}
}
7 changes: 5 additions & 2 deletions src/BuiltInTools/HotReloadClient/DefaultHotReloadClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ async Task<ImmutableArray<string>> ConnectAsync()
// When the client connects, the first payload it sends is the initialization payload which includes the apply capabilities.

var capabilities = (await ClientInitializationResponse.ReadAsync(_pipe, cancellationToken)).Capabilities;
Logger.Log(LogEvents.Capabilities, capabilities);

var result = AddImplicitCapabilities(capabilities.Split(' '));

Logger.Log(LogEvents.Capabilities, string.Join(" ", result));

// fire and forget:
_ = ListenForResponsesAsync(cancellationToken);

return [.. capabilities.Split(' ')];
return result;
}
catch (Exception e) when (e is not OperationCanceledException)
{
Expand Down
7 changes: 7 additions & 0 deletions src/BuiltInTools/HotReloadClient/HotReloadClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ internal abstract class HotReloadClient(ILogger logger, ILogger agentLogger) : I
internal Task PendingUpdates
=> _pendingUpdates;

/// <summary>
/// .NET Framework runtime does not support adding MethodImpl entries, therefore the capability is not in the baseline capability set.
/// All other runtimes (.NET and Mono) support it and rather than servicing all of them we include the capability here.
/// </summary>
protected static ImmutableArray<string> AddImplicitCapabilities(IEnumerable<string> capabilities)
=> [.. capabilities, "AddExplicitInterfaceImplementation"];

public abstract void ConfigureLaunchEnvironment(IDictionary<string, string> environmentBuilder);

/// <summary>
Expand Down
24 changes: 15 additions & 9 deletions src/BuiltInTools/HotReloadClient/Web/WebAssemblyHotReloadClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,30 @@ internal sealed class WebAssemblyHotReloadClient(

private static ImmutableArray<string> GetUpdateCapabilities(ILogger logger, ImmutableArray<string> projectHotReloadCapabilities, Version projectTargetFrameworkVersion)
{
var capabilities = projectHotReloadCapabilities;

if (capabilities.IsEmpty)
{
logger.LogDebug("Using capabilities based on project target framework version: '{Version}'.", projectTargetFrameworkVersion);

capabilities = projectTargetFrameworkVersion.Major switch
var capabilities = projectHotReloadCapabilities.IsEmpty
? projectTargetFrameworkVersion.Major switch
{
9 => s_defaultCapabilities90,
8 => s_defaultCapabilities80,
7 => s_defaultCapabilities70,
6 => s_defaultCapabilities60,
_ => [],
};
}
: projectHotReloadCapabilities;

if (capabilities is not [])
{
capabilities = AddImplicitCapabilities(capabilities);
}

var capabilitiesStr = string.Join(", ", capabilities);
if (projectHotReloadCapabilities.IsEmpty)
{
logger.LogDebug("Project specifies capabilities: {Capabilities}.", capabilitiesStr);
}
else
{
logger.LogDebug("Project specifies capabilities: '{Capabilities}'", string.Join(" ", capabilities));
logger.LogDebug("Using capabilities based on project target framework version: '{Version}': {Capabilities}.", projectTargetFrameworkVersion, capabilitiesStr);
}

return capabilities;
Expand Down
11 changes: 8 additions & 3 deletions src/BuiltInTools/Watch/Process/LaunchSettingsProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal sealed class LaunchSettingsProfile

internal static LaunchSettingsProfile? ReadLaunchProfile(string projectPath, string? launchProfileName, ILogger logger)
{
var launchSettingsPath = LaunchSettingsLocator.TryFindLaunchSettings(projectPath, launchProfileName, (message, isError) =>
var launchSettingsPath = LaunchSettings.TryFindLaunchSettingsFile(projectPath, launchProfileName, (message, isError) =>
{
if (isError)
{
Expand Down Expand Up @@ -94,11 +94,16 @@ internal sealed class LaunchSettingsProfile
return null;
}

var defaultProfileKey = launchSettings.Profiles.FirstOrDefault(entry => entry.Value.CommandName == "Project").Key;
// Look for the first profile with a supported command name
// Note: These must match the command names supported by LaunchSettingsManager in src/Cli/dotnet/Commands/Run/LaunchSettings/
var supportedCommandNames = new[] { "Project", "Executable" };
var defaultProfileKey = launchSettings.Profiles.FirstOrDefault(entry =>
entry.Value.CommandName != null && supportedCommandNames.Contains(entry.Value.CommandName, StringComparer.Ordinal)).Key;

if (defaultProfileKey is null)
{
logger.LogDebug("Unable to find 'Project' command in the default launch profile.");
logger.LogDebug("Unable to find a supported command name in the default launch profile. Supported types: {SupportedTypes}",
string.Join(", ", supportedCommandNames));
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,16 @@ public Option<IEnumerable<string>> ForwardAsManyArgumentsEachPrefixedByOption(st
/// <summary>
/// Calls the forwarding functions for all options that have declared a forwarding function (via <see cref="ForwardedOptionExtensions"/>'s extension members) in the provided <see cref="ParseResult"/>.
/// </summary>
/// <param name="parseResult"></param>
/// <param name="command">If not provided, uses the <see cref="ParseResult.CommandResult" />'s <see cref="CommandResult.Command"/>.</param>
/// <returns></returns>
public IEnumerable<string> OptionValuesToBeForwarded(Command? command = null) =>
(command ?? parseResult.CommandResult.Command)
.Options
public IEnumerable<string> OptionValuesToBeForwarded(Command? command = null)
=> parseResult.OptionValuesToBeForwarded((command ?? parseResult.CommandResult.Command).Options);

/// <summary>
/// Calls the forwarding functions for all options that have declared a forwarding function (via <see cref="ForwardedOptionExtensions"/>'s extension members) in the provided <see cref="ParseResult"/>.
/// </summary>
/// <param name="command">If not provided, uses the <see cref="ParseResult.CommandResult" />'s <see cref="CommandResult.Command"/>.</param>
public IEnumerable<string> OptionValuesToBeForwarded(IEnumerable<Option> options)
=> options
.Select(o => o.ForwardingFunction)
.SelectMany(f => f is not null ? f(parseResult) : []);

Expand All @@ -191,9 +195,6 @@ public IEnumerable<string> OptionValuesToBeForwarded(Command? command = null) =>
/// invokes its forwarding function (if any) and returns the result. If no option with that name is found, or if the option
/// has no forwarding function, returns an empty enumeration.
/// </summary>
/// <param name="command"></param>
/// <param name="alias"></param>
/// <returns></returns>
public IEnumerable<string> ForwardedOptionValues(Command command, string alias)
{
var func = command.Options?
Expand Down
8 changes: 8 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,12 @@ public void ApplyPropertiesToRestore()
RestoreGlobalProperties = new(newdict);
}
}

internal string[]? GetResolvedTargets()
=> this switch
{
{ RequestedTargets: null or { Length: 0 } } => GetTargetResult,
{ GetTargetResult: null or { Length: 0 } } => RequestedTargets,
_ => [.. RequestedTargets.Union(GetTargetResult, StringComparer.OrdinalIgnoreCase)]
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../Microsoft.DotNet.Cli.CommandLine/Microsoft.DotNet.Cli.CommandLine.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="../Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="../Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="..\Microsoft.DotNet.Cli.CommandLine\Microsoft.DotNet.Cli.CommandLine.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="..\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="..\Microsoft.DotNet.Configurer\Microsoft.DotNet.Configurer.csproj" GlobalPropertiesToRemove="PublishDir" />
<ProjectReference Include="..\..\Microsoft.DotNet.ProjectTools\Microsoft.DotNet.ProjectTools.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/Microsoft.TemplateEngine.Cli/TelemetryHelper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Utilities;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Utils;

Expand Down
1 change: 1 addition & 0 deletions src/Cli/Microsoft.TemplateEngine.Cli/TemplateInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Text.RegularExpressions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.Extensions;
using Microsoft.DotNet.Utilities;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.TemplatePackage;
using Microsoft.TemplateEngine.Cli.Commands;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#nullable disable

using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Utilities;

namespace Microsoft.DotNet.Cli.CommandFactory.CommandResolution;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ internal void GenerateDepsJsonFile(
string? stdOut;
string? stdErr;

var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption);
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandDefinition.TargetOption, BuildCommandDefinition.VerbosityOption, BuildCommandDefinition.NoLogoOption);
var forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging(msbuildArgs, msBuildExePath);
if (forwardingAppWithoutLogging.ExecuteMSBuildOutOfProc)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Cli/dotnet/CommandLineInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static void PrintInfo()
Reporter.Output.WriteLine($"{LocalizableStrings.DotNetSdkInfoLabel}");
Reporter.Output.WriteLine($" Version: {Product.Version}");
Reporter.Output.WriteLine($" Commit: {commitSha}");
Reporter.Output.WriteLine($" Workload version: {WorkloadCommandParser.GetWorkloadsVersion()}");
Reporter.Output.WriteLine($" Workload version: {WorkloadCommandDefinition.GetWorkloadsVersion()}");
Reporter.Output.WriteLine($" MSBuild version: {MSBuildForwardingAppWithoutLogging.MSBuildVersion.ToString()}");
Reporter.Output.WriteLine();
Reporter.Output.WriteLine($"{LocalizableStrings.DotNetRuntimeInfoLabel}");
Expand All @@ -40,7 +40,7 @@ private static void PrintWorkloadsInfo()
{
Reporter.Output.WriteLine();
Reporter.Output.WriteLine($"{LocalizableStrings.DotnetWorkloadInfoLabel}");
WorkloadCommandParser.ShowWorkloadsInfo(showVersion: false);
WorkloadCommandDefinition.ShowWorkloadsInfo(showVersion: false);
}

private static string GetDisplayRid(DotnetVersionFile versionFile)
Expand Down
17 changes: 8 additions & 9 deletions src/Cli/dotnet/Commands/Build/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,27 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui
parseResult.ShowHelpOrErrorIfAppropriate();

CommonOptions.ValidateSelfContainedOptions(
parseResult.HasOption(BuildCommandParser.SelfContainedOption),
parseResult.HasOption(BuildCommandParser.NoSelfContainedOption));
parseResult.HasOption(BuildCommandDefinition.SelfContainedOption),
parseResult.HasOption(BuildCommandDefinition.NoSelfContainedOption));

bool noRestore = parseResult.HasOption(BuildCommandParser.NoRestoreOption);
bool noRestore = parseResult.HasOption(BuildCommandDefinition.NoRestoreOption);

return CommandFactory.CreateVirtualOrPhysicalCommand(
BuildCommandParser.GetCommand(),
BuildCommandParser.SlnOrProjectOrFileArgument,
(msbuildArgs, appFilePath) => new VirtualProjectBuildingCommand(
BuildCommandDefinition.SlnOrProjectOrFileArgument,
configureVirtualCommand: (msbuildArgs, appFilePath) => new VirtualProjectBuildingCommand(
entryPointFileFullPath: Path.GetFullPath(appFilePath),
msbuildArgs: msbuildArgs
)
msbuildArgs: msbuildArgs)
{
NoRestore = noRestore,
NoCache = true,
},
(msbuildArgs, msbuildPath) => new RestoringCommand(
createPhysicalCommand: (msbuildArgs, msbuildPath) => new RestoringCommand(
msbuildArgs: msbuildArgs.CloneWithAdditionalArgs("-consoleloggerparameters:Summary"),
noRestore: noRestore,
msbuildPath: msbuildPath
),
[CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption],
[CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandDefinition.TargetOption, BuildCommandDefinition.VerbosityOption, BuildCommandDefinition.NoLogoOption],
parseResult,
msbuildPath
);
Expand Down
Loading