|
| 1 | +--- |
| 2 | +title: .NET SDK Multitargeting Overview |
| 3 | +description: Use MSBuild to compile an application to run on any one of several versions of .NET. |
| 4 | +ms.date: 1/9/2025 |
| 5 | +ms.topic: how-to |
| 6 | +author: ghogen |
| 7 | +ms.author: ghogen |
| 8 | +manager: mijacobs |
| 9 | +ms.subservice: msbuild |
| 10 | +--- |
| 11 | +# Targeting multiple .NET versions in a build |
| 12 | + |
| 13 | +Targeting multiple .NET frameworks in a build allows you to ensure that your application or library is available for different versions or editions of .NET. |
| 14 | + |
| 15 | +Multitargeting for .NET Core and .NET 5 and later projects is significantly different from and more advanced than multitargeting for .NET Framework projects. See [Comparison between .NET Framework and .NET Core multitargeting](#comparison-between-net-framework-and-net-core-multitargeting). |
| 16 | + |
| 17 | +## Set up .NET multitargeting |
| 18 | + |
| 19 | +1. Create a new .NET Standard class library either in Visual Studio or using the `dotnet new classlib` command. |
| 20 | + |
| 21 | +2. Edit the project file. Edit the `.csproj` file to support multiple target frameworks. Change the `<TargetFramework>` element to `<TargetFrameworks>` and list the frameworks you want to target. |
| 22 | + |
| 23 | + ```xml |
| 24 | + <Project Sdk="Microsoft.NET.Sdk"> |
| 25 | + <PropertyGroup> |
| 26 | + <TargetFrameworks>netstandard2.0;net45;netcoreapp3.1;net5.0</TargetFrameworks> |
| 27 | + </PropertyGroup> |
| 28 | + </Project> |
| 29 | + ``` |
| 30 | + |
| 31 | +3. Use conditional compilation symbols to separate code that is specific to a particular version. |
| 32 | + |
| 33 | + ```csharp |
| 34 | + public string GetFramework() |
| 35 | + { |
| 36 | + #if NET45 |
| 37 | + return ".NET Framework 4.5"; |
| 38 | + #elif NETSTANDARD2_0 |
| 39 | + return ".NET Standard 2.0"; |
| 40 | + #elif NETCOREAPP3_1 |
| 41 | + return ".NET Core 3.1"; |
| 42 | + #elif NET5_0 |
| 43 | + return ".NET 5.0"; |
| 44 | + #else |
| 45 | + return "Unknown Framework"; |
| 46 | + #endif |
| 47 | + } |
| 48 | + ``` |
| 49 | + |
| 50 | +4. Build and pack. Use the `dotnet pack` or `MSBuild.exe /t:pack` command to create the package. This will generate a `.nupkg` file that targets all specified frameworks. |
| 51 | + |
| 52 | + ```sh |
| 53 | + MSBuild.exe /t:pack MyProject.csproj |
| 54 | + ``` |
| 55 | + |
| 56 | +## Handle dependencies |
| 57 | + |
| 58 | +When targeting multiple framework versions, you might need to handle dependencies differently for each version. Use conditional `ItemGroup` elements in your project file to specify framework-specific dependencies. |
| 59 | + |
| 60 | +```xml |
| 61 | +<ItemGroup Condition="'$(TargetFramework)' == 'net45'"> |
| 62 | +<PackageReference Include="SomePackage" Version="1.0.0" /> |
| 63 | +</ItemGroup> |
| 64 | +<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> |
| 65 | +<PackageReference Include="SomeOtherPackage" Version="2.0.0" /> |
| 66 | +</ItemGroup> |
| 67 | +``` |
| 68 | + |
| 69 | +Handling version-specific dependencies in a .NET project involves using conditional `PackageReference` elements in your project file. This allows you to specify different versions of a package for different target frameworks. Here's how you can do it: |
| 70 | + |
| 71 | +### Add version-specific dependencies |
| 72 | + |
| 73 | +1. **Edit the Project File**: Open your `.csproj` file and add conditional `PackageReference` elements inside an `ItemGroup` element. This way, you can specify different versions of a package based on the target framework. |
| 74 | + |
| 75 | + ```xml |
| 76 | + <Project Sdk="Microsoft.NET.Sdk"> |
| 77 | + <PropertyGroup> |
| 78 | + <TargetFrameworks>net45;netstandard2.0;netcoreapp3.1;net5.0</TargetFrameworks> |
| 79 | + </PropertyGroup> |
| 80 | + <ItemGroup Condition="'$(TargetFramework)' == 'net45'"> |
| 81 | + <PackageReference Include="SomePackage" Version="1.0.0" /> |
| 82 | + </ItemGroup> |
| 83 | + <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> |
| 84 | + <PackageReference Include="SomePackage" Version="2.0.0" /> |
| 85 | + </ItemGroup> |
| 86 | + <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'"> |
| 87 | + <PackageReference Include="SomePackage" Version="3.0.0" /> |
| 88 | + </ItemGroup> |
| 89 | + <ItemGroup Condition="'$(TargetFramework)' == 'net5.0'"> |
| 90 | + <PackageReference Include="SomePackage" Version="4.0.0" /> |
| 91 | + </ItemGroup> |
| 92 | + </Project> |
| 93 | + ``` |
| 94 | + |
| 95 | +2. **Use the CLI**: You can also add dependencies using the .NET CLI. For example, to add a dependency for a specific target framework, you can use the following command: |
| 96 | + |
| 97 | + ```sh |
| 98 | + dotnet add package SomePackage --version 1.0.0 --framework net45 |
| 99 | + ``` |
| 100 | + |
| 101 | +### Manage transitive dependencies |
| 102 | + |
| 103 | +Transitive dependencies are dependencies of your dependencies. It's important to review and manage these to avoid conflicts and ensure compatibility. You can use the `dotnet list package` command to see all the dependencies and their versions. |
| 104 | + |
| 105 | +```sh |
| 106 | +dotnet list package |
| 107 | +``` |
| 108 | + |
| 109 | +### Handle diamond dependencies |
| 110 | + |
| 111 | +Diamond dependencies occur when multiple versions of a package are present in the dependency tree. NuGet resolves these by selecting the lowest applicable version. To avoid issues, you can specify version ranges or use binding redirects in .NET Framework projects. |
| 112 | + |
| 113 | +```xml |
| 114 | +<PackageReference Include="ExamplePackage" Version="[1.0,2.0)" /> |
| 115 | +``` |
| 116 | + |
| 117 | +By following these practices, you can effectively manage version-specific dependencies in your .NET projects, ensuring compatibility and stability across different target frameworks. See [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies), [Dependencies](/dotnet/standard/library-guidance/dependencies), and [How NuGet resolves package dependencies](/nuget/concepts/dependency-resolution). |
| 118 | + |
| 119 | +## Comparison Between .NET Framework and .NET Core Multitargeting |
| 120 | + |
| 121 | +Multitargeting for .NET Core (and .NET 5 and later) is very different and more powerful than [multitargeting for .NET Framework projects](msbuild-multitargeting-overview.md). |
| 122 | + |
| 123 | +### .NET Framework |
| 124 | +- **Limited Multitargeting**: .NET Framework supports multitargeting, but it is more limited compared to .NET Core. It can target different versions of the .NET Framework, but not multiple frameworks simultaneously. See [MSBuild multitargeting](msbuild-multitargeting-overview.md). |
| 125 | +- **Older Toolset**: Uses an older type of multitargeting with MSBuild, where a project can target only one framework and one platform at a time. |
| 126 | + |
| 127 | +### .NET Core |
| 128 | +- **Advanced Multitargeting**: .NET Core supports advanced multitargeting, allowing you to target multiple frameworks simultaneously using the `<TargetFrameworks>` property in the project file. See [Target frameworks](/dotnet/targetframeworks). |
| 129 | +- **Modern Toolset**: Uses a newer type of multitargeting with MSBuild, where multiple builds occur for each target framework listed. |
| 130 | + |
| 131 | +## Related content |
| 132 | + |
| 133 | +- [Specify the targeted .NET Frameworks - Visual Studio](../ide/visual-studio-multi-targeting-overview.md) |
| 134 | + |
| 135 | +[!INCLUDE[AI generated](../includes/ai-generated-attribution.md)] |
0 commit comments