-
Notifications
You must be signed in to change notification settings - Fork 524
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
[create-vsix] Create a separate package for unstable frameworks #1439
Conversation
**Background** It's Android preview time! Even better, we have support for building API-P bindings within around a week of the Google announcement, via 8ce2537. This raises a question: How does this binding get *used*? Historically, we haven't been very good at this: various bits of code needed to know *all* of the API levels (to associate with `$(TargetFrameworkVersion)` values and Ids and names and...), which meant that the only way the preview binding could be used was to have a preview release of the *entire development stack*: Xamarin.Android, IDE, build-tools, the works. Invariably we didn't have a "preview" release of the new binding until after it was API-stable (or close to it), and the IDEs have been updated, all of which would be *months* after the announcement. Commit 8942eca envisioned a New World Order™ in which the mapping between API level and `$(TargetFrameworkVersion)`/etc. could be more *dynamic*, based on `AndroidApiInfo.xml` files probed at process and IDE startup, to *simplify* what it takes to use binding assemblies. This support, mutated in various forms, is already in the IDEs (though a preview IDE may be needed). With foundational support, we can now try the next bit: update `create-vsix.csproj` so that it can generate one of two packages: 1. A `Xamarin.Android.Sdk-OSS-*.vsix` file which contains *only* the stable API level bindings. 2. An optional `Xamarin.Android.Sdk-OSS-*-UnstableFrameworks.vsix` file which contains *only* the ***unstable*** API bindings. The idea is that the first package can be the "normal" release package, while the second package can be installed "side-by-side" with the first pacakge. Furthermore, the *intent* is that the `-UnstableFrameworks` package could be installed side-by-side with *any* Xamarin.Android.Sdk package. Ideally, this means that it could be installed alongside the current *stable* Xamarin.Android SDK package, with no ill effects. The target workflow is thus: 1. Developer has Xamarin.Android SDK installed on their machine. 2. Developer downloads and installs the `-UnstableFrameworks` package from: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/lastSuccessfulBuild/Azure/ 3. Developer restarts their IDE. 4. Developer edits the `.csproj` of their project, and sets the `$(TargetFrameworkVersion)` value to the value of the unstable API binding, e.g. `v8.1.99`. *Note*: It may instead be possible to change things from within the IDE. Some specifics are not yet sorted out. 5. The next build of the project uses the preview/unstable API level. With luck, this should allow us to provide "usable" (if broken! they're not API stable!) for testing on an improved timeframe. **Implementation** Hack up `create-vsix.csproj` and company to support a new MSBuild property: `$(UnstableFrameworks)` (default False). When True, the output package name is changed to have a `-UnstableFrameworks` suffix, the package ID is changed, the installation directory is changed... *Lots* of things are changed, including the package contents. The "normal" package is altered so that it *only* contains Stable framework bindings. (This is a change from before, in which *all* framework bindings were included.) The "unstable" package contains only non-Stable framework bindings. The `make create-vsix` Makefile target and `HaveUnstableFrameworks` target within `build-tools/scripts/Info.targets` work together to only build the `-UnstableFrameworks.vsix` package if there *are* unstable frameworks to package. If there are no unstable packages, no `-UnstableFrameworks` package is created.
@kzu: What are the semantics/requirements of |
@jonpryor like the idea of having an add-on package. However what happens when a user updates the main .visx when the preview api is now stable? Will the old unstable frameworks directory be removed? |
@dellis1972 asked:
The preview However, I don't actually know. @kzu? :-D |
Nothing can be replaced/overwritten across packages. If files already exist on-disk from a package with another ID, installation of the new one will fail. So, this can only work if both stick to strictly distinct paths. or you document that people should remove the unstable manually before installing the stable that includes that aftewards... Not a nice experience in either case :(. Also, there are no guidelines on package Ids. Many devs even leave the default GUId they get when the FIle|New in VS 🤷♂️ |
Also, will this change anything with regards to how the IDEs discover the available target frameworks for the dropdowns? /cc @tondat |
build |
The
|
Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/592736 Fixes: #1498 Context: 0780e27 Context: #1439 What does it take to *use* a new (and unstable!) API level? Commit 8942eca tried to lay some of this out, but *in principal* the current process should be: 1. Bind the new API level. 2. Add a new `@(AndroidApiInfo)` entry for the new API level. 3. Specify the `$(TargetFrameworkVersion)` of the new API level when building a project. Commit 8ce2537 bound API-P as v8.1.99, finishing steps (1) and (2). Therefore, step (3) should just work, right? $ cd samples/HelloWorld $ ../../bin/Debug/bin/xabuild /p:TargetFrameworkVersion=v8.1.99 # no errors Success! Except, when reading the diagnostic log file, we see: ResolveSdksTask Outputs: AndroidApiLevel: 27 AndroidApiLevelName: 27 ... TargetFrameworkVersion: v8.1.99 We're using the correct v8.1.99 *binding assembly*, but we're *not* using the API-P `android.jar`, because the `<ResolveSdks>` task is treating v8.1.99 (API-P/API-28) as API-27. Oops. --- There are three msbuild invocations of consequence here: 1. `xabuild /p:AndroidUseLatestPlatformSdk=True` 2. `xabuild /p:AndroidUseLatestPlatformSdk=True /p:TargetFrameworkVersion=v8.1.99` 3. `xabuild /p:AndroidUseLatestPlatformSdk=False /p:TargetFrameworkVersion=v8.1.99` (1) is the "default build" scenario (at least so long as our default project templates specify `$(AndroidUseLatestPlatformSdk)`=True). This should build the project against the latest *stable* API level and `$(TargetFrameworkVersion)`, as per 0780e27. This works. (Yay!) If you want to build an *unstable* API level, then the `$(TargetFrameworkVersion)` value must be set explicitly, either on the command-line (as shown here) or by editing the `.csproj`. (2) and (3) are variations to build using the unstable API-P binding; they *should* be identical, but due to code-path differences in `<ResolveSdks>`, they are not necessarily the same. Both (2) and (3) *should* work; they don't, with different behaviors. (2) *builds*, but uses the wrong `android.jar` during compilation, as described above with the `samples/HelloWorld` example. Fix (2) by setting `ResolveSdks.AndroidApiLevel` to `ResolveSdks.SupportedApiLevel`, so that it overrides the default behavior of using the latest *stable* API level value when `$(AndroidUseLatestPlatformSdk)`=True. (3) does *not* build: ResolveSdksTask Outputs: AndroidApiLevel: P AndroidApiLevelName: P ... Task "GetAndroidDefineConstants" …\Xamarin\Android\Xamarin.Android.Common.targets(910,29): error MSB4030: "P" is an invalid value for the "AndroidApiLevel" parameter of the "GetAndroidDefineConstants" task. The "AndroidApiLevel" parameter is of type "System.Int32". Done executing task "GetAndroidDefineConstants" -- FAILED. (3) doesn't build because the `<GetAndroidDefineConstants/>` task invocation is provided `$(_SupportedApiLevel)`, which is the above `AndroidApiLevel` output, and thus contains a value of `P`. Fix (3) by using `AndroidVersions.GetApiLevelFromId()` to lookup the correct API level based on the id derived from `$(TargetFrameworkVersion)` value. This in turn raises a *different* bug: `aapt package` doesn't like to use id values, it wants *just* numbers. Fixing *just* `<ResolveSdks>` results in a build error: Aapt Task ... Executing package -f -m -M obj/Debug/android/manifest/AndroidManifest.xml -J /var/folders/1y/wwmg3hv5685ft661f5q2w2100000gn/T/7464w5of.vfk --custom-package com.xamarin.android.helloworld -F obj/Debug/android/bin/packaged_resources.bk -S obj/Debug/res/ -I …/android-toolchain/sdk/platforms/android-P/android.jar --auto-add-overlay --max-res-version P aapt: error APT0000: max res 0, skipping mipmap-hdpi "max res 0, skipping mipmap-hdpi". aapt: error APT0000: max res 0, skipping mipmap-mdpi "max res 0, skipping mipmap-mdpi". aapt: error APT0000: max res 0, skipping mipmap-xhdpi "max res 0, skipping mipmap-xhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxhdpi "max res 0, skipping mipmap-xxhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxxhdpi "max res 0, skipping mipmap-xxxhdpi". obj/Debug/android/manifest/AndroidManifest.xml(7): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). obj/Debug/android/manifest/AndroidManifest.xml(8): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). Fix this by updating the `<GetJavaPlatformJar/>` task so that `GetJavaPlatformJar.TargetSdkVersion` contains an integer API level value, not the API id. This fixes the `<Aapt/>` error.
* [Xamarin.Android.Build.Tasks] %(AndroidApiInfo.Stable)=False Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/592736 Fixes: #1498 Context: 0780e27 Context: #1439 What does it take to *use* a new (and unstable!) API level? Commit 8942eca tried to lay some of this out, but *in principal* the current process should be: 1. Bind the new API level. 2. Add a new `@(AndroidApiInfo)` entry for the new API level. 3. Specify the `$(TargetFrameworkVersion)` of the new API level when building a project. Commit 8ce2537 bound API-P as v8.1.99, finishing steps (1) and (2). Therefore, step (3) should just work, right? $ cd samples/HelloWorld $ ../../bin/Debug/bin/xabuild /p:TargetFrameworkVersion=v8.1.99 # no errors Success! Except, when reading the diagnostic log file, we see: ResolveSdksTask Outputs: AndroidApiLevel: 27 AndroidApiLevelName: 27 ... TargetFrameworkVersion: v8.1.99 We're using the correct v8.1.99 *binding assembly*, but we're *not* using the API-P `android.jar`, because the `<ResolveSdks>` task is treating v8.1.99 (API-P/API-28) as API-27. Oops. --- There are three msbuild invocations of consequence here: 1. `xabuild /p:AndroidUseLatestPlatformSdk=True` 2. `xabuild /p:AndroidUseLatestPlatformSdk=True /p:TargetFrameworkVersion=v8.1.99` 3. `xabuild /p:AndroidUseLatestPlatformSdk=False /p:TargetFrameworkVersion=v8.1.99` (1) is the "default build" scenario (at least so long as our default project templates specify `$(AndroidUseLatestPlatformSdk)`=True). This should build the project against the latest *stable* API level and `$(TargetFrameworkVersion)`, as per 0780e27. This works. (Yay!) If you want to build an *unstable* API level, then the `$(TargetFrameworkVersion)` value must be set explicitly, either on the command-line (as shown here) or by editing the `.csproj`. (2) and (3) are variations to build using the unstable API-P binding; they *should* be identical, but due to code-path differences in `<ResolveSdks>`, they are not necessarily the same. Both (2) and (3) *should* work; they don't, with different behaviors. (2) *builds*, but uses the wrong `android.jar` during compilation, as described above with the `samples/HelloWorld` example. Fix (2) by setting `ResolveSdks.AndroidApiLevel` to `ResolveSdks.SupportedApiLevel`, so that it overrides the default behavior of using the latest *stable* API level value when `$(AndroidUseLatestPlatformSdk)`=True. (3) does *not* build: ResolveSdksTask Outputs: AndroidApiLevel: P AndroidApiLevelName: P ... Task "GetAndroidDefineConstants" …\Xamarin\Android\Xamarin.Android.Common.targets(910,29): error MSB4030: "P" is an invalid value for the "AndroidApiLevel" parameter of the "GetAndroidDefineConstants" task. The "AndroidApiLevel" parameter is of type "System.Int32". Done executing task "GetAndroidDefineConstants" -- FAILED. (3) doesn't build because the `<GetAndroidDefineConstants/>` task invocation is provided `$(_SupportedApiLevel)`, which is the above `AndroidApiLevel` output, and thus contains a value of `P`. Fix (3) by using `AndroidVersions.GetApiLevelFromId()` to lookup the correct API level based on the id derived from `$(TargetFrameworkVersion)` value. This in turn raises a *different* bug: `aapt package` doesn't like to use id values, it wants *just* numbers. Fixing *just* `<ResolveSdks>` results in a build error: Aapt Task ... Executing package -f -m -M obj/Debug/android/manifest/AndroidManifest.xml -J /var/folders/1y/wwmg3hv5685ft661f5q2w2100000gn/T/7464w5of.vfk --custom-package com.xamarin.android.helloworld -F obj/Debug/android/bin/packaged_resources.bk -S obj/Debug/res/ -I …/android-toolchain/sdk/platforms/android-P/android.jar --auto-add-overlay --max-res-version P aapt: error APT0000: max res 0, skipping mipmap-hdpi "max res 0, skipping mipmap-hdpi". aapt: error APT0000: max res 0, skipping mipmap-mdpi "max res 0, skipping mipmap-mdpi". aapt: error APT0000: max res 0, skipping mipmap-xhdpi "max res 0, skipping mipmap-xhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxhdpi "max res 0, skipping mipmap-xxhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxxhdpi "max res 0, skipping mipmap-xxxhdpi". obj/Debug/android/manifest/AndroidManifest.xml(7): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). obj/Debug/android/manifest/AndroidManifest.xml(8): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). Fix this by updating the `<GetJavaPlatformJar/>` task so that `GetJavaPlatformJar.TargetSdkVersion` contains an integer API level value, not the API id. This fixes the `<Aapt/>` error. * Add to LibraryResources.csproj
* [Xamarin.Android.Build.Tasks] %(AndroidApiInfo.Stable)=False Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/592736 Fixes: #1498 Context: 0780e27 Context: #1439 What does it take to *use* a new (and unstable!) API level? Commit 8942eca tried to lay some of this out, but *in principal* the current process should be: 1. Bind the new API level. 2. Add a new `@(AndroidApiInfo)` entry for the new API level. 3. Specify the `$(TargetFrameworkVersion)` of the new API level when building a project. Commit 8ce2537 bound API-P as v8.1.99, finishing steps (1) and (2). Therefore, step (3) should just work, right? $ cd samples/HelloWorld $ ../../bin/Debug/bin/xabuild /p:TargetFrameworkVersion=v8.1.99 # no errors Success! Except, when reading the diagnostic log file, we see: ResolveSdksTask Outputs: AndroidApiLevel: 27 AndroidApiLevelName: 27 ... TargetFrameworkVersion: v8.1.99 We're using the correct v8.1.99 *binding assembly*, but we're *not* using the API-P `android.jar`, because the `<ResolveSdks>` task is treating v8.1.99 (API-P/API-28) as API-27. Oops. --- There are three msbuild invocations of consequence here: 1. `xabuild /p:AndroidUseLatestPlatformSdk=True` 2. `xabuild /p:AndroidUseLatestPlatformSdk=True /p:TargetFrameworkVersion=v8.1.99` 3. `xabuild /p:AndroidUseLatestPlatformSdk=False /p:TargetFrameworkVersion=v8.1.99` (1) is the "default build" scenario (at least so long as our default project templates specify `$(AndroidUseLatestPlatformSdk)`=True). This should build the project against the latest *stable* API level and `$(TargetFrameworkVersion)`, as per 0780e27. This works. (Yay!) If you want to build an *unstable* API level, then the `$(TargetFrameworkVersion)` value must be set explicitly, either on the command-line (as shown here) or by editing the `.csproj`. (2) and (3) are variations to build using the unstable API-P binding; they *should* be identical, but due to code-path differences in `<ResolveSdks>`, they are not necessarily the same. Both (2) and (3) *should* work; they don't, with different behaviors. (2) *builds*, but uses the wrong `android.jar` during compilation, as described above with the `samples/HelloWorld` example. Fix (2) by setting `ResolveSdks.AndroidApiLevel` to `ResolveSdks.SupportedApiLevel`, so that it overrides the default behavior of using the latest *stable* API level value when `$(AndroidUseLatestPlatformSdk)`=True. (3) does *not* build: ResolveSdksTask Outputs: AndroidApiLevel: P AndroidApiLevelName: P ... Task "GetAndroidDefineConstants" …\Xamarin\Android\Xamarin.Android.Common.targets(910,29): error MSB4030: "P" is an invalid value for the "AndroidApiLevel" parameter of the "GetAndroidDefineConstants" task. The "AndroidApiLevel" parameter is of type "System.Int32". Done executing task "GetAndroidDefineConstants" -- FAILED. (3) doesn't build because the `<GetAndroidDefineConstants/>` task invocation is provided `$(_SupportedApiLevel)`, which is the above `AndroidApiLevel` output, and thus contains a value of `P`. Fix (3) by using `AndroidVersions.GetApiLevelFromId()` to lookup the correct API level based on the id derived from `$(TargetFrameworkVersion)` value. This in turn raises a *different* bug: `aapt package` doesn't like to use id values, it wants *just* numbers. Fixing *just* `<ResolveSdks>` results in a build error: Aapt Task ... Executing package -f -m -M obj/Debug/android/manifest/AndroidManifest.xml -J /var/folders/1y/wwmg3hv5685ft661f5q2w2100000gn/T/7464w5of.vfk --custom-package com.xamarin.android.helloworld -F obj/Debug/android/bin/packaged_resources.bk -S obj/Debug/res/ -I …/android-toolchain/sdk/platforms/android-P/android.jar --auto-add-overlay --max-res-version P aapt: error APT0000: max res 0, skipping mipmap-hdpi "max res 0, skipping mipmap-hdpi". aapt: error APT0000: max res 0, skipping mipmap-mdpi "max res 0, skipping mipmap-mdpi". aapt: error APT0000: max res 0, skipping mipmap-xhdpi "max res 0, skipping mipmap-xhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxhdpi "max res 0, skipping mipmap-xxhdpi". aapt: error APT0000: max res 0, skipping mipmap-xxxhdpi "max res 0, skipping mipmap-xxxhdpi". obj/Debug/android/manifest/AndroidManifest.xml(7): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). obj/Debug/android/manifest/AndroidManifest.xml(8): error APT0000: No resource found that matches the given name (at 'icon' with value '@mipmap/icon'). Fix this by updating the `<GetJavaPlatformJar/>` task so that `GetJavaPlatformJar.TargetSdkVersion` contains an integer API level value, not the API id. This fixes the `<Aapt/>` error. * Add to LibraryResources.csproj
Closing this PR as obsolete; we have a completely different packaging system now. |
Background
It's Android preview time!
Even better, we have support for building API-P bindings within around
a week of the Google announcement, via 8ce2537.
This raises a question: How does this binding get used?
Historically, we haven't been very good at this: various bits of code
needed to know all of the API levels (to associate with
$(TargetFrameworkVersion)
values and Ids and names and...), whichmeant that the only way the preview binding could be used was to have
a preview release of the entire development stack: Xamarin.Android,
IDE, build-tools, the works.
Invariably we didn't have a "preview" release of the new binding until
after it was API-stable (or close to it), and the IDEs have been
updated, all of which would be months after the announcement.
Commit 8942eca envisioned a New World Order™ in which the mapping
between API level and
$(TargetFrameworkVersion)
/etc. could be moredynamic, based on
AndroidApiInfo.xml
files probed at process andIDE startup, to simplify what it takes to use binding assemblies.
This support, mutated in various forms, is already in the IDEs (though
a preview IDE may be needed).
With foundational support, we can now try the next bit: update
create-vsix.csproj
so that it can generate one of two packages:A
Xamarin.Android.Sdk-OSS-*.vsix
file which contains only thestable API level bindings.
An optional
Xamarin.Android.Sdk-OSS-*-UnstableFrameworks.vsix
file which contains only the unstable API bindings.
The idea is that the first package can be the "normal" release
package, while the second package can be installed "side-by-side" with
the first pacakge.
Furthermore, the intent is that the
-UnstableFrameworks
packagecould be installed side-by-side with any Xamarin.Android.Sdk
package. Ideally, this means that it could be installed alongside the
current stable Xamarin.Android SDK package, with no ill effects.
The target workflow is thus:
Developer has Xamarin.Android SDK installed on their machine.
Developer downloads and installs the
-UnstableFrameworks
package from:
Developer restarts their IDE.
Developer edits the
.csproj
of their project, and sets the$(TargetFrameworkVersion)
value to the value of the unstable APIbinding, e.g.
v8.1.99
.Note: It may instead be possible to change things from within
the IDE. Some specifics are not yet sorted out.
The next build of the project uses the preview/unstable API level.
With luck, this should allow us to provide "usable" (if broken!
they're not API stable!) for testing on an improved timeframe.
Implementation
Hack up
create-vsix.csproj
and company to support a new MSBuildproperty:
$(UnstableFrameworks)
(default False). When True, theoutput package name is changed to have a
-UnstableFrameworks
suffix,the package ID is changed, the installation directory is changed...
Lots of things are changed, including the package contents.
The "normal" package is altered so that it only contains Stable
framework bindings. (This is a change from before, in which all
framework bindings were included.)
The "unstable" package contains only non-Stable framework bindings.
The
make create-vsix
Makefile target andHaveUnstableFrameworks
target within
build-tools/scripts/Info.targets
work together to onlybuild the
-UnstableFrameworks.vsix
package if there are unstableframeworks to package. If there are no unstable packages, no
-UnstableFrameworks
package is created.