From 5ee304c07472b56f9785e8921af75c70dcfa8db4 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 4 Mar 2020 10:28:03 -0500 Subject: [PATCH] [build] Use `$(AndroidPlatformId)` when appropriate Context: 485e39b173c5c9516b91bd1e850781124a6fb4bd Context: eb08bb464567f70d1977d0a349d38e336842d867 ...and doubtless others... Three MSBuild properties control the `android.jar` which is bound and the `$(TargetFrameworkVersion)` of `Mono.Android.dll`: * `$(AndroidApiLevel)`: The API level that is bound. Must be an int. * `$(AndroidFrameworkVersion)`: The `$(TargetFrameworkVersion)` of the generated `Mono.Android.dll`. Must be *mostly* parseable by `System.Version` except with a leading `v`, e.g. `v10.0`. * `$(AndroidPlatformId)`: The "ID" of the API level. *Most* of the time, `$(AndroidApiLevel)` and `$(AndroidPlatformId)` will be *identical*: for API-29, they're both `29`. Where they differ is for new *preview* API levels, such as API-R: `$(AndroidApiLevel)` will be 30, but `$(AndroidPlatformId)` is `R`. The distinction is important because various filesystem paths within the Android SDK use the "id" and *not* the API level when they differ, e.g. the API-R `android.jar` is installed into: $(AndroidSdkDirectory)/platforms/android-R/android.jar We thus need to be *careful* when distinguishing between `$(AndroidApiLevel)` and `$(AndroidPlatformId)`, using the former when an integer is *required*, and using the latter whenever it refers to filesystem paths. Unfortunately, we *haven't* been careful, because these values really only differ for ~4 months out of the year, and for only one `$(TargetFrameworkVersion)` version. Start bringing some sanity...and finding bugs while we do so: `api-xml-adjuster.targets` should use `%(AndroidApiInfo.Id)` and *not* `%(AndroidApiLevel.Level)`, as it references filesystem locations. Consequently, `src/Mono.Android/Profiles/api-30.params.txt` must be renamed to `src/Mono.Android/Profiles/api-R.params.txt` so that it correctly embeds the `$(AndroidPlatformId)` value. `Mono.Android.targets` should likewise use `$(AndroidPlatformId)` and not `$(AndroidApiLevel)` when using filesystem paths from the SDK. For good measure, `Mono.Android.csproj` now overrides `$(IntermediateOutputPath)` to contain `$(AndroidPlatformId)`, because why not (MOAR CONSISTENCY!). These changes, unfortunately, introduce breakage, which will need to be addressed: *Because* API-R was installed into `$(AndroidSdkDirectory)/platforms/android-R`, `api-versions.xml` *was not previously used* because `Mono.Android.targets` was using `$(AndroidApiLevel)`, and `platforms/android-30/data/api-version.xml` does not yet exist. (It will come June! But not now.) As it didn't exist, it hit the fallback path and used `platform-tools/api/api-versions.xml` (4cd20605c). You would *think* this wouldn't be a problem, but the API-R `api-versions.xml` is *missing* members relative to platform-tools, resulting in members *missing* `RegisterAttribute.ApiSince` values, which `Microsoft.DotNet.ApiCompat.exe` reports, e.g.: CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'Java.Lang.StringBuilder.TrimToSize()' changed from '[RegisterAttribute("trimToSize", "()V", "", ApiSince=9)]' in the contract to '[RegisterAttribute("trimToSize", "()V", "")]' in the implementation xamarin/java.interop@568d24ac added support to allow `generator --apiversions` to be specified multiple times. Take advantage of this new support to pass in the `api-versions.xml` files from *both* `platforms/android-R` *and* `platform-tools/api` when binding API levels > API-29. (Attempting to do this for *all* versions which have both resulted in bizarre API compat errors, as the `RegisterAttribute.ApiSince` value was *cleared*. ?!) This works around the deficiency in API-R's `api-versions.xml` and allows us to retain correct `RegisterAttribute.ApiSince` values. Aside: to manually build the API-R binding, use: msbuild /p:AndroidPlatformId=R /p:AndroidApiLevel=30 /p:AndroidFrameworkVersion=v10.0.99 src/Mono.Android/Mono.Android.csproj /v:diag > b.txt --- .../api-xml-adjuster/api-xml-adjuster.targets | 10 +++++----- src/Mono.Android/Mono.Android.csproj | 2 +- src/Mono.Android/Mono.Android.targets | 15 ++++++++++++--- .../{api-30.params.txt => api-R.params.txt} | 0 4 files changed, 18 insertions(+), 9 deletions(-) rename src/Mono.Android/Profiles/{api-30.params.txt => api-R.params.txt} (100%) diff --git a/build-tools/api-xml-adjuster/api-xml-adjuster.targets b/build-tools/api-xml-adjuster/api-xml-adjuster.targets index 8432970bf27..4b24b03288a 100644 --- a/build-tools/api-xml-adjuster/api-xml-adjuster.targets +++ b/build-tools/api-xml-adjuster/api-xml-adjuster.targets @@ -10,12 +10,12 @@ <_Api - Condition=" Exists('$(_TopDir)\src\Mono.Android\Profiles\api-%(AndroidApiInfo.Level).params.txt') " + Condition=" Exists('$(_TopDir)\src\Mono.Android\Profiles\api-%(AndroidApiInfo.Id).params.txt') " Include="@(AndroidApiInfo)"> + AdditionalMetadata="ParameterDescription=$(_TopDir)\src\Mono.Android\Profiles\api-%(_Api.Id).params.txt;ClassParseXml=$(_OutputPath)api\api-%(_Api.Id).xml.class-parse;ApiAdjustedXml=$(_OutputPath)api\api-%(_Api.Id).xml.in"> @@ -30,8 +30,8 @@ $(_TopDir)\bin\Build$(Configuration)\api-xml-adjuster.exe diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index a6dbe692964..f6851d03598 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -97,7 +97,7 @@ False - $(IntermediateOutputPath)android-$(AndroidApiLevel)\ + $(IntermediateOutputPath)android-$(AndroidPlatformId)\ diff --git a/src/Mono.Android/Mono.Android.targets b/src/Mono.Android/Mono.Android.targets index 373e64eac0f..51dbd6718bc 100644 --- a/src/Mono.Android/Mono.Android.targets +++ b/src/Mono.Android/Mono.Android.targets @@ -79,9 +79,18 @@ Outputs="$(IntermediateOutputPath)mcw\Mono.Android.projitems"> - <_ApiVersions Condition="Exists('$(AndroidSdkDirectory)\platforms\android-$(AndroidApiLevel)\data\api-versions.xml')">"$(AndroidSdkDirectory)\platforms\android-$(AndroidApiLevel)\data\api-versions.xml" - <_ApiVersions Condition="'$(_ApiVersions)'==''">"$(AndroidSdkDirectory)\platform-tools\api\api-versions.xml" + <_PlatformIdVersions>$(AndroidSdkDirectory)\platforms\android-$(AndroidPlatformId)\data\api-versions.xml + + <_ApiVersion + Condition=" '$(AndroidApiLevel)' > 29 Or !Exists ('$(_PlatformIdVersions)')" + Include="$(AndroidSdkDirectory)\platform-tools\api\api-versions.xml" + /> + <_ApiVersion + Condition="Exists('$(_PlatformIdVersions)')" + Include="$(_PlatformIdVersions)" + /> + "$(XAInstallPrefix)xbuild\Xamarin\Android\generator.exe" <_GenFlags>--public --product-version=7 @@ -91,7 +100,7 @@ <_Fixup>--fixup=metadata <_Enums1>--preserve-enums --enumflags=enumflags --enumfields=map.csv --enummethods=methodmap.csv <_Enums2>--enummetadata=$(IntermediateOutputPath)mcw\enummetadata - <_Versions>--apiversions=$(_ApiVersions) + <_Versions>@(_ApiVersion->'--apiversions="%(Identity)"', ' ') <_Annotations>--annotations="$(AndroidSdkDirectory)\platform-tools\api\annotations.zip" <_Assembly>--assembly="Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" <_TypeMap>--type-map-report=$(IntermediateOutputPath)mcw\type-mapping.txt diff --git a/src/Mono.Android/Profiles/api-30.params.txt b/src/Mono.Android/Profiles/api-R.params.txt similarity index 100% rename from src/Mono.Android/Profiles/api-30.params.txt rename to src/Mono.Android/Profiles/api-R.params.txt