-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Microsoft.NET.TargetFrameworkInference.targets
201 lines (165 loc) · 12.1 KB
/
Microsoft.NET.TargetFrameworkInference.targets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<!--
***********************************************************************************************
Microsoft.NET.TargetFrameworkInference.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
Note that this file is only included when $(TargetFramework) is set and so we do not need to check that here.
Common targets require that $(TargetFrameworkIdentifier) and $(TargetFrameworkVersion) are set by static evaluation
before they are imported. In common cases (currently netstandard, netcoreapp, or net), we infer them from the short
names given via TargetFramework to allow for terseness and lack of duplication in project files.
For other cases, the user must supply them manually.
For cases where inference is supported, the user need only specify the targets in TargetFrameworks, e.g:
<PropertyGroup>
<TargetFrameworks>net45;netstandard1.0</TargetFrameworks>
</PropertyGroup>
For cases where inference is not supported, identifier, version and profile can be specified explicitly as follows:
<PropertyGroup>
<TargetFrameworks>portable-net451+win81;xyz1.0</TargetFrameworks>
<PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'portable-net451+win81'">
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'xyz1.0'">
<TargetFrameworkIdentifier>Xyz</TargetFrameworkVersion>
<PropertyGroup>
Note in the xyz1.0 case, which is meant to demonstrate a framework we don't yet recognize, we can still
infer the version of 1.0. The user can also override it as always we honor a TargetFrameworkIdentifier
or TargetFrameworkVersion that is already set.
-->
<!-- Hook for importing custom target framework parsing -->
<Import Project="$(BeforeTargetFrameworkInferenceTargets)" Condition="$(BeforeTargetFrameworkInferenceTargets) != ''" />
<!-- Split $(TargetFramework) (e.g. net45) into short identifier and short version (e.g. 'net' and '45'). -->
<PropertyGroup Condition="'$(TargetFramework)' != '' and !$(TargetFramework.Contains(',')) and !$(TargetFramework.Contains('+'))">
<_ShortFrameworkIdentifier>$(TargetFramework.TrimEnd('.0123456789'))</_ShortFrameworkIdentifier>
<_ShortFrameworkVersion>$(TargetFramework.Substring($(_ShortFrameworkIdentifier.Length)))</_ShortFrameworkVersion>
</PropertyGroup>
<!-- Versions with dots are taken as is and just given leading 'v'. -->
<PropertyGroup Condition="'$(TargetFrameworkVersion)' == '' and '$(_ShortFrameworkVersion)' != '' and $(_ShortFrameworkVersion.Contains('.'))">
<TargetFrameworkVersion>v$(_ShortFrameworkVersion)</TargetFrameworkVersion>
</PropertyGroup>
<!-- Versions with no dots and up to 3 characters get leading 'v' and implicit dots between characters. -->
<PropertyGroup Condition="'$(TargetFrameworkVersion)' == '' and '$(_ShortFrameworkVersion)' != ''">
<TargetFrameworkVersion Condition="$(_ShortFrameworkVersion.Length) == 1">v$(_ShortFrameworkVersion[0]).0</TargetFrameworkVersion>
<TargetFrameworkVersion Condition="$(_ShortFrameworkVersion.Length) == 2">v$(_ShortFrameworkVersion[0]).$(_ShortFrameworkVersion[1])</TargetFrameworkVersion>
<TargetFrameworkVersion Condition="$(_ShortFrameworkVersion.Length) == 3">v$(_ShortFrameworkVersion[0]).$(_ShortFrameworkVersion[1]).$(_ShortFrameworkVersion[2])</TargetFrameworkVersion>
</PropertyGroup>
<!-- Map short name to long name. See earlier comment for example of how to work with identifiers that are not recognized here. -->
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == ''">
<TargetFrameworkIdentifier Condition="'$(_ShortFrameworkIdentifier)' == 'netstandard'">.NETStandard</TargetFrameworkIdentifier>
<TargetFrameworkIdentifier Condition="'$(_ShortFrameworkIdentifier)' == 'netcoreapp'">.NETCoreApp</TargetFrameworkIdentifier>
<!-- The meaning of "net" as a short framework name depends on the version. If it's 4.x or less, it means .NETFramework.
If the version is 5.0 or higher, then "net" means .NET 5.0 and on, which is the evolution of .NET Core, and uses
the .NETCoreApp TargetFrameworkIdentifier. -->
<TargetFrameworkIdentifier Condition="'$(_ShortFrameworkIdentifier)' == 'net' And
$([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '5.0'))">.NETFramework</TargetFrameworkIdentifier>
<TargetFrameworkIdentifier Condition="'$(_ShortFrameworkIdentifier)' == 'net' And
$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '5.0'))">.NETCoreApp</TargetFrameworkIdentifier>
</PropertyGroup>
<!--
Trigger an error if we're unable to infer the framework identifier and version.
We have to evaluate this here and not in the target because by the time the target runs,
Microsoft.Common.targets will have defaulted to .NETFramework,Version=v4.0
-->
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == '' or '$(TargetFrameworkVersion)' == ''">
<_UnsupportedTargetFrameworkError>true</_UnsupportedTargetFrameworkError>
</PropertyGroup>
<!--
NOTE: We must not validate the TFM before restore target runs as it prevents adding additional TFM
support from being provided by a nuget package such as MSBuild.Sdk.Extras.
We run before RunResolvePackageDependencies and GetReferenceAssemblyPaths so that design-time builds
which do not currently invoke _CheckForInvalidConfigurationAndPlatform, will not trigger spurious
errors that are only consequences of the root cause identified here.
-->
<Target Name="_CheckForUnsupportedTargetFramework"
BeforeTargets="_CheckForInvalidConfigurationAndPlatform;RunResolvePackageDependencies;GetFrameworkPaths;GetReferenceAssemblyPaths"
Condition="'$(_UnsupportedTargetFrameworkError)' == 'true'"
>
<NETSdkError Condition="!$(TargetFramework.Contains(';'))"
ResourceName="CannotInferTargetFrameworkIdentifierAndVersion"
FormatArguments="$([MSBuild]::Escape('$(TargetFramework)'))" />
<NETSdkError Condition="$(TargetFramework.Contains(';'))"
ResourceName="TargetFrameworkWithSemicolon"
FormatArguments="$([MSBuild]::Escape('$(TargetFramework)'))" />
</Target>
<UsingTask TaskName="AllowEmptyTelemetry" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
<Target Name="_CollectTargetFrameworkForTelemetry" AfterTargets="_CheckForUnsupportedTargetFramework">
<AllowEmptyTelemetry EventName="targetframeworkeval" EventData="TargetFrameworkVersion=$([MSBuild]::Escape('$(TargetFrameworkMoniker)'));RuntimeIdentifier=$(RuntimeIdentifier);SelfContained=$(SelfContained);UseApphost=$(UseApphost);OutputType=$(OutputType)" />
</Target>
<!--
Don't leave TargetFrameworkVersion empty if it still hasn't been determined. We will trigger the error above,
but we need this to be a valid version so that our error message does not get pre-empted by failure to interpret
version comparison expressions, which is currently unrecoverable in VS.
Also don't leave TargetFrameworkIdentifier unset as it will be defaulted to .NETFramework by common targets, which
can cause restore (which we cannot block, see above) to silently succeed for empty TargetFramework.
-->
<PropertyGroup Condition="'$(TargetFrameworkVersion)' == ''">
<TargetFrameworkVersion >v0.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == ''">
<TargetFrameworkIdentifier>_</TargetFrameworkIdentifier>
</PropertyGroup>
<!--
Trigger an error if targeting a higher version of .NET Core or .NET Standard than is supported by the current SDK.
-->
<Target Name="_CheckForUnsupportedNETCoreVersion" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;Restore;CollectPackageReferences"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(NETCoreAppMaximumVersion)' != ''">
<NETSdkError Condition="'$(_TargetFrameworkVersionWithoutV)' > '$(NETCoreAppMaximumVersion)'"
ResourceName="UnsupportedTargetFrameworkVersion"
FormatArguments=".NET Core;$(_TargetFrameworkVersionWithoutV);$(NETCoreAppMaximumVersion)"
/>
</Target>
<!--
Trigger an error if C++ project targeting a lower version of .NET Core than 3.1.
-->
<Target Name="_CheckForUnsupportedCppNETCoreVersion" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;Restore;CollectPackageReferences">
<NETSdkError Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(_TargetFrameworkVersionWithoutV)' < '3.1' and '$(Language)' == 'C++'"
ResourceName="CppRequiresTFMVersion31"
/>
</Target>
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' And '$(NETStandardMaximumVersion)' == ''">
<NETStandardMaximumVersion>2.1</NETStandardMaximumVersion>
</PropertyGroup>
<Target Name="_CheckForUnsupportedNETStandardVersion" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;Restore;CollectPackageReferences"
Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' And '$(NETStandardMaximumVersion)' != ''">
<NETSdkError Condition="'$(_TargetFrameworkVersionWithoutV)' > '$(NETStandardMaximumVersion)'"
ResourceName="UnsupportedTargetFrameworkVersion"
FormatArguments=".NET Standard;$(_TargetFrameworkVersionWithoutV);$(NETStandardMaximumVersion)"
/>
</Target>
<Target Name="_CheckForUnsupportedTargetFrameworkAndFeatureCombination" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;Restore;CollectPackageReferences"
Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<NETSdkError Condition="'$(UsingNETSdkDefaults)' != 'true'"
ResourceName="NETFrameworkWithoutUsingNETSdkDefaults" />
</Target>
<!-- Exclude files from OutputPath and IntermediateOutputPath from default item globs. Use the value
of these properties before the TargetFramework is appended, so that if these values are specified
in the project file, the specified value will be used for the exclude.
We may be able to move this to Microsoft.NET.Sdk.DefaultItems.targets (where the other DefaultItemExcludes
are defined) if we fix https://github.com/dotnet/sdk/issues/550
-->
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);$(OutputPath)/**</DefaultItemExcludes>
<DefaultItemExcludes>$(DefaultItemExcludes);$(IntermediateOutputPath)/**</DefaultItemExcludes>
</PropertyGroup>
<!-- Projects which don't use Microsoft.NET.Sdk will typically define the OutputPath directly (usually in a
Configuration-specific PropertyGroup), so in that case we won't append to it by default. -->
<PropertyGroup Condition="'$(UsingNETSdkDefaults)' == 'true'">
<AppendTargetFrameworkToOutputPath Condition="'$(AppendTargetFrameworkToOutputPath)' == ''">true</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<!--
Append $(TargetFramework) directory to output and intermediate paths to prevent bin clashes between
targets.
-->
<PropertyGroup Condition="'$(AppendTargetFrameworkToOutputPath)' == 'true' and '$(TargetFramework)' != '' and '$(_UnsupportedTargetFrameworkError)' != 'true'">
<IntermediateOutputPath>$(IntermediateOutputPath)$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>
<OutputPath>$(OutputPath)$(TargetFramework.ToLowerInvariant())\</OutputPath>
</PropertyGroup>
</Project>