-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Is your feature request related to a problem? Please describe.
When running a project, dotnet run
has a protocol that it implements to determine how to run the project:
- Detect the project that should be run
- Determine the 'launch settings' and profile that will be applied to the project
- Build the project if required
- Determine the RunCommand/RunArguments/RunWorkingDirectory for the project to create an executable ICommand
- Apply 'launch settings' to the ICommand
- Invoke the ICommand
In a graphic this looks like:
sequenceDiagram
participant dotnet as dotnet CLI
participant project as myproj.proj
participant exe as RunCommand
dotnet->>dotnet: detect project to run
dotnet->>dotnet: read launch settings from file and pick launch profile
dotnet->>project: build project (if required)
dotnet->>project: evaluate project to get run settings
dotnet->>exe: create process to spawn from run settings
dotnet->>exe: apply launch profile to process
dotnet->>exe: spawn process
dotnet->>exe: run process to completion
This process relies on MSBuild evaluation to determine the RunCommand/RunArguments/RunWorkingDirectory, which means that these values can only be set during evaluation - no code or logic can run to influence their values. This can be highly limiting and means that use cases that need to run some dynamic logic to determine a value to put in the RunWorkingDirectory, for example, cannot be safely run.
Describe the solution you'd like
We should have an opt-in protocol that would allow dotnet run
to invoke a target to get the RunCommand/RunArguments/RunWorkingDirectory data. This target should be public and documented and would update step 4 above as follows:
- Determine the RunCommand/RunArguments/RunWorkingDirectory for the project to create an executable ICommand
a. if the project supports a ComputeRunCommand Target, then run that target and read the RunCommand/RunArguments/RunWorkingDirectory after target execution
b. otherwise read the same properties just after evaluation, as is done today
c. when called, this target would be passed all of the same MSBuild properties as applied to the implicit build in step 3
In a graphic this would look like:
sequenceDiagram
participant dotnet as dotnet CLI
participant project as myproj.proj
participant exe as RunCommand
dotnet->>dotnet: detect project to run
dotnet->>dotnet: read launch settings from file and pick launch profile
dotnet->>project: build project (if required)
dotnet->>project: evaluate project
dotnet->>project: invoke target to get run settings
project->>dotnet: return run settings
dotnet->>exe: create process to spawn from run settings
dotnet->>exe: apply launch profile to process
dotnet->>exe: spawn process
dotnet->>exe: run process to completion
Run Command Protocol
This new target would need to define its protocol
- Name
- Dependencies - what is a reasonable dependency chain for this Target? How do projects like MAUI change this dependency chain?
- Outputs - should the target set properties, or should we take the opportunity to make a different representation
Opting-in
Projects would need to opt into the new behavior - the SDK currently computes the values here and so could change this for SDK-style projects as a default. Should there be a property-based opt-in, or should we just start doing this wholesale since the CLI and SDK targets change in lockstep?
Use cases like Azure Functions or MAUI may want to override the generation and so could override the target or set up a BeforeTargets, etc.
Compatibility
- The MSBuild Run target defined in the SDK should have a dependency on the new target if defined.
- The
dotnet watch
command currently uses the RunCommand/RunArguments/RunWorkingDirectory as inputs toGenerateWatchList
- it will need to become aware of this target if necessary as well. - We should add a new ProjectCapability signalling that a Project uses this new mechanism, so that IDEs have a flag for behavior.
- The new Target could be integrated into the Design-Time Build dependency chain.
Binlogs
We would to to ensure that if a binlog was requested that the configured binlog logger also applied to this new target, not just the implicit build + project evaluation for Run argument discovery
Additional context
@captainsafia for Aspire
@fabiocav for Functions
@jonathanpeppers for MAUI
@danroth27 for web
@tmat for watch
@tmeschter for project-system