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
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 c4e81655 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.
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.
Fixes the `ObjectDisposedException` during process shutdown described
in commit 0a9d1641.
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.
Fixes: https://github.com/xamarin/xamarin-android/issues/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.
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 0e1d1c8a, 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.
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.
Support generating CodeBehind files for `.axml` layout files. This
removes the need to call `FindViewById<T>()` manually, as properties
generated into the CodeBehind file will call it instead.
The CodeBehind files are generated for all `.axml` files with a build
action of `@(AndroidResource)` *and* contain an XML namespace to
`http://schemas.android.com/tools` and a `tools:class` attribute
that contains the name of the `partial class` to generate:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:tools="http://schemas.xamarin.com/android/tools"
tools:class="UnnamedProject.MainActivity">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>
The generated CodeBehind partial class will use the value of the
`//@tools:class` attribute, and will contain a property for each
element with an `//@android:id` attribute. The `//@android:id`
attribute is the name of a generated field, while the containing
element name is the type of the property.
The above XML fragment would partially produce:
partial class MainActivity {
// Call instead of `SetContentView()`
private void InitializeContentView ();
// Called if `myButton` can't be found
partial void OnLayoutViewNotFound<T> (int resourceId, ref T type)
where T : global::Android.Views.View;
// One property per //@android:id
// Throws InvalidOperationException if it can't be found
public Button myButton { get; }
}
This allows replacing the current code pattern of:
SetContentView (Resource.Layout.NameOfLayoutFilename);
var button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate {
};
and instead rely on the CodeBehind properties:
InitializeContentView ();
myButton.Click += delegate {
};
There are two other requirements to make this work:
1. All declarations of the class specified by the `//@tools:class`
attribute must be `partial` classes, otherwise a CS0260 error
will be produced at build time.
2. `InitializeContentView()` must be called instead of
`SetContentView()`. `InitializeContentView()` itself calls
`SetContentView()`, providing the `@(AndroidResource)` filename
as the layout to use.
This feature was originally prototyped by @grendello.
The following is a sample of the kind of code which will be
generated by this new system:
namespace UnnamedProject {
using System;
using Android.App;
using Android.Widget;
using Android.Views;
using Android.OS;
// Generated from layout file 'Resources/layout/Main.axml'
public partial class MainActivity {
private Func<Button> @__myButtonFunc;
private Button @__myButton;
partial void OnLayoutViewNotFound<T> (int resourceId, ref T type)
where T : global::Android.Views.View;
public Button myButton {
get {
if (@__myButtonFunc == null) {
@__myButtonFunc = this.@__Create_myButton;
}
return this.@__EnsureView<Button>(this.@__myButtonFunc, ref this.@__myButton);
}
}
private void InitializeContentView() {
this.SetContentView(Resource.Layout.Main);
}
private T @__FindView<T>(global::Android.Views.View parentView, int resourceId)
where T : global::Android.Views.View
{
T view = parentView.FindViewById<T>(resourceId);
if ((view == null)) {
this.OnLayoutViewNotFound(resourceId, ref view);
}
if ((view != null)) {
return view;
}
throw new System.InvalidOperationException($"View not found (ID: {resourceId})");
}
private T @__FindView<T>(global::Android.App.Activity parentView, int resourceId)
where T : global::Android.Views.View
{
T view = parentView.FindViewById<T>(resourceId);
if ((view == null)) {
this.OnLayoutViewNotFound(resourceId, ref view);
}
if ((view != null)) {
return view;
}
throw new System.InvalidOperationException($"View not found (ID: {resourceId})");
}
private T @__FindView<T>(global::Android.App.Fragment parentView, int resourceId)
where T : global::Android.Views.View
{
return this.@__FindView<T>(parentView.Activity, resourceId);
}
private T @__EnsureView<T>(System.Func<T> creator, ref T field)
where T : class
{
if ((field != null)) {
return field;
}
if ((creator == null)) {
throw new System.ArgumentNullException(nameof (creator));
}
field = creator();
return field;
}
private Button @__Create_myButton() {
return this.@__FindView<Button>(this, Resource.Id.myButton);
}
}
}
Our components team currently have to go through lots of hoops to
include `.aar` files in the build system: since we are not allowed to
ship some of the google `.aar` files within the Nuget packages, the
`.aar` files instead need to be downloaded on demand. To work within
the current build system these `.aar` files then need to be unpacked,
restructured, compressed and included in the Nuget assembly as an
`@(EmbeddedResource)`. This requires updating the assembly after it
has been downloaded from nuget.
With the introduction of the `@(AndroidAarLibrary)` build action we
can remove the rebuilding of the Nuget assembly completely. The new
system will still download the required `.aar` files on demand. But
instead of repacking them into the `.dll`, the Nuget `.targets` file
will simply add these `.aar` files to the `@(AndroidAarLibrary)`
ItemGroup. These Items will then be picked up by the
`<ResolveLibraryProjectImports/>` task. They will then be extracted
nto the `$(IntermediateOutputDir)`. From there the resources, assets
and `.jar` files in the `.aar` will then be included in the build
system of the application.
Part of the XA build process is download and installation of Android SDK, NDK as
well as creation of native compilation toolchains. However, it appears that at
some point we regressed and stopped performing those tasks and, thus, the builds
fail when adjusting API description files with api-xml-adjuster since at this
point no SDK, NDK or toolchains are found. The download and installation of
those components is handled by the android-toolchain project which is dependent
upon by several other projects in XA that require the SDK and the NDK to be
present. android-xml-adjuster needs them as well but it hasn't dependent on
android-toolchain until this commit which adds a reference to the toolchain
project and fixes the build.
The [macOS+xbuild build][0] is [broken][1]:
obj/Debug/android-10/mcw/Android.Content.ContentProvider.cs(282,84): error CS0234: The type or namespace name 'Collections' does not exist in the namespace 'Android.System' (are you missing an assembly reference?)
...and 1271 other similar errors...
[0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/855/
[1]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/855/consoleText
The apparent cause is 7d705bf7, which updated the build process to
generate `api.xml` files from `android-*.jar` at build time, instead
of requiring pre-generated paths within `src/Mono.Android/Profiles`,
as the `api-merge.exe` invocation was altered.
The *actual* cause is a latent bug in `api-merge.exe`: when using
`api-merge FILES --last-description=FILE`, `FILE` is incorrectly
compared with the list of `FILES`. When building with `xbuild`,
the `@(_AndroidProfile)` item group contains *full path names*, while
the `--last-description` option is a relative path:
Executing: mono ../../bin/BuildDebug/api-merge.exe -o "obj/Debug/android-10/mcw/api.xml" \
-s '../../bin/BuildDebug/api/api-*.xml.in' \
…/xamarin-android/bin/BuildDebug/api/api-10.xml.in \
...
--last-description=../../bin/BuildDebug/api/api-10.xml.in
Because `api-merge` didn't normalize the path names, it attempted to
compare `…/xamarin-android/bin/BuildDebug/api/api-10.xml.in` to
`../../bin/BuildDebug/api/api-10.xml.in`, which *always failed*.
Consequently, the resulting `obj/Debug/android-10/mcw/api.xml` file
contained *all* API levels, including the `android.system` package
(introduced in API-21), while not containing the namespace renaming
logic to map `android.system` to `Android.Systems`.
The result is that e.g.
obj/Debug/android-10/mcw/Android.Content.ContentProvider.cs`
contained "innocuous" identifiers such as
`System.Collections.Generic.IList<Android.Content.ContentProviderOperation>`
which were being incorrectly resolved to
`Android.System.Collections.Generic.IList<Android.Content.ContentProviderOperation>`,
which doesn't exist.
Fix `api-merge` so that it compares *full paths* to
`api-merge --last-description=FILE`, allowing the `api-merge` command
to properly stop merging APIs once it's hit (in this case)
`api-10.xml.in`.
`@(JavaSourceJar)` works like `@(JavaDocJar)`, but in slightly more
complicated way.
`@(JavaDocJar)` only extracts the `.jar` contents and passes
`index.html` as `@(JavaDocIndex)`, while `@(JavaSourceJar)` extracts
the `.jar`, then runs `javadoc` to generate JavaDoc documentation,
then passes the generated `index.html` as `@(JavaDocIndex)`.
This fix involves `@(JavaDocIndex)` path fixes that incorrectly
passed file name as directory name (regression from
[Java.Interop/806082f][ji-80]), as well as `javadoc-to-mdoc` fix to
not try to substring beyond string length within `HtmlLoader` to
detect documentation type.
[ji-80]: https://github.com/xamarin/Java.Interop/commit/806082f
XA's Makefile exports the OS environment variable set to output of the `uname
-s` command which returns the operating system's name. On macOS it will return
`Darwin`, on Linux `Linux` etc. MSBuild (the build system, not the command)
defines a standard property `$(OS)` which names the operating system kind -
`Windows_NT` on Windows and `Unix` on *nix systems.
Our project and target files (also a large set of them from e.g. Mono) use the
property to check whether they are running on Unix or Windows and they rely on
the property's value to be set correctly to make the right decisions.
MSBuild (the system) supports setting of properties from the command line but it
also takes their values from the process environment. However, it appears
there's a major difference between Mono's xbuild (which is used by default by
XA) and msbuild in that xbuild "protects" the `OS` property by NOT using the
OS environment property to set its value, while msbuild sets the property from
the environment variable. This results in the property to have the value of
`Darwin` on macOS and `Linux` on Linux and it happens to work (more or less)
correctly on macOS because we do check for `'$(OS)' == 'Darwin' or '$(OS)' ==
'Unix')` in a few places while we do NOT check for `'$(OS)' == 'Linux')`
anywhere. All this together breaks XA build on Linux in a few places.
This patch makes the msbuild build (`make MSBUILD=msbuild`) to work on Linux by
renaming the Make `$(OS)` variable to `$(CURRENT_OS)` and thus "protecting" the
standard value of the `$(OS)` property during the build.
(The extension is a lie!)
Commit 6fd330df lists the ideal build scenario:
> Load Xamarin.Android.sln into your IDE and Build the project.
We're not there yet.
What *prevents* that? In part, the *existence* of `.mdproj` files.
While `msbuild`-at-the-command-line doesn't care about project
extensions, *Visual Studio **does***. Thus, the presence of `.mdproj`
files results in Visual Studio showing an "(incompatible)" message
next to the project, and it refuses to load the project.
Improve things by renaming all `.mdproj` files to `.csproj` files, and
then adding a `$(TargetFrameworkVersion)` value to each of them (as
Visual Studio requires `$(TargetFrameworkVersion)` in order to load
the project file).
With these two changes -- change extension, set
`$(TargetFrameworkVersion)` -- Visual Studo 2017 will load all of the
projects in the solution without showing the "(incompatible)" message.
Note: Visual Studio caches project state within the `.vs` directory
(stored in the toplevel checkout directory). If `Xamarin.Android.sln`
has been previously loaded into Visual Studio, you will need to do one
of the following to allow Visual Studio to load the projects:
1. Right-click the project within the Solution Explorer, then click
Reload. Repeat for all such projects. Or,
2. Exit Visual Studio, and delete the `.vs` folder. When Visual
Studio next loads the project, the projects will load.
[Xamarin.Android.Build.Tasks] LogicalName & __AndroidLibraryProjects__
Fixes: https://github.com/xamarin/xamarin-android/issues/1235
There seems to be a [bug in msbuild][1] where if you create an item
inside a task and the task is skipped, the metadata is not created
for the item.
We get into a situation where `__AndroidLibraryProjects__.zip`
does not contain the correct `%(EmbededResource.LogicalName)` value.
As a result the extraction process cannot find the resource, and
builds fail.
Fix this by splitting out the code that created the zip file into a
new `_CreateManagedLibraryResourceArchive` target. This allows us to
skip this new target if needed. However the
`_AddLibraryProjectsEmbeddedResourceToProject` target which creates
the item can now run for every build. This will ensure that the
metadata is always created.
Add a unit test.
[1]: https://social.msdn.microsoft.com/Forums/netframework/en-US/259271d8-a3fc-4a9b-9e3a-fecad8f6f63f/potential-bug-with-createitem-task-and-additionalmetadata?forum=msbuild
Mono supports an [AOT profiler][aotp]: when enabled, mono will
generate a file containing the methods that were encountered while
the AOT profiler is enabled, usually during the lifetime of the
process. AOT profiler output can then be fed into the AOT compiler,
allowing *selective AOT of assemblies*: instead of AOT'ing
*everything*, only the specified methods would be AOT'd. This would
hopefully allow for smaller `.apk` files containing AOT output.
[aotp]: 4a99504591/man/mono-profilers.1 (L325-L330)
The question: How do we make use of this functionality?
We don't have an answer. We need to start *experimenting* to
determine an answer.
To help support that experimentation, set things up so that the AOT
profiler can be used:
* *Build* and package the AOT profiler, contained within the
`libmono-profiler-aot.so` native library. This was done in
commit 37119924.
* Allow the `.apk` to contain `libmono-profiler-aot.so`.
* Profile the application.
* Grab the profiler output.
Allow the `$(AndroidEmbedProfilers)` MSBuild property to use the
value `aot` so that the `libmono-profiler-aot.so` profiling library
will be embedded into the `.apk` file:
msbuild /p:AndroidEmbedProfilers=aot TheApp.csproj /t:SignAndroidPackage
Once the `.apk` contains `libmono-profiler-aot.so`, then the profiler
can be used by setting the `debug.mono.profile` system property:
adb shell setprop debug.mono.profile aot
When the application is next launched, the AOT profiler will be used.
If (see below) AOT output is produced, it can be extracted from the
device by using the `adb pull` command.
There are four known issues:
1. The *filename* of the produced file, which changes in PR #1254.
2. The *path* of the produced file, which will be in the
`.__override__` directory. See also [DevelopmentTips.md][update].
3. AOT profiler output isn't constantly written to. To ensure that
*all* AOT profiler output is written to the output file, the
process must currently exit. This can be done by calling
`Environment.Exit()` at some point within the application.
4. `Java.Interop` doesn't support cleanly shutting down.
[update]: a102708499/Documentation/DevelopmentTips.md (update-directory)
Specifically, if you *do* call `Environment.Exit()`, process exit
is not cleanly performed:
[ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'The ThreadLocal object has been disposed.'.
at System.Threading.ThreadLocal`1[T].GetValueSlow ()
at System.Threading.ThreadLocal`1[T].get_Value ()
at Java.Interop.JniEnvironment.get_CurrentInfo ()
at Java.Interop.JniEnvironment.get_Runtime ()
at Java.Interop.JniObjectReference.Dispose (Java.Interop.JniObjectReference& reference)
at Java.Interop.JniRuntime.Dispose (System.Boolean disposing)
at Java.Interop.JniRuntime.Finalize ()
As such, AOT profiling *does not work*.
However, we want to *permit enabling AOT profiling* so that we can
more easily test and get things to a working state.
Commit 20123b5 broke the build system on Windows. The
condition on `_RegisterAndroidFilesWithFileWrites` was
incorrect. `$(_IsRunningXBuild)` can be empty when running
under MSBuild. As a result the condition will always
result in the target being skipped.
This commit fixes the condition to that it will run
correctly under msbuild and is skipped on xbuild.
Fixes: https://github.com/xamarin/xamarin-android/issues/1164
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=61108
The `IncrementalClean` target basically deletes a ton of stuff if
it's not in the `@(FileWrites)` group. Under certain conditons this
include assemblies in `$(OutDir)`. It mainly effects projects which
use a shared `$(OutDir)`.
So if a third level dependency is copied to the `$(OutDir)` but is
not referenced by the main app project we end up with the
`IncrementalClean` target deleting the file. This then breaks
packaging since we expect the file to exist.
This causes problems with TFS because it seems to ALWAYS use
a shared `$(OutDir)`.
To work around this problem we just need to tell the
`IncrementalClean` target to ignore any dll in the `$(OutDir)`. Since
we already have a target in place to handle this we can just expand
the list of files it should be ignoring.
GCC has recently added flags to mitigate effects of the Spectre CPU bug. The
flags enable compiler to replace certain processor instructions vulnerable to
the attack (function return, indirect branches - function calls, conditional
branching etc) by instructions which invalidate CPU's branch prediction cache
and thus mitigate the threat.
Fixes: https://github.com/xamarin/xamarin-android/issues/1248
JDK 9 doesn't currently provide a robust and reliable user
experience. Until we can provide a reliable experience, we
should "fail early".
We already have a property for `$(LatestSupportedJavaVersion)`
which currently cannot be overridden. We also currently emit
a warning when the java version is greater than this property.
However with JDK 9 it seems a warning is not enough. So we
should change the warning to an error. We also need to make
`$(LatestSupportedJavaVersion)` writable so that it can be
overridden for local testing from the command line via:
msbuild /p:LatestSupportedJavaVersion=9.0.0 /t:SignAndroidPackage TheApp.csproj
When merging we process several API description files, each for a separate
platform. The resulting file currently carries the *first* platform level in its
`<api platform="">` root element attribute. This is a subtle issue that may
cause problems when applying fixups from metadata (for instance) as the
`api-since` and `api-until` attributes in fixups may apply to incorrect sets of
API members.
Fix the issue by putting the latest API description platform level as obtained
from the files provided to api-merge (the files are sorted in platform level
ascending order)
There were multiple occurences in the past, where having host mono
binary in the bundle would be handy.
Because we are extending the bundle with aot profiler, we can add mono
binary as well and bump bundle version just once.
The aot profiler will be used to generate aot profiles for "profiled"
AOT builds. Note that we don't have an infrastructure for "profiled"
AOT builds yet.
I plan to test the "profiled" AOT to have an idea what apk sizes and
startup times to expect.
Fixes: https://github.com/xamarin/xamarin-android/issues/1234
The following user code:
[Activity (ConfigurationChanges=ConfigChanges.SmallestScreenSize)]
partial class MyActivity : Activity {
}
was effectively a no-op, as the check for
`ConfigChanges.SmallestScreenSize` was instead checking for
`ConfigChanges.ScreenSize`; `ConfigChanges.SmallestScreenSize` would
*never* be interpreted.
Turns out it was from [monodroid/c2831532][0], a long-standing issue.
[0]: https://github.com/xamarin/monodroid/commit/c28315322e
Start using complete Java.Interop, ie. `Debug` and `Release`
configurations instead of `XAIntegrationDebug` and
`XAIntegrationRelease`.
Add Java.Interop java sources to the list of sources to build
mono.android.jar. This is needed for `ManagedPeer` and other classes
with java counterparts.
Few updates to distinguish between `Android.Runtime.JavaObject` and
`Java.Interop.JavaObject`.
Added System.Collections reference is for `List<JniSurfacedPeerInfo>`
return type in `AndroidValueManager`.
The [`msbuild`-based Jenkins job][jenkins-msbuild] job has been
failing a lot recently:
[jenkins-msbuild]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-msbuild/
error MSB3644: The reference assemblies for framework "MonoAndroid,Version=v1.0" were not found.
The cause of the error is that *when there is no prebuilt mono runtime
to download*, this file does not exist:
bin/Debug/lib/xamarin.android/xbuild-frameworks/MonoAndroid/v1.0/RedistList/FrameworkList.xml
The above file is created by the
`build-tools/scripts/mono-runtimes.mdproj` build, and
`mono-runtimes.mdproj` *is not being built*. Without a mono build,
there is no `MonoAndroid/v1.0` framework, and everything fails.
I don't know when this actually broke, or what change is responsible.
(It works with `xbuild`!)
Attempt to improve reliability by adding `mono-runtimes.mdproj` to
`$(MSBUILD_PREPARE_PROJS)`. This will cause the `msbuild`-based build
to explicitly build `mono-runtimes.mdproj` *before* attempting to
build `Xamarin.Android.Build.Tasks.csproj` or `Xamarin.Android.sln`.
Fixes: https://github.com/xamarin/xamarin-android/issues/1201
It turned out that the criminal who generated `_Color` and
`ColorObject` as internal was *metadata fixup*, not generator itself.
It was buried in thousands of lines of `src/Mono.Android/metadata`.
`Color` is absolutely a technical debt that Xamarin.Android should
clean up and provide every related API in int properties and constants,
but so far add a workaround by renaming `Color` to `ColorObject` class.
Binding `android.graphics.Color` allows all methods which use it to
be bound, which in turn allows binding some previously unbound types.
For example [`android.app.WallpaperManager.OnColorsChangedListener`][0]
is now bound as `Android.App.WallpaperManager.IOnColorsChangedListener`.
[0]: https://developer.android.com/reference/android/app/WallpaperManager.OnColorsChangedListener.html
Once again we hit an issue where the `apksigner.bat` file provided
with android build-tools was not functioning correctly. So like
we did with `dx.bat` and other tooling we should switch to using
the `apksigner.jar` file directly.
Additionally JDK 9 has removed support for the `java.ext.dirs`, which
all versions of the `apksigner.bat` use. As a result this tool will
not work with JDK 9. So its best to remove it now.
We have existing unit tests which check that the Apk is being
signed correctly. So not additional tests are required.
Context: https://github.com/xamarin/xamarin-android/pull/1211#issuecomment-359177901
Context: https://github.com/xamarin/xamarin-android/pull/1211#issuecomment-359179075
What *should* happen when a portion of a build fails?
That's not entirely rhetorical: the *entire* build should fail.
What *does* happen when a portion of a build fails?
Unfortunately that's also not rhetorical: the build continues!
(Say what?!)
Case in point: [PR #1211 build 2373][pr-2373], which experienced a
failure in the mono build:
[pr-2373]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-pr-builder/2373/
MONO_PATH="./../../class/lib/build:$MONO_PATH" ... -R ../../../class/lib/monodroid/nunitlite.dll ...
error CS0009: Metadata file '/Users/builder/jenkins/workspace/xamarin-android-pr-builder/xamarin-android/external/mono/mcs/class/lib/monodroid/nunitlite.dll' could not be opened -- PE image doesn't contain managed metadata.
*But the error was ignored*, and the build continued, resulting in the
"final" errors (among others)
System.Net/NetworkChangeTest.cs(5,7): error CS0246: The type or namespace name `NUnit' could not be found. Are you missing an assembly reference?
**This is *madness*.** The first error *should* have stopped the
build. The build *wasn't* stopped, meaning that it continued -- with
an "unstable" tree state -- resulting in "bizarre" build errors
*later*. In particular, `Xamarin.Android.NUniteLite.dll` wasn't built
in the *Debug* configuration because the *mono* build failed for the
Debug configuration, but everything "worked" in Release.
The fundamental cause of this madness? Makefile rules such as
`make leeroy-all`, which *effectively* are:
tools/scripts/xabuild Xamarin.Android.sln /p:Configuration=Debug ; \
tools/scripts/xabuild Xamarin.Android.sln /p:Configuration=Release; \
*Because* of the `;` separating the commands, any errors from the
first command are *ignored*, resulting in the tearing out of my hair
when everything goes "weird".
Review the Makefile targets in `Makefile` and
`build-tools/scripts/BuildEverything.mk` and replace `;` with
`|| exit 1` when the command should have fatal errors. This *should*
cause the build to fail the *first* time an error is encountered,
instead of continuing on its merry way to die horribly later.
We have a VSTS+macOS build machine which has JDK 9 as the default JDK,
thus causing *all* xamarin-android builds to fail, as `gradlew` and
JDK 9 don't *directly* mix:
Executing: ./gradlew assembleDebug --stacktrace
...
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':library'.
...
Caused by: org.gradle.internal.event.ListenerNotificationException:
Failed to notify project evaluation listener.
...
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
...
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
When using JDK 9, `gradlew` fails because *something* within it
attempts to use the deprecated type
`javax.xml.bind.annotation.XmlSchema`, and JDK 9 doesn't provide
deprecated modules in the default `$CLASSPATH`.
Knowing that the VSTS machine *also* has JDK 8 installed, we've tried
to "filter out" JDK 9 so that it wouldn't be used; see e.g. a3c43584.
Unfortunately that doesn't work, because on macOS the default JDK used
is [always the JDK with the highest version number][macOS-jdk], and
this can't be easily changed system-wide because changing this
behavior requires "removing" a `Info.plist` file to prevent the JDK
from being "seen" by `/usr/bin/java`:
[macOS-jdk]: https://stackoverflow.com/a/44169445
# Don't use JDK 9 by default on macOS:
$ cd /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents
$ mv Info.plist Info.plist.disabled
(Renaming `Info.plist.disabled` to `Info.plist` will restore JDK 9 as
the default JDK on the machine.)
A "proper" fix would presumably involve using and exporting
`$JAVA_HOME` *everywhere*, which isn't currently the case.
[This is something that *should* be explored.][xa-1213]
[xa-1213]: https://github.com/xamarin/xamarin-android/issues/1213
In the meantime, a question: *Can* we build with JDK 9?
*Is it even possible in the first place*?
Turns out, *yes*, it *is* possible. The above `gradlew` error can be
fixed by providing the (new-in-JDK9) `--add-modules` option, so that
the `java.xml.bind` module is accessible:
$ ANDROID_HOME=... JAVA_OPTS="--add-modules java.xml.bind" ./gradlew assembleDebug --stacktrace --no-daemon
# ...works!
Unfortunately, *other* parts xamarin-android get in the way, e.g. the
`<ResolveSdks/>` task doesn't correctly parse the version number out
of `java -version`, and JDK 9 `javac` requires `-source` and `-target`
when `-bootclasspath` is used.
Update the build system and tests so that things *can* be built under
JDK 9.
Additionally, cleanup the internal build system a bit: instead of
having `javac` and `jar` calls strewn throughout *7* different
projects -- all of which would need to be updated to provide usable
`javac -source` and `javac -target` values (JDK 9 doesn't support
`-target 1.6` anymore!), introduce `build-tools\scripts\Jar.targets`
and the new `BuildTestJarFile` target. This takes all
`@(TestJarEntry)` files, compiles them with `javac`, and `jar`s the
compiled files into `%(TestJarEntry.OutputFile)`.
**Note**: This does ***NOT*** mean that building and/or using JDK 9
will be commercially supported in *any* way. (It might not even work!)
We need to add an additional conditional Import for the
Installer target. This will allow commerial users to
use the following targets.
GetAndroidDependencies
InstallAndroidDependencies
Reproduction:
2>C:\Users\dougl\source\repos\App75\App75\App75.Android\App75.Android.csproj : warning XA0105: The $(TargetFrameworkVersion) for FormsViewGroup.dll (vv8.0) is greater than the $(TargetFrameworkVersion) for your project (v7.1). You need to increase the $(TargetFrameworkVersion) for your project.
2>C:\Users\dougl\source\repos\App75\App75\App75.Android\App75.Android.csproj : warning XA0105: The $(TargetFrameworkVersion) for Xamarin.Forms.Platform.Android.dll (vv8.0) is greater than the $(TargetFrameworkVersion) for your project (v7.1). You need to increase the $(TargetFrameworkVersion) for your project.
2>C:\Users\dougl\source\repos\App75\App75\App75.Android\App75.Android.csproj : warning XA0105: The $(TargetFrameworkVersion) for Xamarin.Forms.Platform.dll (vv8.0) is greater than the $(TargetFrameworkVersion) for your project (v7.1). You need to increase the $(TargetFrameworkVersion) for your project.
Fixes: https://github.com/xamarin/xamarin-android/issues/1165
Add the following overridable properties:
* `$(AndroidSdkPlatformToolsVersion)`: The preferred/default
version of the Android SDK `platform-tools` package.
* `$(AndroidSdkToolsVersion)`: The preferred/default version
of the Android SDK `tools` package.
* `$(AndroidNdkVersion)`: The preferred/default version of the
Android NDK.
The Visual Studio (+ for Mac) SDK Manager will eventually use these
values to determine which package versions to install.
Context: https://github.com/xamarin/xamarin-android/issues/1089
Context: https://github.com/xamarin/xamarin-android/pull/1078
Context: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/823/
Commit 8ff139f9 [broke][0] the [build][1], in a minor way:
[0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/824/console
[1]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android/824/
# reading extras from: inter-api-extra-v2.3-v4.0.3.txt
mono --debug /Users/builder/jenkins/workspace/xamarin-android/xamarin-android/bin/BuildDebug/mono-api-html.exe "inter-apis/v2.3/Mono.Android.xml" "inter-apis/v4.0.3/Mono.Android.xml" --ignore-changes-parameter-names --ignore-changes-virtual --ignore-changes-property-setters --ignore-nonbreaking
<h1>### API BREAK BETWEEN v2.3 and v4.0.3</h1>
...
<h2>Namespace Android.Text</h2>
<!-- start type ClipboardManager --> <div>
<h3>Type Changed: Android.Text.ClipboardManager</h3>
<p>Modified properties:</p>
<pre>
<div data-is-breaking> public <span class='added added-breaking-inline'>abstract</span> bool HasText { get; }
</div><div data-is-breaking> public <span class='added added-breaking-inline'>abstract</span> Java.Lang.ICharSequence TextFormatted { get; set; }
</div></pre>
...
These are "acceptable" API breakage for now, previously not reported
[because the test was broken][6dfb]. The test was fixed on
xamarin-android-api-compatibility/master, but we haven't been able to
merge to that commit yet (PR #1078).
[6dfb]: 6dfba92e57
Unfortunately, 8ff139f9 included a bump to
xamarin-android-api-compatibility/master, thus introducing the
"UNSTABLE" breakage that PR #1078 encountered.
For now -- until we can properly fix things -- bump to
xamarin-android-api-compatibility/d15-6, which *lacks* the test fixes
on master, and thus will allow the API compatibility checks to pass.
Fixes: https://github.com/xamarin/xamarin-android/issues/1170
Context: a301764a88
Bumps to xamarin-android-api-compatibility/master/6874e3f3
Xamarin.Android 8.1 (d15-5) provides an `Android.Widget.ChoiceMode`
enum type in API-10+, used by the
`Android.Widget.ListView.ChoiceMode` property.
`ChoiceMode` contains the `android.widget.ListView.CHOICE_MODE_*`
constants from API-10, which were moved to
`android.widget.AbsListView` in API-15.
Xamarin.Android 8.2 (d15-6) inadvertently *removed* the
`Android.Widget.ChoiceMode` enum, because
[xamarin-android/a301764a][xa-a301764a] altered the mapping of the
`CHOICE_MODE` constants so that they were only bound into the
`Android.Widget.ChoiceMode` enum for API-15+.
[xa-a301764a]: a301764a88
Removing the `ChoiceMode` enum in turn caused the
`ListView.ChoiceMode` property to be removed, as the
`ListView.getChoiceMode()` and `ListView.setChoiceMode()` methods
expected the (now nonexistent) `ChoiceMode` enum type.
Update `map.csv` so that the `CHOICE_MODE_*` values are mapped to the
`ChoiceMode` enum in API-10+, not API-15+, which restores the
`Android.Widget.ChoiceMode` enum type and the `ListView.ChoiceMode`
property.