In order to build and test the .NET Core Command-line Interface (CLI), you need the following installed on you machine:
- git (available from the Git Website) on the PATH.
- Visual Studio "Desktop development with C++" workload with all defaults (see Native AOT prerequisites).
- git (available from your package manager or the Git Website) on the PATH.
- git (available from Homebrew or the Git Website) on the PATH.
Run the following command from the root of the repository:
build.cmd
The build script will output a dotnet installation to artifacts\bin\redist\Debug\dotnet that will include any local changes to the .NET Core CLI.
As part of the build, some intermediate files will get generated which may run into long-path issues. If you encounter a build failure with an error message similar to Resource file [filename].resx cannot be found., enable long paths and try again.
The simple way to launch Visual Studio after building via build.cmd is to double-click the VS with sdk.slnx Windows shortcut in the artifacts folder. This will load the generated environment automatically and launch Visual Studio with the sdk.slnx solution.
Alternatively, to open the solution in Visual Studio, be sure to build with build.cmd and run the generated environment for your shell. If you're using cmd, then run artifacts\sdk-build-env.bat. If you're using PowerShell, you need to 'dot source' artifacts/sdk-build-env.ps1. Finally, open Visual Studio with devenv sdk.slnx.
In addition, Visual Studio must have the following option set (this option is automatically set in preview Visual Studio builds):
Go to Tools -> Options to make sure "Use previews of the .NET SDK (requires restart)" is checked and restart VS.
Note
If you're building main, we may be using a preview version of the SDK to build as specified in global.json. We only test preview SDKs with the latest Visual Studio previews so would recommend installing the latest preview build. You can see the preview versions we test with here
Run the following command from the root of the repository:
./build.sh
The build script will output a .NET Core installation to artifacts\bin\redist\Debug\dotnet that will include any local changes to the .NET Core CLI.
Run the following command from the root of the repository to run all the .NET Core CLI tests:
build.cmd -test
Run the following command from the root of the repository to run all the .NET Core CLI tests:
./build.sh --test
The dotnet executable in the artifacts directory can be run directly.
However, it's easier to configure a test environment to run the built dotnet. This test environment is managed by dogfood.
The dogfood script starts a new Powershell with the environment configured to redirect SDK resolution to your build.
From that shell your SDK will be available in:
- any Visual Studio instance launched (via
& devenv.exe) dotnet buildmsbuild
Run the following commands from the root of the repository to setup the test environment:
eng\dogfood.cmd
Ensure the dotnet being used is from the artifacts directory:
where dotnet
This should output ..\artifacts\bin\redist\Debug\dotnet\dotnet.exe.
You can now run dotnet commands to test changes.
Run the following commands from the root of the repository to setup the test environment:
source ./eng/dogfood.sh
NOTE: If you are running on MacOS you will need to use a bash shell rather than the default zsh. You can either change your default shell or type bash before executing the above command.
Ensure the dotnet being used is from the artifacts directory:
which dotnet
This should output .../artifacts/bin/redist/Debug/dotnet/dotnet.
You can now run dotnet commands to test changes.
Run "dotnet --debug " which will launch dotnet and pause waiting for user input. This will give you time to attach a debugger to the running dotnet process, set the breakpoints you want to stop at in your built copy of the sdk, and then you can hit enter for the dotnet command to continue.
build.cmd # to have a full build first
.\artifacts\sdk-build-env.bat
cd test\YOURTEST.Tests # cd to the test folder that contains the test csproj file
dotnet test --filter "FullyQualifiedName~TESTNAME" # run individual testUse developer command prompt for Visual Studio or put devenv on you PATH
build.cmd # to have a full build first
.\artifacts\sdk-build-env.bat
devenv sdk.slnxNote again that in Visual studio "Use previews of the .NET SDK (requires restart)" must be checked. See the above comment for how to enable this.
Using the dotnet built in the previous steps:
mkdir test
cd test
dotnet new console
dotnet run
This should print Hello World!.
If you see error like error MSB3021: Unable to copy file "sdk-tasks.dll" to "sdk-tasks.dll". The process cannot access the file 'sdk-tasks.dll' because it is being used by another process.
You could run the following to stop all dotnet related processes
taskkill /F /IM dotnet.exe /T ||
taskkill /F /IM VSTest.Console.exe /T ||
taskkill /F /IM msbuild.exe /TThe SDK repository includes GitHub Actions workflows that automate common maintenance tasks directly from pull requests.
When you modify .resx resource files, the corresponding .xlf translation files need to be updated. Instead of manually running the build locally, comment /updatexlf on the PR and the GitHub Action will:
- Check out the PR branch
- Run
./build.sh /t:UpdateXlf(or full build if needed) - Commit any updated
.xlffiles directly to the PR branch
This is useful when you've changed localized strings and the CI build is failing due to outdated XLF files.
See also: Localization documentation
The CLI includes snapshot-based tests for shell completions (bash, zsh, pwsh, etc.). When you add or modify CLI commands, these snapshots need to be updated. Comment /fixcompletions on the PR and the GitHub Action will:
- Build the repository
- Run the completion tests
- Update the verified snapshot files
- Commit the changes directly to the PR branch
This is useful when you've added new commands or options and the completion snapshot tests are failing.
See also: Snapshot-based testing documentation
The SDK team manages many branches. You may use /backport to {branch_name} to mimic the process of cherry-picking a PR onto another branch.
The dotnet CLI supports several models for adding new commands:
- In the CLI itself via
dotnet.dll. - Through a .NET Core Global Tool.
- Through MSBuild tasks & targets in a NuGet package.
- Through executables prefixed with
dotnet-on thePATH.
Developers are generally encouraged to avoid adding commands to dotnet.dll or the CLI installer directly. This is appropriate for very general commands such as restore, build, publish, test, and clean, but is generally too broad of a distribution mechanism for new commands.
Create an issue and engage the repository maintainers if you feel there is a missing core command that you would like to add.
A .NET Core Global Tool can be used to install a dotnet- prefixed tool to the PATH.
The CLI will then treat the remainder of the tool name as a dotnet command. For example, a tool with the name dotnet-hello could be executed by dotnet hello.
NuGet allows adding tasks and targets to a project through a NuGet package. Extending the CLI through this model has several advantages:
- Targets have access to the MSBuild Project Context, allowing them to reason about the files and properties being used to build a particular project.
- Targets are not CLI-specific, making them easy to share across command-line and IDE environments
Commands added as targets can be invoked once the target project adds a reference to the containing NuGet package and restores.
Targets are invoked by calling dotnet msbuild /t:{TargetName}
The dotnet CLI considers any executable on the path named dotnet-{commandName} to be a command it can call out to.
