You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Don't use Targets* helper properties in libs (#64500)
* Don't use Targets* helper properties in libs projs
This change makes it possible to migrate 200+ (ref+src) projects to use
TargetFramework instead of TargetFrameworks which avoids the additional
outer build evaluation and invocation which ultimately makes the overall
build faster.
Targets* properties (i.e. TargetsWindows, TargetsAnyOS, TargetsUnix,
etc.) rely on the TargetFramework property which usually are set
inside a project. The TargetFramework property is only
available before a project specifies it if it's explicitly set in a props
file or if the project is cross-targeting and the outer-build dispatches
into the inner-build. During the dispatch, the TargetFramework property
is passed in as a global property.
Until now that behavior wasn't a problem because every libraries project
cross-targeted (by setting the TargetFrameworks property) even though
many only include a single TargetFramework (i.e. NetCoreAppCurrent).
To allow projects to use the TargetFramework property instead of
TargetFrameworks, the Targets* helper properties can't be calculated
anymore early in a props file as the TargetFramework property isn't set
at that time.
In general, the guidance by the SDK/msbuild team is to not read from the
TargetFramework property before the project sets it
(in a property group). That effectively means that the TargetFramework
property shouldn't be used in props files at all.
Therefore these helper properties can't be used anymore for property
conditions and I'm replacing their usage with TargetPlatformIdentifier
comparisons for both properties and items.
In nearly all cases, the Targets* helper properties can be replaced with
TargetPlatformIdentifier checks on items and in the few cases where
TargetsUnix or TargetsLinux marks multiple tfms as compatible, the exact
tfms must be used instead for the TargetPlatformIdentifier comparison.
Whenever a project needs to condition properties on the platform, I'm
first setting the TargetPlatformIdentifier the same way the SDK sets it
so that the SDK later doesn't need to set it again to avoid the
additional expensive msbuild function call.
* Use TargetFramework singular to avoid outer builds
Use TargetFramework instead of TargetFrameworks property whenever a
projects only targets a single target framework. This avoid unnecessary
outer builds and evaluations and makes the build faster.
- Note this property should be file path safe and thus can be used in file names or directories that need to a unique path for a project configuration.
42
-
- The only required Build Settings value is the `$(BuildTargetFramework)` the others are optional.
43
-
44
40
Example:
45
-
Pure netstandard configuration:
41
+
Non cross-targeting project that targets .NETStandard:
@@ -61,15 +57,15 @@ All supported targets with unique windows/unix build for netcoreapp:
61
57
A full or individual project build is centered around BuildTargetFramework, TargetOS, Configuration and TargetArchitecture.
62
58
63
59
1.`$(BuildTargetFramework), $(TargetOS), $(Configuration), $(TargetArchitecture)` can individually be passed in to change the default values.
64
-
2. If nothing is passed to the build then we will default value of these properties from the environment. Example: `net5.0-[TargetOS Running On]-Debug-x64`.
65
-
3.While Building an individual project from the VS, we build the project for all latest netcoreapp target frameworks.
60
+
2. If nothing is passed to the build then we will default value of these properties from the environment. Example: `net7.0-[TargetOS Running On]-Debug-x64`.
61
+
3.When building an individual project (either from the CLI or an IDE), all target frameworks are built.
66
62
67
63
We also have `RuntimeOS` which can be passed to customize the specific OS and version needed for native package builds as well as package restoration. If not passed it will default based on the OS you are running on.
68
64
69
-
Any of the mentioned properties can be set via `/p:<Property>=<Value>` at the command line. When building using our run tool or any of the wrapper scripts around it (i.e. build.cmd) a number of these properties have aliases which make them easier to pass (run build.cmd/sh -? for the aliases).
65
+
Any of the mentioned properties can be set via `/p:<Property>=<Value>` at the command line. When building using any of the wrapper scripts around it (i.e. build.cmd) a number of these properties have aliases which make them easier to pass (run build.cmd/sh -? for the aliases).
70
66
71
67
## Selecting the correct BuildSettings
72
-
When building an individual project the `BuildTargetFramework` and `TargetOS` will be used to select the closest matching TargetFramework listed in the projects `TargetFrameworks` property. The rules used to select the targetFramework will consider compatible target frameworks and OS fallbacks.
68
+
When building an individual project the `BuildTargetFramework` and `TargetOS` will be used to select the compatible dependencies which are expressed as ProjectReference items.
73
69
74
70
## Supported full build settings
75
71
- .NET Core latest on current OS (default) -> `$(NetCoreAppCurrent)-[RunningOS]`
@@ -80,37 +76,64 @@ When building an individual project the `BuildTargetFramework` and `TargetOS` wi
80
76
## TargetFramework conditions
81
77
`TargetFramework` conditions should be avoided in the first PropertyGroup as that causes DesignTimeBuild issues: https://github.com/dotnet/project-system/issues/6143
82
78
83
-
1. Use an equality check if the TargetFramework isn't overloaded with the OS portion.
79
+
1. Use TargetFrameworkIdentifier to condition on an entire framework to differentiate between .NETCoreApp, .NETStandard and .NETFramework.
2. Use a StartsWith when you want to test for multiple .NETStandard or .NETFramework versions.
99
+
3. Use the `TargetPlatformIdentifier` property to condition on a .NETCoreApp platform specific target framework. Note that .NETStandard and .NETFramework target frameworks can't be platform specific.
Important: In contrast to the old `Targets*` checks, `TargetPlatformIdentifier` conditions apply to a single tfm only, inheritance between target frameworks can't be expressed. See the example below for Unix:
3. Use a StartsWith if the TargetFramework is overloaded with the OS portion.
117
+
4. Set the `TargetPlatformIdentifier` property in the project to be able to condition on it in properties in the project file.
118
+
That is necessary as the SDK sets the `TargetPlatformIdentifier` in a .targets file after the project is evaluated. Because of that, the property isn't available during the project's evaluation and must be set manually.
0 commit comments