-
Notifications
You must be signed in to change notification settings - Fork 533
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] Fragments & Shorter acw-map #1301
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fixes: dotnet#1296 Xamarin.Android attempts to expose the Java-based Android API as a ".NET feeling" API. This takes many forms, such as prefixing interface names with `I`, mapping `get` and `set` methods to properties, mapping listener interfaces to events, and PascalCasing method names. This also affects Java package names and C# namespaces. When creating the `.apk` file, we philosophically need to go the opposite direction: PascalCased members need to be mapped to "something appropriate" within Java. For example, many Android Resource ids *must* be all lowercase, and Android doesn't support package names starting with an uppercase letter in all circumstances. At one point, we tried mapping C# PascalCased namespaces to camelCased namespaces, so e.g. `MyExampleNamespace` became the `myExampleNamesapce` Java package within Java Callable Wrappers. This turned out to be a Terrible Mistake, particularly on case-sensitive filesystems, as if casing was *inconsistent* (`MyExampleNamespace` vs `MyExamplenamespace`), files might not be packaged. By Mono for Android 1.0, we settled on just lowercasing the namespace name to produce Java package names within Android Callable Wrappers. This was not without it's own problems; in particular, the assembly name wasn't involved, so if the "same" type (namespace + type) were present in two different assemblies and we needed to generate Android Callable Wrappers, they'd "collide," the build would fail, and we'd have some unhappy customers. This was later addressed in Xamarin.Android 5.1 by changing the Java package name generation algorithm to be an MD5SUM of the assembly name and namespace name, thus allowing types to have assembly identity. (This was not without its own problems.) Then it gets slightly more complicated: Android allows type names to appear in various locations, such as in layout View XML. These don't allow "just" using the type name; the package name is required for types outside the `android.widget` Java package. Initially, we did nothing, so developers had to directly use the Android Callable Wrapper names: <myexamplenamespace.MyCustomCSharpView android:id="@+id/yay_csharp" .../> <fragment android:name="myexamplenamespace.MyCustomCSharpFragment" ... /> With the change in Xamarin.Android 5.1, *this couldn't work*; those types didn't exist anymore. To square this circle, we processed the resource files to "fixup" identifiers and replace them with the actual Android Callable Wrapper names. We'd replace any/all of: MyExampleNamespace.MyCustomCSharpView // Full name MyExampleNamespace.MyCustomCSharpView, MyAssembly // Partial assembly-qualified name MyExampleNamespace.MyCustomCSharpView, MyAssembly, Version=... // Full assembly qualified name myexamplenamespace.MyCustomCSharpView // compatibility name with the appropriate md5'd Android Callable Wrapper name. Brilliant as this was, there was a problem: [Bug #61073][61073]. If the assembly had a wildcard in the assembly version: [61073]: https://bugzilla.xamarin.com/show_bug.cgi?id=61073 [assembly: AssemblyVersion ("1.0.0.*")] then the "Full assembly qualified name" value would change on *every build*, which had numerious unintended knock-on effects. This was fixed in commit e5b1c92, which worked largely by just killing the Full assembly qualified name version entirely. Xamarin.Android doesn't support embedding two different versions of the same assembly, so this was considered to be fine. ...except for one compatibility case: `<fragment/>`s can contain ~arbitrary strings, and we support replacing the entire Full assembly qualified name within them: <fragment android:name="MyExampleNamespace.MyCustomCSharpFragment, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ... /> However, in a post e5b1c92 world, the above now fails to load on the device, because it's *not* being appropriately fixed up! FATAL EXCEPTION: main Process: Mono.Samples.HelloTests, PID: 22977 java.lang.RuntimeException: Unable to start activity ComponentInfo{Mono.Samples.HelloTests/mono.samples.HelloApp}: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment ... Caused by: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment Mono.Samples.Hello.MyFragment, Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: make sure class name exists, is public, and has an empty constructor that is public ... Caused by: java.lang.ClassNotFoundException: Didn't find class "Mono.Samples.Hello.MyFragment, Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" on path: DexPathList[[zip file "/data/app/Mono.Samples.HelloTests-1/base.apk"],nativeLibraryDirectories=[/data/app/Mono.Samples.HelloTests-1/lib/arm64, /system/fake-libs64, /data/app/Mono.Samples.HelloTests-1/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]] ... The problem is that what Android "sees" *should* be <fragment android:name="md5whatever.MyCustomCSharpFragment" ... /> where `md5whatever.MyCustomCSharpFragment` *is* a valid Java type that Android is able to load successfully, but because of e5b1c92 this replacement was removed. The fix: simplify the Full assembly-qualified name case to an already supported example. If the `//fragment/@android:name` value contains a `,`, assume it's an assembly qualified name and compute the Full name from it, by stripping off the comma and everything after it, then use the Full name to lookup the correct Android Callable Wrapper type.
dellis1972
approved these changes
Feb 14, 2018
baulig
pushed a commit
that referenced
this pull request
Feb 21, 2018
commit d3ad544 Author: Dean Ellis <[email protected]> Date: Wed Feb 21 16:36:10 2018 +0000 [Xamarin.Android.Build.Tasks] Update `CalculateProjectDependencies` to match spec (#1323) The `GetAndroidDependencies` target (f9b2c97) is intended to be called by an IDE on project-load, so that the IDE can install project dependencies "in the background," and ideally have the dependencies installed before the project is actually built. As such, the semantics of the `@(AndroidDependency)` output item group need to be agreed upon by xamarin-android, the IDEs, and whatever the IDEs use to actually install the dependencies. The `%(AndroidDependency.Identity)` values need to be well-defined and consistent across these three different libraries. In commit f9b2c97, certain values would have a version number "embedded" within `%(AndroidDependency.Identity)`, using a `;` to separate the name from the version, e.g. `build-tools;26.0.1`. Use of `;` was chosen because that made it easier for the package installation code to use (e.g. it would be identical to what the Android SDK `sdkmanager` utility expects). Unfortunately, the use of `;` was counter to the [spec][spec], and also looks "weird" in the context of MSBuild, as `;` is *also* the item group separator. Change the version separator to instead be a `/`. This "looks" better and is also consistent with the [installer manifest][manifest] schema that we will use, wherein `%(AndroidDependency.Identity)` matches a `//xamarin-android/*/@filesystem-path` attribute value: <xamarin-android sdk-version="0.0.0" generated-on="Tue, 20 Feb 2018 21:16:01 GMT"> <platform-tools filesystem-path="platform-tools" path="platform-tools" revision="27.0.1" manifest-url="https://dl.google.com/android/repository/repository2-1.xml" description="Android SDK Platform-Tools" obsolete="False" preview="False" license="android-sdk-license" original-type="generic:genericDetailsType"> <!-- ... --> </platform-tools> <build-tool filesystem-path="build-tools/27.0.3" path="build-tools;27.0.3" revision="27.0.3" manifest-url="https://dl.google.com/android/repository/repository2-1.xml" description="Android SDK Build-Tools 27.0.3" obsolete="False" preview="False" license="android-sdk-license" original-type="generic:genericDetailsType"> </build-tool> <!-- ... --> </xamarin-android> `@(AndroidDependency)` could be equivalent to: <ItemGroup> <AndroidDependency Include="build-tools/27.0.3"> <Version>27.0.3</Version> </AndroidDependency> <AndroidDependency Include="platform-tools"> <Version>$(AndroidSdkPlatformToolsVersion)</Version> </AndroidDependency> <AndroidDependency Include="platforms/android-27"> <Version>27</Version> </AndroidDependency> <AndroidDependency Include="tools"> <Version>$(AndroidSdkToolsVersion)</Version> </AndroidDependency> </ItemGroup> [manifest]: https://gist.github.com/dellis1972/08ba76cc19cdce3dec89c68684664299 [spec]: https://microsoft-my.sharepoint.com/:w:/r/personal/mhutch_microsoft_com/_layouts/15/WopiFrame.aspx?sourcedoc=%7B0436dd38-c9ff-4cf2-b33c-ee4515b68546%7D&action=edit&wdPid=64869a58 commit e489aae Author: Jonathan Pryor <[email protected]> Date: Wed Feb 21 10:41:32 2018 -0500 Bump to mono/2017-12/de4729fa (#1325) Context: #1078 Context: mono/mono#7145 The primary impetus is that mono/de4729fa contains "ignore" improvements to `mono-api-html`, which will be needed in order to complete PR #1078. commit f7b24f7 Author: Dean Ellis <[email protected]> Date: Tue Feb 20 16:25:23 2018 +0000 [Xamarin.Android.Build.Tests] Add tests for <ResolveSdks/> (#1321) This commit adds a basic unit test for the `<ResolveSdks/>` task. commit d207275 Author: Atsushi Eno <[email protected]> Date: Tue Feb 20 00:37:10 2018 +0900 [msbuild] Fix <Import>-ed filename, for case sensitivity. (#1322) There is a trivial difference between `msbuild` and `xbuild` - `msbuild` seems to respect (or ignorant of) the fact that filenames that are different in case are actually different on case-sensitive filesystem. Thus with `msbuild`, our binding projects don't build due to "missing" Microsoft.CSharp.Targets (there are only Microsoft.CSharp.targets even in `xbuild` support files in mono). This trivial fix should make it work. commit 49ecdda Author: Ludovic Henry <[email protected]> Date: Fri Feb 16 17:09:43 2018 -0500 Bump to mono/2017-12/0d51a806 (#1318) To simplify integrating mono's SDKs feature. commit 8419f81 Author: Jonathan Pryor <[email protected]> Date: Fri Feb 16 16:07:12 2018 -0500 Bump $(ProductVersion) to 8.3.99 (Commercial) Xamarin.Android v8.3 is being tracked in the [xamarin-android/d15-7][0] branch, which was branched from commit 70ccc83. Bump `$(ProductVersion)` to 8.3.99 to track development progress of the *next* version of Xamarin.Android. [0]: https://github.com/xamarin/xamarin-android/commits/d15-7 commit 70ccc83 Author: Matt Sylvia <[email protected]> Date: Fri Feb 16 11:56:35 2018 -0500 Bump to Java.Interop/master/15cf8c1, mono/2017-12/fbc4f05 (#1317) Context: mono/mono#6948 Harmonizes on cecil/mono-2017-12/dfee11e. commit c960a6f Author: Jonathan Pryor <[email protected]> Date: Fri Feb 16 10:43:11 2018 -0500 Bump to xamarin-android-api-compatibility/d15-7/dc5f0c2e Fixes an [ABI break][0] in 72ef39b: [0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/877/ <h3>Type Changed: Microsoft.SqlServer.Server.SqlDataRecord</h3> <p>Removed method:</p> <pre> <span class='removed removed-method breaking' data-is-breaking>public virtual System.Data.IDataReader GetData (int);</span> </pre> <h3>Type Changed: System.Data.SqlClient.SqlConnectionStringBuilder</h3> <p>Removed property:</p> <pre> <span class='removed removed-property breaking' data-is-breaking>public bool IsFixedSize { get; }</span> </pre> </div> <!-- end type SqlConnectionStringBuilder --> <!-- start type SqlParameterCollection --> <div> <h3>Type Changed: System.Data.SqlClient.SqlParameterCollection</h3> <p>Removed properties:</p> <pre> <span class='removed removed-property breaking' data-is-breaking>public bool IsFixedSize { get; }</span> <span class='removed removed-property breaking' data-is-breaking>public bool IsReadOnly { get; }</span> <span class='removed removed-property breaking' data-is-breaking>public bool IsSynchronized { get; }</span> </pre> This doesn't fix the "ABI break"; there is no ABI break of consequence. This fixes the *reporting* of the ABI break. See also: xamarin/xamarin-android-api-compatibility@5be4d43 commit 72ef39b Author: Jonathan Pryor <[email protected]> Date: Thu Feb 15 20:32:20 2018 -0500 Bump to xamarin-android-api-compatibility/d15-7/9d71e200 Context: #1303 Fixes an [ABI BREAK][0] from b2ca17a: <h3>Type Changed: Android.Widget.ListView</h3> <p>Modified fields:</p> <pre> <div data-is-breaking> public const <span class='removed removed-inline removed-breaking-inline'>int</span> <span class='added '>ChoiceMode</span> ChoiceModeMultiple = 2; </div><div data-is-breaking> public const <span class='removed removed-inline removed-breaking-inline'>int</span> <span class='added '>ChoiceMode</span> ChoiceModeNone = 0; </div><div data-is-breaking> public const <span class='removed removed-inline removed-breaking-inline'>int</span> <span class='added '>ChoiceMode</span> ChoiceModeSingle = 1; </div></pre> The problem is that [xamarin-android-api-compatibility PR #13][ac-13] is part of PR #1303, but #1303 hasn't been merged yet. As such, it had no need to be in the xamarin-android-api-compatibility/d15-7 branch. It has been reverted, thus fixing the above ABI break. [0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/876/console [ac-13]: xamarin/xamarin-android-api-compatibility#13 commit d0cb3ce Author: Jonathan Pryor <[email protected]> Date: Thu Feb 15 14:12:30 2018 -0500 Bump to mono/2017-12/2ad3f0bf Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60088 commit b2ca17a Author: Jonathan Pryor <[email protected]> Date: Thu Feb 15 12:38:12 2018 -0500 Bump to xamarin-android-api-compatibility/d15-7/10df9b67 (#1314) Context: 34f437d Context: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/873/ The bump to mono/2017-12 in commit 34f437d included ABI "breakage" in `System.Data.dll` which wasn't *actual* breakage. Update xamarin-android-api-compatibility to so that we don't report warnings for this "breakage." commit 3a35c00 Author: Jonathan Pryor <[email protected]> Date: Thu Feb 15 12:36:24 2018 -0500 Bump to Java.Interop/master/0841c32f Bumps to cecil/master/dfee11e For d15-7 harmonization. commit 92949f4 Author: Jonathan Pryor <[email protected]> Date: Thu Feb 15 12:27:55 2018 -0500 [mono-runtimes] Fix bundle usage Commit 34f437d inadvertently broke mono bundle usage. For example, the [first commit after the mono bump][xa-01be] *should* have taken around 3h to build. Instead, it took nearly 7h, because the bundle wasn't being used, causing the mono runtimes to be rebuilt: [xa-01be]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/874/ Target _BuildUnlessCached needs to be built as output file '…/xamarin-android//bin/Debug/lib/xamarin.android//../../bcl-tests/System.Runtime.CompilerServices.Unsafe.pdb' does not exist. Indeed, `System.Runtime.CompilerServices.Usafe.pdb` *doesn't* exist, nor should it, as it's compiled from IL directly. Fix mono bundle usage by updating `@(_BclTestAssemblyDestination)` to exclude `System.Runtime.CompilerServices.Unsafe.pdb`. This allows the `_BuildUnlessCached` target to properly recognize that all required files *do* exist, thus skipping the mono-runtimes build (as desired). commit 01be8ac Author: Dean Ellis <[email protected]> Date: Thu Feb 15 02:38:56 2018 +0000 [Xamarin.Android.Build.Tasks] Stop designtime designer being deleted. (#1307) Fixes: #1286 We have a number of problems with our DesignTime build system. The main one which this PR addresses is the designer file is deleted by `IncrementalClean` AND `CoreClean`. This them completely messes up the DesignTime system since it can no longer find the file. So what we should be doing is making sure we don't tell the build system about the designer file ;-). We do this by not writing the path to the `$(CleanFile)`. ~~ Some background on the [DesignTime build system][2] ~~ The primary entry point is the `CoreCompile` target, with occasional calls to the `RefreshReferences` target. In theory [`$(DesignTimeBuild)`][1] should be set to `true`; however, this is not always the case which is why we have the `_SetupForDesignTimeBuild` target which hooks into the `CoreCompile` target. Additionally, `$(BuildingProject)` should be False. ([Additional information][2]). However this document is not seem to be 100% accurate since the IDE's (namely Visual Studio) do not always set the required properties. One of the key requirements for design time builds seems to be that they are independent of the main builds. The files it uses should not be removed since the `CoreCompile` target does not seem to be called consistently. For example, if the designer file is removed and the `RefreshReferences` target is called, the design time build may well fail because the targets required to re-generate the designer file are not called. Now for the problem: the `IncrementalClean` target runs between builds. It seems to want to remove files from the previous build. I suspect the purpose is to remove files that are no longer needed. (For example an assembly which is no longer referenced.) The problem is that we have a file (the design time `Resource.designer.cs`) which is not built as part of the normal build. But this file was still being written to `$(CleanFile)` which is the driver for the `IncrementalClean` process. As a result, the file gets removed because its not in the list of current `@(FileWrites)`. Not writing the name of this file to `$(CleanFile)` seems to hide it from `IncrementalClean`. There was also another problem with the `CoreClean` target. This was also removing the designer files. Again this was down to the fact that the file was listed in `$(CleanFile)`. However our older workarounds did not work since they relied on `IncrementalClean` running. For a `Clean` target invocation it does not. Again the solution seems to be Don't Write the file to `$(CleanFile)`, which is counterintuitive since we are told to write all files we generate to that file. [1]: https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md#determining-whether-a-target-is-run-in-a-design-time-build [2]: https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md commit 34f437d Author: Ludovic Henry <[email protected]> Date: Wed Feb 14 14:05:02 2018 -0500 Bump to mono/2017-12/a0af42ab (#1263) Context: https://bugzilla.xamarin.com/show_bug.cgi?id=6339 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=6401 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=8477 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=19503 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=20562 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=31507 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=35661 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=40699 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=45893 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=49308 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=52675 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=53296 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=56003 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=56194 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=57893 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=57938 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=58261 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=58400 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=58411 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=58965 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59080 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59182 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59364 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59393 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59608 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59664 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59881 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59909 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59913 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59916 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59953 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59956 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59967 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60028 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60029 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60115 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60175 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60216 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60224 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60233 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60238 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60245 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60255 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60267 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60288 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60298 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60317 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60340 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60422 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60435 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60505 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60514 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60539 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60545 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60634 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60680 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60771 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60860 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60865 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=60973 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=61002 Bump minimum macOS Mono version to 5.10.0.47. commit f279ad3 Author: Dean Ellis <[email protected]> Date: Wed Feb 14 15:04:45 2018 +0000 [Xamarin.Android.Build.Tasks] GetAndroidDependencies calls _SetLatestTargetFrameworkVersion (#1305) This is a bug in the `GetAndroidDependencies` target: it does not cause `MonoAndroidHelper.RefreshSupportedVersions()` to be invoked. As a result if called directly it will generate a `NullReferenceException` as `MonoAndroidHelper.SupportedVersions` will be `null`. The `GetAndroidDependencies` should thus depend upon the `_SetLatestTargetFrameworkVersion` target. This will initialize `MonoAndroidHelper.SupportedVersions`, and will also resolve the correct `$(TargetFrameworkVersion)` if the user has `$(AndroidUseLatestPlatformSdk)`=True. commit 0dee27d Author: Jonathan Pryor <[email protected]> Date: Wed Feb 14 05:50:23 2018 -0500 [Xamarin.Android.Build.Tasks] Fragments & Shorter acw-map (#1301) Fixes: #1296 Xamarin.Android attempts to expose the Java-based Android API as a ".NET feeling" API. This takes many forms, such as prefixing interface names with `I`, mapping `get` and `set` methods to properties, mapping listener interfaces to events, and PascalCasing method names. This also affects Java package names and C# namespaces. When creating the `.apk` file, we philosophically need to go the opposite direction: PascalCased members need to be mapped to "something appropriate" within Java. For example, many Android Resource ids *must* be all lowercase, and Android doesn't support package names starting with an uppercase letter in all circumstances. At one point, we tried mapping C# PascalCased namespaces to camelCased namespaces, so e.g. `MyExampleNamespace` became the `myExampleNamesapce` Java package within Java Callable Wrappers. This turned out to be a Terrible Mistake, particularly on case-sensitive filesystems, as if casing was *inconsistent* (`MyExampleNamespace` vs `MyExamplenamespace`), files might not be packaged. By Mono for Android 1.0, we settled on just lowercasing the namespace name to produce Java package names within Android Callable Wrappers. This was not without it's own problems; in particular, the assembly name wasn't involved, so if the "same" type (namespace + type) were present in two different assemblies and we needed to generate Android Callable Wrappers, they'd "collide," the build would fail, and we'd have some unhappy customers. This was later addressed in Xamarin.Android 5.1 by changing the Java package name generation algorithm to be an MD5SUM of the assembly name and namespace name, thus allowing types to have assembly identity. (This was not without its own problems.) Then it gets slightly more complicated: Android allows type names to appear in various locations, such as in layout View XML. These don't allow "just" using the type name; the package name is required for types outside the `android.widget` Java package. Initially, we did nothing, so developers had to directly use the Android Callable Wrapper names: <myexamplenamespace.MyCustomCSharpView android:id="@+id/yay_csharp" .../> <fragment android:name="myexamplenamespace.MyCustomCSharpFragment" ... /> With the change in Xamarin.Android 5.1, *this couldn't work*; those types didn't exist anymore. To square this circle, we processed the resource files to "fixup" identifiers and replace them with the actual Android Callable Wrapper names. We'd replace any/all of: MyExampleNamespace.MyCustomCSharpView // Full name MyExampleNamespace.MyCustomCSharpView, MyAssembly // Partial assembly-qualified name MyExampleNamespace.MyCustomCSharpView, MyAssembly, Version=... // Full assembly qualified name myexamplenamespace.MyCustomCSharpView // compatibility name with the appropriate md5'd Android Callable Wrapper name. Brilliant as this was, there was a problem: [Bug #61073][61073]. If the assembly had a wildcard in the assembly version: [61073]: https://bugzilla.xamarin.com/show_bug.cgi?id=61073 [assembly: AssemblyVersion ("1.0.0.*")] then the "Full assembly qualified name" value would change on *every build*, which had numerious unintended knock-on effects. This was fixed in commit e5b1c92, which worked largely by just killing the Full assembly qualified name version entirely. Xamarin.Android doesn't support embedding two different versions of the same assembly, so this was considered to be fine. ...except for one compatibility case: `<fragment/>`s can contain ~arbitrary strings, and we support replacing the entire Full assembly qualified name within them: <fragment android:name="MyExampleNamespace.MyCustomCSharpFragment, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ... /> However, in a post e5b1c92 world, the above now fails to load on the device, because it's *not* being appropriately fixed up! FATAL EXCEPTION: main Process: Mono.Samples.HelloTests, PID: 22977 java.lang.RuntimeException: Unable to start activity ComponentInfo{Mono.Samples.HelloTests/mono.samples.HelloApp}: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment ... Caused by: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment Mono.Samples.Hello.MyFragment, Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: make sure class name exists, is public, and has an empty constructor that is public ... Caused by: java.lang.ClassNotFoundException: Didn't find class "Mono.Samples.Hello.MyFragment, Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" on path: DexPathList[[zip file "/data/app/Mono.Samples.HelloTests-1/base.apk"],nativeLibraryDirectories=[/data/app/Mono.Samples.HelloTests-1/lib/arm64, /system/fake-libs64, /data/app/Mono.Samples.HelloTests-1/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]] ... The problem is that what Android "sees" *should* be <fragment android:name="md5whatever.MyCustomCSharpFragment" ... /> where `md5whatever.MyCustomCSharpFragment` *is* a valid Java type that Android is able to load successfully, but because of e5b1c92 this replacement was removed. The fix: simplify the Full assembly-qualified name case to an already supported example. If the `//fragment/@android:name` value contains a `,`, assume it's an assembly qualified name and compute the Full name from it, by stripping off the comma and everything after it, then use the Full name to lookup the correct Android Callable Wrapper type. commit 5c46ee3 Author: Jonathan Pryor <[email protected]> Date: Wed Feb 14 05:42:22 2018 -0500 [api-xml-adjuster] Fix rebuilds (#1300) Ideally, project rebuilds when nothing has changed should be *fast*. `api-xml-adjuster` isn't: $ time (cd build-tools/api-xml-adjuster ; xbuild) real 2m1.084s user 1m55.916s sys 0m8.853s # and the rebuild! $ time (cd build-tools/api-xml-adjuster ; xbuild) real 2m0.824s user 1m56.140s sys 0m8.600s A *minimum* two minute+ rebuild -- when *nothing* has changed -- is a surefire way to get really annoyed. With diagnostic logging, we start to see the culprit: Target _ClassParse needs to be built as input file '@(ApiFileDefinition -> /Volumes/Seagate4TB/work/xamarin-android/build-tools/api-xml-adjuster/../../src/Mono.Android/Profiles/api-27.params.txt)' does not exist. This in turn causes `class-parse.exe` and `api-xml-adjuster.exe` to be *re-executed* on *every* `android.jar` on *every* build. Fix this by correcting the `//Target/@Inputs` and `//Target/@Outputs` for the `_ClassParse` and `_AdjustApiXml` tasks. After which, no-change rebuilds are *significantly* faster: $ time (cd build-tools/api-xml-adjuster ; xbuild) real 0m5.308s user 0m6.042s sys 0m1.237s commit 20b4190 Author: Peter Collins <[email protected]> Date: Tue Feb 13 12:53:26 2018 -0500 [BCL-Tests] Remove '-s' from _GrantPermissions (#1299) The [semantics of the `$(AdbTarget)` property][adb-target] are the same as the [`adb` Target Device option][adb], which permits any of: [adb-target]: Documentation/build_process.md [adb]: https://developer.android.com/studio/command-line/adb.html#issuingcommands * `-d`: Only attached *device*. * `-e`: Only attached *emulator* * `-s SERIAL_NUMBER`: A specifically named target; needed if there is more than one attached device or emulator. The problem with commit c4e8165 is that it overrode the `$(InstallDependsOnTargets)` property to call the `_GrantPermissions` target, which doesn't properly use `$(AdbTarget)`; it instead *requires* using the `-s` option, which is inconsistent: adb -s $(AdbTarget) shell pm grant ... Remove `-s` from the `adb` invocation so that `$(AdbTarget)` can contain e.g. `-d` or `-e`, as is intended & documented. commit a4ed574 Author: Dean Ellis <[email protected]> Date: Tue Feb 13 16:04:44 2018 +0000 [Xamarin.Android.Build.Tasks] Only report `ndk-bundle` if required. (#1298) We should only list `ndk-bundle` in the `@(AndroidDependencies)` if the user is using AOT or MkBundle. Otherwise we will end up downloading a ton of stuff we don't need. This commit fixes the `CalculateProjectDependencies` to report `ndk-bundle` if needed. It also adds a unit test to make sure it is not included when it shouldn't be. commit cb68bc3 Author: Jonathan Pryor <[email protected]> Date: Mon Feb 12 17:58:59 2018 -0500 Bump to Java.Interop/master/10647a5e (#1295) Fixes the `ObjectDisposedException` during process shutdown described in commit 0a9d164. Moves the `ManagedPeer.Init()` invocation within the `JniRuntime` constructor so that a `NullReferenceException` is avoided. (Instead, a *different*, more meaningful exception should be thrown.) Bumps to cecil/mono-2017-12/1afa0668 for d15-7 harmonization. commit f9b2c97 Author: Dean Ellis <[email protected]> Date: Mon Feb 12 16:20:35 2018 +0000 [Xamarin.Android.Build.Tasks] Add GetAndroidDependencies Target (#1290) Fixes: #1269 This commit adds the `GetAndroidDependencies` target to the `Xamarin.Android.Common.targets`. Its purpose is to examine the various settings in the project and report which Android SDK build-tools, platform-tools, etc. are required. `GetAndroidDependencies` will output an `@(AndroidDependency)` with `%(AndroidDependency.Version)` metadata. `@(AndroidDependency)` will contain `%(Identity)` values of: * `build-tools;{VERSION}`, where `{VERSION}` and `%(Version)` is controlled by the `$(AndroidSdkBuildToolsVersion)` property. * `ndk-bundle`: `%(Version)` is controlled by the `$(AndroidNdkVersion)` property. * `platform-tools`: `%(Version)` is controlled by the `$(AndroidSdkPlatformToolsVersion)` property. * `platforms;android-{API}`, where `{API}` and `%(Version)` is the API level for the `$(TargetFrameworkVersion)` in the `.csproj`. For example, `platforms;android-27` for `$(TargetFrameworkVersion)`=`v7.1`. * `tools`: `%(Version)` is controlled by the `$(AndroidSdkToolsVersion)` property. commit 0d822e2 Author: Jonathan Pryor <[email protected]> Date: Mon Feb 12 10:39:48 2018 -0500 [Xamarin.Android.Build.Tasks] Improve `javac -version` parsing (#1292) The [Ubuntu build][0] is [failing][1]: warning : Failed to get the Java SDK version as it does not appear to contain a valid version number. `javac -version` returned: ```openjdk version "1.8.0_03-Ubuntu" OpenJDK Runtime Environment (build 1.8.0_03-Ubuntu-8u77-b03-3ubuntu3-b03) OpenJDK 64-Bit Server VM (build 25.03-b03, mixed mode) ``` ... Task "AdjustJavacVersionArguments" …/bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android/Xamarin.Android.Common.targets: error : Error executing task AdjustJavacVersionArguments: Required property 'JdkVersion' not set. [0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-linux/779/ [1]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-linux/779/consoleText This was introduced/broken by commit 0e1d1c8, which turned `AdjustJavacVersionArguments.JdkVersion` into a `[Required]` parameter. The value for `AdjustJavacVersionArguments.JdkVersion` comes from the `<ResolveSdks/>` task `JdkVersion` output parameter, which itself comes from parsing `javac -version` output. The problem is that the regex we used to parse the output of `javac -version` wasn't properly parsing the output on Ubuntu: openjdk version "1.8.0_03-Ubuntu" Specifically, the `-Ubuntu` text was causing the regex to not match. Update the regex to be a bit more lenient, enabling it to work with the Ubuntu `javac -version` output, which *should* allow the build to progress further. commit 0114586 Author: Jonathan Peppers <[email protected]> Date: Sun Feb 11 12:53:52 2018 -0600 [build] fix api-xml-adjuster.targets on Windows (#1291) Since 7d705bf, the Windows builds on VSTS have seemed to be failing. I tested this locally, and noticed the use of command line arguments such as: -parameter-names='%(SomeVariable)' Unfortunately, this isn't working on Windows due to the single quote. It is more appropriately expressed as: -parameter-names="%(SomeVariable)" This isn't very pretty, but it should work on all platforms. I also fixed all the tabs I saw in this file--in favor of spaces, and fixed other XML code conventions. I will now return to my regularly scheduled baby duty.
Merged
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes: #1296
Xamarin.Android attempts to expose the Java-based Android API as a
".NET feeling" API. This takes many forms, such as prefixing interface
names with
I
, mappingget
andset
methods to properties, mappinglistener interfaces to events, and PascalCasing method names.
This also affects Java package names and C# namespaces.
When creating the
.apk
file, we philosophically need to go theopposite direction: PascalCased members need to be mapped to
"something appropriate" within Java. For example, many Android
Resource ids must be all lowercase, and Android doesn't support
package names starting with an uppercase letter in all circumstances.
At one point, we tried mapping C# PascalCased namespaces to camelCased
namespaces, so e.g.
MyExampleNamespace
became themyExampleNamesapce
Java package within Java Callable Wrappers.This turned out to be a Terrible Mistake, particularly on
case-sensitive filesystems, as if casing was inconsistent
(
MyExampleNamespace
vsMyExamplenamespace
), files might not bepackaged.
By Mono for Android 1.0, we settled on just lowercasing the namespace
name to produce Java package names within Android Callable Wrappers.
This was not without it's own problems; in particular, the assembly
name wasn't involved, so if the "same" type (namespace + type) were
present in two different assemblies and we needed to generate Android
Callable Wrappers, they'd "collide," the build would fail, and we'd
have some unhappy customers.
This was later addressed in Xamarin.Android 5.1 by changing the Java
package name generation algorithm to be an MD5SUM of the assembly name
and namespace name, thus allowing types to have assembly identity.
(This was not without its own problems.)
Then it gets slightly more complicated: Android allows type names to
appear in various locations, such as in layout View XML. These don't
allow "just" using the type name; the package name is required for
types outside the
android.widget
Java package.Initially, we did nothing, so developers had to directly use the
Android Callable Wrapper names:
With the change in Xamarin.Android 5.1, this couldn't work; those
types didn't exist anymore.
To square this circle, we processed the resource files to "fixup"
identifiers and replace them with the actual Android Callable Wrapper
names. We'd replace any/all of:
with the appropriate md5'd Android Callable Wrapper name.
Brilliant as this was, there was a problem: Bug #61073.
If the assembly had a wildcard in the assembly version:
then the "Full assembly qualified name" value would change on every
build, which had numerious unintended knock-on effects.
This was fixed in commit e5b1c92, which worked largely by just
killing the Full assembly qualified name version entirely.
Xamarin.Android doesn't support embedding two different versions of
the same assembly, so this was considered to be fine.
...except for one compatibility case:
<fragment/>
s can contain~arbitrary strings, and we support replacing the entire Full assembly
qualified name within them:
However, in a post e5b1c92 world, the above now fails to load on the
device, because it's not being appropriately fixed up!
The problem is that what Android "sees" should be
where
md5whatever.MyCustomCSharpFragment
is a valid Java type thatAndroid is able to load successfully, but because of e5b1c92 this
replacement was removed.
The fix: simplify the Full assembly-qualified name case to an already
supported example. If the
//fragment/@android:name
value contains a,
, assume it's an assembly qualified name and compute the Full namefrom it, by stripping off the comma and everything after it, then use
the Full name to lookup the correct Android Callable Wrapper type.