Skip to content

Can't remove entries from SdkSupportedTargetPlatformVersion without removing _OR_GREATER defines #38016

@rolfbjarne

Description

@rolfbjarne

The SdkSupportedTargetPlatformVersion item group is used for (at least) two things:

  1. Generate the _OR_GREATER preprocessing symbols:

<!-- Add OR_GREATER compilation symbols for target platforms. -->
<Target Name="GeneratePlatformCompatibleDefineConstants"
Condition=" '$(DisableImplicitFrameworkDefines)' != 'true' and '$(TargetPlatformIdentifier)' != '' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 5.0)) " >
<ItemGroup>
<_SupportedPlatformCompatibleVersions Include="@(SdkSupportedTargetPlatformVersion)" Condition=" %(Identity) != '' and $([MSBuild]::VersionLessThanOrEquals(%(Identity), $(TargetPlatformVersion))) " />
<_ImplicitDefineConstant Include="@(_SupportedPlatformCompatibleVersions->Distinct()->'$(TargetPlatformIdentifier.ToUpper())%(Identity)_OR_GREATER'->Replace('.', '_'))" />
</ItemGroup>
</Target>

  1. Validate the TargetPlatformVersion:

<Target Name="_CheckForInvalidTargetPlatformVersion"
BeforeTargets="_CheckForInvalidConfigurationAndPlatform"
DependsOnTargets="_NormalizeTargetPlatformVersion"
Condition="'$(TargetPlatformVersion)' != '' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 5.0)) and ('$(Language)' != 'C++' or '$(_EnablePackageReferencesInVCProjects)' == 'true')">
<PropertyGroup>
<TargetPlatformVersionSupported Condition="'$(TargetPlatformVersionSupported)' == '' and '@(_ValidTargetPlatformVersion)' != ''" >true</TargetPlatformVersionSupported>
<_ValidTargetPlatformVersions Condition="'@(SdkSupportedTargetPlatformVersion)' != ''" >@(SdkSupportedTargetPlatformVersion, '%0a')</_ValidTargetPlatformVersions>
<_ValidTargetPlatformVersions Condition="'@(SdkSupportedTargetPlatformVersion)' == ''" >None</_ValidTargetPlatformVersions>
</PropertyGroup>
<NetSdkError Condition="'$(TargetPlatformVersionSupported)' != 'true'"
ResourceName="InvalidTargetPlatformVersion"
FormatArguments="$(TargetPlatformVersion);$(TargetPlatformIdentifier);$(_ValidTargetPlatformVersions)" />
</Target>

The problem is that these two uses aren't equivalent.

Take for example the following scenario:

We release bindings for iOS 10, and a library developer takes advantage of the
bindings for the new iOS version, while at the same time supporting
multi-targeting to older platforms:

#if IOS10_0_OR_GREATER
    UseNewApi ();
#else
    UseOldApi ();
#endif

Time passes, iOS 11 comes out, and we stop shipping bindings specifically for
iOS 10 (the APIs themselves would be included in the bindings for iOS 11). The
code above should continue to work, but iOS 10 is not a valid
TargetPlatformVersion anymore. However, with the current situation there's no
way to express this, because the moment we remove the "10.0" version from
SdkSupportedTargetPlatformVersion, the IOS10_0_OR_GREATER define isn't
generated anymore.

We discussed this in a meeting internally, and the suggestion that came up
was to use metadata to handle this situation.

Ref: dotnet/android#8569 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions