Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Xamarin.Android.Build.Tasks] introduce XA1038 #8569

Closed
wants to merge 1 commit into from

Conversation

jonathanpeppers
Copy link
Member

Fixes: #8331

Building a net8.0-android33 project, currently fails with:

error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.33' was not present in workload manifests.
C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

To solve this, you would either change 33 to 34, or just remove the number to rely on the default value.

To make this easier:

  • Automatically switch to 34 if the user specifies 33 or less.

  • Emit the new XA1038 warning message.

This allows these projects to build with a reasonable warning message.

The only concern down the road: if we ever support net8.0-android35 alongside net8.0-android34, then we'd need to slightly adjust the logic here.

@jpobst
Copy link
Contributor

jpobst commented Dec 6, 2023

My opinion is this should be an error rather than a warning + autofix. 🤷‍♂️

@jonpryor
Copy link
Member

@jpobst: @jonathanpeppers thinking was that trying to target net8.0-android33 would be analagous to building a classic Xamarin.Android app with <uses-sdk android:targetSdkVersion="32" /> when $(TargetFrameworkVersion)=v13.0 (API-33), in which we issue an XA1006 warning, then basically "ignore" it: the resulting AndroidManifest.xml uses the specified <uses-sdk/> value (API-32), while Java Callable Wrapper compilation uses API-33's android.jar.

Maybe these aren't analagous situations, but we thought they rhymed?

@jonpryor
Copy link
Member

It occurs to me that Android and iOS should probably be consistent here, unless there's a good reason not to be, so I'm asking @dalexsoto: https://discord.com/channels/732297728826277939/732297808148824115/1184613129544531988

@jpobst
Copy link
Contributor

jpobst commented Dec 13, 2023

One thing we need to consider is how this will affect NuGet package resolving logic, as TargetFramework plays an important role there.

If I set my application to net8.0-android33.0, what happens when I try to reference a net8.0-android (net8.0-android34.0) NuGet binding library?

Am I locked out of the .NET 8 Android NuGet ecosystem? Or will that be fixed up as well?

I guess a worse scenario would be net8.0-android28.0. Am I locked out of all NuGet Android packages?

Somewhat related: NuGet/NuGetGallery#9741 (comment)

@jonpryor
Copy link
Member

@jpobst: in the "warning" case as outlined in this PR, net8.0-android33.0 would issue an XA1038 warning and then be treated as net8.0-android34.0. There would be no ecosystem lockeout.

@jonpryor
Copy link
Member

In the consistency question, @rolfbjarne has replied, and agrees with @jpobst that this scenario should be an error, not a warning.

There was another good comment by "gkarabin" as well, seconding the "error" argument:

Interjecting a comment from the peanut gallery - a downside to warning+fix is that when the warning is not comprehended by the user, the app’s behavior ends up being different in some way that you can’t infer from reading the .csproj file - you have to build it. Forcing the error means you have to make the .csproj file line up to reality.

@jonpryor
Copy link
Member

@jonathanpeppers: this solves "too low" but doesn't address "too high". If I take a dotnet new android project and set $(TargetFramework)=net8.0-android35, I get:

error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.35' was not present in workload manifests.

On a "similar yet different 'too high'" take, what about $(TargetFramework)=net9.0-android with .NET 8? That results in the even more bizarre:

error NETSDK1139: The target platform identifier android was not recognized.

?!

Okay, and $(TargetFramework)=net9.0 with .NET 8?

error NETSDK1045: The current .NET SDK does not support targeting .NET 9.0.  Either target .NET 8.0 or lower, or use a version of the .NET SDK that supports .NET 9.0. Download the .NET SDK from https://aka.ms/dotnet/download

which is at least reasonable.


I suspect there's no helping the error message produced for net9.0-android on our end -- though a PR to dotnet/whatever could be nice? ;-) -- but the net8.0-android35.0 scenario should be under our control, and should be improved.

</PropertyGroup>
<PropertyGroup>
<_AndroidTargetingPackId Condition="$(TargetPlatformVersion.EndsWith('.0'))">$(TargetPlatformVersion.Substring(0, $(TargetPlatformVersion.LastIndexOf('.0'))))</_AndroidTargetingPackId>
<_AndroidTargetingPackId Condition="'$(_AndroidTargetingPackId)' == ''">$(TargetPlatformVersion)</_AndroidTargetingPackId>
<_AndroidRuntimePackId Condition=" '$(_AndroidTargetingPackId)' &lt; '@ANDROID_LATEST_STABLE_API_LEVEL@' ">@ANDROID_LATEST_STABLE_API_LEVEL@</_AndroidRuntimePackId>
<!-- NOTE: adjust if a TargetFramework supports multiple API levels -->
<_AndroidWarnOnTargetPlatformVersion Condition=" '$(_AndroidTargetingPackId)' &lt; '$(_AndroidLatestStableApiLevel)' ">$(_AndroidTargetingPackId)</_AndroidWarnOnTargetPlatformVersion>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also "do something" when '$(_AndroidTargetingPackId)' &gt; '$(_AndroidLatestStableApiLevel)'.

This should also take $(EnablePreviewFeatures) into consideration, so that when net8.0-android35.0 previews are available, $(TargetFramework)=net8.0-android35 continues to emit an XA1038 error, while TargetFramework=net8.0-android35;EnablePreviewFeatures=true succeeds.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

35.0 gets a different error:

(_CheckForInvalidTargetPlatformVersion target) -> 
dotnet/sdk/9.0.100-alpha.1.23628.5/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.TargetFrameworkInference.targets(243,5):
error NETSDK1140: 35.0 is not a valid TargetPlatformVersion for Android.
Valid versions include:
21.0
22.0
23.0
24.0
25.0
26.0
27.0
28.0
29.0
30.0
31.0
32.0
33.0
34.0

@jonpryor
Copy link
Member

WIP commit message:

Fixes: https://github.com/xamarin/xamarin-android/issues/8331

Building a `net8.0-android33` project currently fails with:

	error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.33' was not present in workload manifests.
	C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

To solve this, you would either use `net8.0-android34`, changing
33 to 34, or just use `net8.0-android` by removing the number, which
uses the default value.

Improve this situation by emitting an XA1038 error message instead of
the NETSDK1181 error message:

	error XA1038: $(TargetPlatformVersion) 33 is not a valid target for 'net8.0-android' projects. Please update your $(TargetPlatformVersion) to a supported version (e.g. 34).

<AndroidError Code="XA1038"
ResourceName="XA1038"
Condition=" '$(_AndroidWarnOnTargetPlatformVersion)' != '' "
FormatArguments="$(_AndroidWarnOnTargetPlatformVersion);$(TargetFramework);$(_AndroidLatestStableApiLevel)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand dotnet build handling of $(TargetFramework):

Assume a project with $(TargetFramework)=net8.0-android33.0.

By the time we encounter this line, is $(TargetFramework) changed to net8.0-android, moving the 33.0 into $(TargetFrameworkVersion)? Or does it remain net8.0-android33.0?

I'm curious because of the error message text: if it isn't changed to remove the 33.0, we'd have an error message such as:

$(TargetPlatformVersion) 33.0 is not a valid target for 'net8.0-android33.0 projects. Please update your $(TargetPlatformVersion) to a supported version (e.g. 34).

Copy link
Member Author

@jonathanpeppers jonathanpeppers Jan 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly, but I think the best option is to use net$(TargetFrameworkVersion.TrimStart('vV')), so it will be:

$(TargetPlatformVersion) 33.0 is not a valid target for 'net8.0' projects. Please update your $(TargetPlatformVersion) to a supported version (e.g. 34).

https://github.com/dotnet/sdk/blob/941d6c72eb97fce7ae4d2703b30aaa5e473b6976/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.TargetFrameworkInference.targets#L59

Fixes: dotnet#8331

Building a `net8.0-android33` project, currently fails with:

    error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.33' was not present in workload manifests.
    C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

To solve this, you would either change 33 to 34, or just remove the
number to rely on the default value.

To make this easier:

* Automatically switch to 34 if the user specifies 33 or less.

* Emit the new `XA1038` error message.

This allows these projects to build with a reasonable error message.

The only concern down the road: if we ever support `net8.0-android35`
alongside `net8.0-android34`, then we'd need to slightly adjust the
logic here.
@rolfbjarne
Copy link
Member

rolfbjarne commented Jan 10, 2024

I think there's a simpler way: change the SupportedTargetPlatformVersion item group to only include the target platform versions you support. Then .NET will automatically validate the TPV, there's no need to do anything else.

FWIW this is .NET's error:

error NETSDK1140: 35.0 is not a valid TargetPlatformVersion for Android. Valid versions include: ...

rolfbjarne added a commit to rolfbjarne/xamarin-macios that referenced this pull request Jan 10, 2024
We've used to ignore the target platform version (the "17.0" part in "net8.0-ios17.0")
since our initial .NET relaese - customers could specify any valid OS version between
the minimum and maximum versions, and we'd completely ignore the value [1].

The purpose of the target platform version is to specify which bindings to choose:
"net8.0-ios17.0" would mean that the developer wants packages that have bindings
for iOS 17.0 (and earlier iOS versions, but not later iOS versions).

So saying "net8.0-ios11.0" would technically mean that the developer would want our
bindings for iOS 11.0 (and earlier iOS versions, but not later iOS versions). The
problem is that we don't ship any such thing... we shipped iOS 17.0 bindings in .NET
8, and that's it, you can't choose to build with something that does *not* have bindings
for iOS 17.0.

This will change with multi-targeting: we'll support *some* matrix of bindings. For
instance, we might want to support the OS version we shipped initial support in any
given .NET release + the latest OS version.

For example, we might want to support both of these:

* net8.0-ios17.0
* net8.0-ios17.2

This means that the target platform version (17.0/17.2) can't keep staying ignored.

The proper way to do this is to change the `SdkSupportedTargetPlatformVersion` item
group to only include target platform version we actually support, but the downside
of this approach is that it will make existing projects fail to compile, if they
happened to include an invalid target platform version.

So I've added a compatibility mode for .NET 8, where we show a warning (and tell
the developer what to do) instead of an error, and then in .NET 9 we'll make the
warning an error instead. This is accomplished by still lying in the `SdkSupportedTargetPlatformVersion`
item group in .NET 8, and detect the condition in our own logic and report the error.
For .NET 9 we can remove this logic, makes ure `SdkSupportedTargetPlatformVersion`
is correct, and then .NET itself will show the proper error.

Side note: Android is also making an invalid target platform version an error in
.NET 9: dotnet/android#8569.

[1]: We'd ignore the value for executable projects. It did have an effect for library
projects that were packed into NuGets: the target platform version would be stored
in the NuGet.
rolfbjarne added a commit to rolfbjarne/xamarin-macios that referenced this pull request Jan 10, 2024
We've used to ignore the target platform version (the "17.0" part in "net8.0-ios17.0")
since our initial .NET relaese - customers could specify any valid OS version between
the minimum and maximum versions, and we'd completely ignore the value [1].

The purpose of the target platform version is to specify which bindings to choose:
"net8.0-ios17.0" would mean that the developer wants packages that have bindings
for iOS 17.0 (and earlier iOS versions, but not later iOS versions).

So saying "net8.0-ios11.0" would technically mean that the developer would want our
bindings for iOS 11.0 (and earlier iOS versions, but not later iOS versions). The
problem is that we don't ship any such thing... we shipped iOS 17.0 bindings in .NET
8, and that's it, you can't choose to build with something that does *not* have bindings
for iOS 17.0.

This will change with multi-targeting: we'll support *some* matrix of bindings. For
instance, we might want to support the OS version we shipped initial support in any
given .NET release + the latest OS version.

For example, we might want to support both of these:

* net8.0-ios17.0
* net8.0-ios17.2

This means that the target platform version (17.0/17.2) can't keep staying ignored.

The proper way to do this is to change the `SdkSupportedTargetPlatformVersion` item
group to only include target platform version we actually support, but the downside
of this approach is that it will make existing projects fail to compile, if they
happened to include an invalid target platform version.

So I've added a compatibility mode for .NET 8, where we show a warning (and tell
the developer what to do) instead of an error, and then in .NET 9 we'll make the
warning an error instead. This is accomplished by still lying in the `SdkSupportedTargetPlatformVersion`
item group in .NET 8, and detect the condition in our own logic and report the error.
For .NET 9 we can remove this logic, makes ure `SdkSupportedTargetPlatformVersion`
is correct, and then .NET itself will show the proper error.

Side note: Android is also making an invalid target platform version an error in
.NET 9: dotnet/android#8569.

[1]: We'd ignore the value for executable projects. It did have an effect for library
projects that were packed into NuGets: the target platform version would be stored
in the NuGet.
rolfbjarne added a commit to rolfbjarne/xamarin-macios that referenced this pull request Jan 10, 2024
We've used to ignore the target platform version (the "17.0" part in "net8.0-ios17.0")
since our initial .NET relaese - customers could specify any valid OS version between
the minimum and maximum versions, and we'd completely ignore the value [1].

The purpose of the target platform version is to specify which bindings to choose:
"net8.0-ios17.0" would mean that the developer wants packages that have bindings
for iOS 17.0 (and earlier iOS versions, but not later iOS versions).

So saying "net8.0-ios11.0" would technically mean that the developer would want our
bindings for iOS 11.0 (and earlier iOS versions, but not later iOS versions). The
problem is that we don't ship any such thing... we shipped iOS 17.0 bindings in .NET
8, and that's it, you can't choose to build with something that does *not* have bindings
for iOS 17.0.

This will change with multi-targeting: we'll support *some* matrix of bindings. For
instance, we might want to support the OS version we shipped initial support in any
given .NET release + the latest OS version.

For example, we might want to support both of these:

* net8.0-ios17.0
* net8.0-ios17.2

This means that the target platform version (17.0/17.2) can't keep staying ignored.

The proper way to do this is to change the `SdkSupportedTargetPlatformVersion` item
group to only include target platform version we actually support, but the downside
of this approach is that it will make existing projects fail to compile, if they
happened to include an invalid target platform version.

So I've added a compatibility mode for .NET 8, where we show a warning (and tell
the developer what to do) instead of an error, and then in .NET 9 we'll make the
warning an error instead. This is accomplished by still lying in the `SdkSupportedTargetPlatformVersion`
item group in .NET 8, and detect the condition in our own logic and report the error.
For .NET 9 we can remove this logic, makes ure `SdkSupportedTargetPlatformVersion`
is correct, and then .NET itself will show the proper error.

Side note: Android is also making an invalid target platform version an error in
.NET 9: dotnet/android#8569.

[1]: We'd ignore the value for executable projects. It did have an effect for library
projects that were packed into NuGets: the target platform version would be stored
in the NuGet.
@jonathanpeppers
Copy link
Member Author

I think there's a simpler way: change the SupportedTargetPlatformVersion item group to only include the target platform versions you support

I don't think we can remove the lower ones like 21-33, as they provide the ANDROID21-33 $(DefineConstants):

https://github.com/dotnet/sdk/blob/7bdcabeef08d0d361b39a8664f295299a3a3d330/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets#L234-L235

I think 21-33 also supports the analyzer that would warn about an API 24+-only API, which would require a OperatingSystem.IsAndroidAtLeast(24) check. (Although I'm having trouble finding the code responsible for this one)

@rolfbjarne
Copy link
Member

I think there's a simpler way: change the SupportedTargetPlatformVersion item group to only include the target platform versions you support

I don't think we can remove the lower ones like 21-33, as they provide the ANDROID21-33 $(DefineConstants):

dotnet/sdk@7bdcabe/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets#L234-L235

This implementation doesn't seem very future-proof... according to the design it seems the *_OR_GREATER defines are supposed to be defined for all eternity, but that means we can't ever remove anything from SupportedTargetPlatformVersion.

Instead, I think we'll have to maintain a separate list of OS versions, that we both support, and have supported at some point. To put it to the extreme, we'd have to define all variables starting with iOS 2... (which we obviously aren't going to do, but we'll have to pick some sane lower value - probably the min OS version in .NET 6 - and then never change it).

I think 21-33 also supports the analyzer that would warn about an API 24+-only API, which would require a OperatingSystem.IsAndroidAtLeast(24) check. (Although I'm having trouble finding the code responsible for this one)

I think this is keyed off the SupportedOSPlatformVersion property.

@jonathanpeppers
Copy link
Member Author

jonathanpeppers commented Jan 11, 2024

From the meeting, we might be able to do something like:

<ItemGroup>
  <!-- ancient ones, we just put some really low version -->
  <SdkSupportedTargetPlatformVersion Include="21" MaximumNETVersion="1.0" />
  <!-- ... -->
  <SdkSupportedTargetPlatformVersion Include="33" MaximumNETVersion="7.0" />
  <SdkSupportedTargetPlatformVersion Include="34" MinimumNETVersion="8.0" />
</ItemGroup>

We might need a change in dotnet/sdk to enable this, as only "Minimum" is supported:

https://github.com/dotnet/sdk/blob/12c083fc90700d3255cc021b665764876c5747fe/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.WindowsSdkSupportedTargetPlatforms.props#L18-L20

@rolfbjarne
Copy link
Member

From the meeting, we might be able to do something like:

<ItemGroup>
  <!-- ancient ones, we just put some really low version -->
  <SdkSupportedTargetPlatformVersion Include="21" MaximumNETVersion="1.0" />
  <!-- ... -->
  <SdkSupportedTargetPlatformVersion Include="33" MaximumNETVersion="7.0" />
  <SdkSupportedTargetPlatformVersion Include="34" MinimumNETVersion="8.0" />
</ItemGroup>

We might need a change in dotnet/sdk to enable this, as only "Minimum" is supported:

dotnet/sdk@12c083f/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.WindowsSdkSupportedTargetPlatforms.props#L18-L20

I think this would have to be changed to take into account both a min and a max:

https://github.com/dotnet/sdk/blob/12c083fc90700d3255cc021b665764876c5747fe/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.TargetFrameworkInference.targets#L233-L246

@rolfbjarne
Copy link
Member

I filed dotnet/sdk#38016 (and a PR with a suggested fix) about this.

Note that I didn't go for the .NET version range validation, because it doesn't really work for us.

We might want to have strange combination of valid values SdkSupportedTargetPlatformVersion. For a given iOS release, these might be the versions we'd want to support (all in .NET 8):

  • iOS 17.0: 17.0
  • iOS 17.1: 17.0 + 17.1
  • iOS 17.2: 17.0 + 17.2 (but not 17.1)

and the .NET version range check becomes weird in that case (we'd have to come up with something non-intuitive to exclude 17.1).

rolfbjarne added a commit to rolfbjarne/xamarin-macios that referenced this pull request Jan 24, 2024
We've used to ignore the target platform version (the "17.0" part in "net8.0-ios17.0")
since our initial .NET relaese - customers could specify any valid OS version between
the minimum and maximum versions, and we'd completely ignore the value [1].

The purpose of the target platform version is to specify which bindings to choose:
"net8.0-ios17.0" would mean that the developer wants packages that have bindings
for iOS 17.0 (and earlier iOS versions, but not later iOS versions).

So saying "net8.0-ios11.0" would technically mean that the developer would want our
bindings for iOS 11.0 (and earlier iOS versions, but not later iOS versions). The
problem is that we don't ship any such thing... we shipped iOS 17.0 bindings in .NET
8, and that's it, you can't choose to build with something that does *not* have bindings
for iOS 17.0.

This will change with multi-targeting: we'll support *some* matrix of bindings. For
instance, we might want to support the OS version we shipped initial support in any
given .NET release + the latest OS version.

For example, we might want to support both of these:

* net8.0-ios17.0
* net8.0-ios17.2

This means that the target platform version (17.0/17.2) can't keep staying ignored.

There was an somewhat related issue with the `SdkSupportedTargetPlatformVersion`,
where we're now able to distinguish between old versions we no longer support and
new versions that limits the valid values for TargetPlatformVersion (see 74d83ca).
We've already taken advantage of this to properly annotate every version, even in
.NET 8 (in a future service update), because the dotnet/sdk change required to understand
the new annotations (and ignore old versions in the `SdkSupportedTargetPlatformVersion`
item group) won't be shipped until .NET 9, so this won't be a breaking change in
.NET 8.

However, we'd still like to give customers a heads up that their project files need
to change, so this PR adds a warning (that tells developers what to do), and then
in .NET 9 we'll make the warning an error instead. Side note: Android is also making
an invalid target platform version an error in .NET 9: dotnet/android#8569.

[1]: We'd ignore the value for executable projects. It did have an effect for library
projects that were packed into NuGets: the target platform version would be stored
in the NuGet.
rolfbjarne added a commit to xamarin/xamarin-macios that referenced this pull request Jan 25, 2024
…19901)

We've used to ignore the target platform version (the "17.0" part in "net8.0-ios17.0")
since our initial .NET relaese - customers could specify any valid OS version between
the minimum and maximum versions, and we'd completely ignore the value [1].

The purpose of the target platform version is to specify which bindings to choose:
"net8.0-ios17.0" would mean that the developer wants packages that have bindings
for iOS 17.0 (and earlier iOS versions, but not later iOS versions).

So saying "net8.0-ios11.0" would technically mean that the developer would want our
bindings for iOS 11.0 (and earlier iOS versions, but not later iOS versions). The
problem is that we don't ship any such thing... we shipped iOS 17.0 bindings in .NET
8, and that's it, you can't choose to build with something that does *not* have bindings
for iOS 17.0.

This will change with multi-targeting: we'll support *some* matrix of bindings. For
instance, we might want to support the OS version we shipped initial support in any
given .NET release + the latest OS version.

For example, we might want to support both of these:

* net8.0-ios17.0
* net8.0-ios17.2

This means that the target platform version (17.0/17.2) can't keep staying ignored.

There was an somewhat related issue with the `SdkSupportedTargetPlatformVersion`,
where we're now able to distinguish between old versions we no longer support and
new versions that limits the valid values for TargetPlatformVersion (see 74d83ca).
We've already taken advantage of this to properly annotate every version, even in
.NET 8 (in a future service update), because the dotnet/sdk change required to understand
the new annotations (and ignore old versions in the `SdkSupportedTargetPlatformVersion`
item group) won't be shipped until .NET 9, so this won't be a breaking change in
.NET 8.

However, we'd still like to give customers a heads up that their project files need
to change, so this PR adds a warning (that tells developers what to do), and then
in .NET 9 we'll make the warning an error instead. Side note: Android is also making
an invalid target platform version an error in .NET 9: dotnet/android#8569.

[1]: We'd ignore the value for executable projects. It did have an effect for library
projects that were packed into NuGets: the target platform version would be stored
in the NuGet.
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this pull request Feb 29, 2024
…API levels

Fixes: dotnet#8331
Context: dotnet#8569
Context: dotnet/sdk@25b360d

Building for `net9.0-android33` would give a poor error message:

    error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.33' was not present in workload manifests.
    C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

To solve this, you would either change 33 to 34, or just remove the number to rely on the default value.

To make this easier:

* Automatically switch to 34 if the user specifies 33 or less.

* Opt into `%(DefineConstantsOnly)=true` for API levels 21-33 (and not
  the latest), which allows the .NET SDK to emit the *better* .NET SDK
  error message instead.

So now users will get:

    (_CheckForInvalidTargetPlatformVersion target) ->
    dotnet/sdk/9.0.100-alpha.1.23628.5/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.TargetFrameworkInference.targets(243,5):
    error NETSDK1140: 33.0 is not a valid TargetPlatformVersion for Android.
    Valid versions include: 34.0

I added a test for this scenario.
@jonathanpeppers
Copy link
Member Author

Closing in favor of: #8777

jonathanpeppers added a commit that referenced this pull request Mar 1, 2024
…API levels (#8777)

Fixes: #8331
Context: #8569
Context: dotnet/sdk@25b360d

Building for `net9.0-android33` would give a poor error message:

    error NETSDK1181: Error getting pack version: Pack 'Microsoft.Android.Ref.33' was not present in workload manifests.
    C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

To solve this, you would either change 33 to 34, or just remove the number to rely on the default value.

To make this easier:

* Automatically switch to 34 if the user specifies 33 or less.

* Opt into `%(DefineConstantsOnly)=true` for API levels 21-33 (and not
  the latest), which allows the .NET SDK to emit the *better* .NET SDK
  error message instead.

So now users will get:

    (_CheckForInvalidTargetPlatformVersion target) ->
    dotnet/sdk/9.0.100-alpha.1.23628.5/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.TargetFrameworkInference.targets(243,5):
    error NETSDK1140: 33.0 is not a valid TargetPlatformVersion for Android.
    Valid versions include: 34.0

I added a test for this scenario.
@github-actions github-actions bot locked and limited conversation to collaborators Apr 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TargetFramework=net8.0-android33 gives poor error message
5 participants