Граф коммитов

12 Коммитов

Автор SHA1 Сообщение Дата
Marek Habersack 0f463a1b42
[monodroid] Fix `mono_log_mask` parsing and add property docs (#6494)
From the "how did I miss it?!" department.

The main purpose of this commit is to fix parsing of the
`mono_log_mask` component of the `debug.mono.log` property.
The component is set to a list of Mono logging categories (e.g. `asm`,
`gc` or `dll`) which, so far, was supposed to be a comma-separated
list.

However… `debug.mono.log` *itself* uses commas to separate components,
so using the following:

	$ adb shell setprop debug.mono.log mono_log_mask=asm,gc,dll

would *not* set the `$MONO_LOG_MASK` environment variable to the
expected value of `asm,gc,dll`, but would instead it would end up being
just `asm`, as the other values would be considered to be
`debug.mono.log` components instead.

To fix this, change the `mono_log_mask` separator to `:`, so that
we would now use:

	$ adb shell setprop debug.mono.log mono_log_mask=asm:gc:dll

Additionally, document all the `debug.mono.*` properties and remove
the `DEBUG_MONO_GDBPORT_PROPERTY` constant, since it's not used
anywhere.

Also, when `assembly` or `gc` logging is enabled, we now set the Mono
tracing level to `info` instead of the default `error`.  This makes
tracking assembly loader and garbage collector issues easier by
showing more info from the Mono runtime, not just from Xamarin.Android.
2021-11-18 12:22:32 -05:00
Marek Habersack c92702619f
[monodroid] Embedded assemblies store (#6311)
What do we want?  Faster (Release) App Startup!

How do we get that?  Assembly Stores!

"In the beginning", assemblies were stored in the `assemblies`
directory within the `.apk`.  App startup would open the `.apk`,
traverse all entries within the `.apk` looking for `assemblies/*.dll`,
`assemblies/*.dll.config`, and `assemblies/*.pdb` files.  When a
"supported" `assemblies/*` entry was encountered, the entry would be
**mmap**(2)'d so that it could be used; see also commit c1956835bd.

Of particular note is:

 1. The need to enumerate *all* entries within the `.apk`, as there
    is no guarantee of entry ordering, and

 2. The need for *N* `mmap()` invocations, one per assembly included
    in the app, *plus* additional `mmap()` invocations for the `.pdb`
    and `.dll.config` files, if present.

    Useful contextual note: a "modern" AndroidX-using app could pull
    in dozens to over 200 assemblies without really trying.

    There will be *lots* of `mmap()` invocations.

Instead of adding (compressed! d236af54) data for each assembly
separately, instead add a small set of "Assembly Store" files which
contain the assembly & related data to use within the app:

  * `assemblies/assemblies.blob`
  * `assemblies/assemblies.[ARCHITECTURE].blob`

`assemblies.[ARCHITECTURE].blob` contains architecture-specific
assemblies, e.g. `System.Private.CoreLib.dll` built for x86 would be
placed within `assemblies.x86.blob`.  `ARCHITECTURE` is one of `x86`,
`x86_64`, `armeabi_v7a`, or `arm64_v8a`; note use of `_` instead of
`-`, which is different from the `lib/ARCHITECTURE` convention within
`.apk` files.  This is done because this is apparently what Android
and `bundletool` do, e.g. creating `split_config.armeabi_v7a.apk`.

Once the architecture-neutral `assemblies.blob` and appropriate
(singular!) `assemblies.[ARCHITECTURE].blob` for the current
architecture is found and `mmap()`'d, `.apk` entry traversal can end.
There is no longer a need to parse the entire `.apk` during startup.

The reduction in the number of `mmap()` system calls required can
have a noticeable impact on process startup, particularly with
.NET SDK for Android & MAUI; see below for timing details.

The assembly store format uses the followings structures:

	struct AssemblyStoreHeader {
	    uint32_t magic, version;
	    uint32_t local_entry_count;                    // Number of AssemblyStoreAssemblyDescriptor entries
	    uint32_t global_entry_count;                   // Number of AssemblyStoreAssemblyDescriptor entries in entire app, across all *.blob files
	    uint32_t store_id;
	};
	struct AssemblyStoreAssemblyDescriptor {
	    uint32_t data_offset, data_size;                // Offset from beginning of file for .dll data
	    uint32_t debug_data_offset, debug_data_size;    // Offset from beginning of file for .pdb data
	    uint32_t config_data_offset, config_data_size;  // Offset from beginning of file for .dll.config data
	};
	struct AssemblyStoreHashEntry {
	    union {
	        uint64_t hash64;                            // 64-bit xxhash of assembly filename
	        uint32_t hash64;                            // 32-bit xxhash of assembly filename
	    };
	    uint32_t mapping_index, local_store_index, store_id;
	};

The assembly store format is roughly as follows:

	AssemblyStoreHeader                 header {…};
	AssemblyStoreAssemblyDescriptor     assemblies [header.local_entry_count];

	// The following two entries exist only when header.store_id == 0
	AssemblyStoreHashEntry              hashes32[header.global_entry_count];
	AssemblyStoreHashEntry              hashes64[header.global_entry_count];

	uint8_t data[];

Note that `AssemblyStoreFileFormat::hashes32` and
`AssemblyStoreFileFormat::hashes64` are *sorted by their hash*.
Further note that assembly *filenames* are not present.
`EmbeddedAssemblies::blob_assemblies_open_from_bundles()` will hash
the filename, then binary search the appropriate `hashes*` array to
get the appropriate assembly information.

As the assembly store format doesn't include assembly names, `.apk`
and `.aab` files will also contain an `assemblies.manifest` file,
which contains the assembly names and other information in a human-
readable format; it is also used by `assembly-store-reader`:

	Hash 32     Hash 64             Blob ID  Blob idx  Name
	0xa2e0939b  0x4288cfb749e4c631  000      0000      Xamarin.AndroidX.Activity
	…
	0xad6f1e8a  0x6b0ff375198b9c17  001      0000      System.Private.CoreLib

Add a new `tools/assembly-store-reader` utility which can read the
new `assemblies*.blob` files:

	% tools/scripts/read-assembly-store path/to/app.apk
	Store set 'base_assemblies':
	  Is complete set? yes
	  Number of stores in the set: 5

	Assemblies:
	  0:
	    Name: Xamarin.AndroidX.Activity
	    Store ID: 0 (shared)
	    Hashes: 32-bit == 0xa2e0939b; 64-bit == 0x4288cfb749e4c631
	    Assembly image: offset == 1084; size == 14493
	    Debug data: absent
	    Config file: absent
	  …
	  16:
	    Name: System.Private.CoreLib
	    Store ID: 1 (x86)
	    Hashes: 32-bit == 0xad6f1e8a; 64-bit == 0x6b0ff375198b9c17
	    Assembly image: offset == 44; size == 530029
	    Debug data: absent
	    Config file: absent
	  …

On a Pixel 3 XL (arm64-v8a) running Android 12 with MAUI
6.0.101-preview.10.1952, we observe:

~~ MAUI: Displayed Time ~~

| Before ms |  After ms |            Δ | Notes                                 |
| ---------:| --------: | -----------: | ------------------------------------- |
|  1016.800 |   892.600 |    -12.21% ✓ | defaults; profiled AOT; 32-bit build  |
|  1016.100 |   894.700 |    -11.95% ✓ | defaults; profiled AOT; 64-bit build  |
|  1104.200 |   922.000 |    -16.50% ✓ | defaults; full AOT+LLVM; 64-bit build |
|  1102.700 |   926.100 |    -16.02% ✓ | defaults; full AOT; 32-bit build      |
|  1108.400 |   932.600 |    -15.86% ✓ | defaults; full AOT; 64-bit build      |
|  1106.300 |   932.600 |    -15.70% ✓ | defaults; full AOT+LLVM; 32-bit build |
|  1292.000 |  1271.800 |     -1.56% ✓ | defaults; 64-bit build                |
|  1307.000 |  1275.400 |     -2.42% ✓ | defaults; 32-bit build                |

Displayed time reduces by ~12% when Profiled AOT is used.

It is interesting to note that **Displayed time** is nearly identical
for the default (JIT) settings case. It's most probably caused by the
amount of JIT-ed code between `OnCreate()` and the time when the
application screen is presented, most likely the time is spent JIT-ing
MAUI rendering code.


~~ MAUI: Total native init time (before `OnCreate()`) ~~

| Before ms |  After ms |            Δ | Notes                                 |
| --------: | --------: | -----------: | ------------------------------------- |
|    96.727 |    88.921 |     -8.07% ✓ | defaults; 32-bit build                |
|    97.236 |    89.693 |     -7.76% ✓ | defaults; 64-bit build                |
|   169.315 |   108.845 |    -35.71% ✓ | defaults; profiled AOT; 32-bit build  |
|   170.061 |   109.071 |    -35.86% ✓ | defaults; profiled AOT; 64-bit build  |
|   363.864 |   208.949 |    -42.57% ✓ | defaults; full AOT; 64-bit build      |
|   363.629 |   209.092 |    -42.50% ✓ | defaults; full AOT; 32-bit build      |
|   373.203 |   218.289 |    -41.51% ✓ | defaults; full AOT+LLVM; 64-bit build |
|   372.783 |   219.003 |    -41.25% ✓ | defaults; full AOT+LLVM; 32-bit build |

Note that "native init time" includes running `JNIEnv.Initialize()`,
which requires loading `Mono.Android.dll` + dependencies such as
`System.Private.CoreLib.dll`, which in turn means that the AOT DSOs
such as `libaot-System.Private.CoreLib.dll.so` must *also* be loaded.
The loading of the AOT DSOs is why JIT is fastest here (no AOT DSOs),
and why Profiled AOT is faster than Full AOT (smaller DSOs).


~~ Plain Xamarin.Android: Displayed Time ~~

| Before ms |  After ms |            Δ | Notes                                 |
| --------: | --------: | -----------: | ------------------------------------- |
|   289.300 |   251.000 |    -13.24% ✓ | defaults; full AOT+LLVM; 64-bit build |
|   286.300 |   252.900 |    -11.67% ✓ | defaults; full AOT; 64-bit build      |
|   285.700 |   255.300 |    -10.64% ✓ | defaults; profiled AOT; 32-bit build  |
|   282.900 |   255.800 |     -9.58% ✓ | defaults; full AOT+LLVM; 32-bit build |
|   286.100 |   256.500 |    -10.35% ✓ | defaults; full AOT; 32-bit build      |
|   286.100 |   258.000 |     -9.82% ✓ | defaults; profiled AOT; 64-bit build  |
|   328.900 |   310.600 |     -5.56% ✓ | defaults; 32-bit build                |
|   319.300 |   313.000 |     -1.97% ✓ | defaults; 64-bit build                |


~~ Plain Xamarin.Android: Total native init time (before `OnCreate()`) ~~

| Before ms |  After ms |            Δ | Notes                                 |
| --------: | --------: | -----------: | ------------------------------------- |
|    59.768 |    42.694 |    -28.57% ✓ | defaults; profiled AOT; 64-bit build  |
|    60.056 |    42.990 |    -28.42% ✓ | defaults; profiled AOT; 32-bit build  |
|    65.829 |    48.684 |    -26.05% ✓ | defaults; full AOT; 64-bit build      |
|    65.688 |    48.713 |    -25.84% ✓ | defaults; full AOT; 32-bit build      |
|    67.159 |    49.938 |    -25.64% ✓ | defaults; full AOT+LLVM; 64-bit build |
|    67.514 |    50.465 |    -25.25% ✓ | defaults; full AOT+LLVM; 32-bit build |
|    66.758 |    62.531 |     -6.33% ✓ | defaults; 32-bit build                |
|    67.252 |    62.829 |     -6.58% ✓ | defaults; 64-bit build                |
2021-10-25 09:54:31 -04:00
Peter Collins 9cdaf84146
[Documentation] Update OSS Build Artifact docs (#5350)
Fixes: https://github.com/xamarin/xamarin-android/issues/5295

Our Open Source build artifact docs were never updated to cover the
transition from Jenkins to Azure Pipelines.  The `JenkinsBuildArtifacts`
file has been renamed to `OSSBuildArtifacts` and the content has been
updated to reflect the new way to obtain and install these artifacts.
2020-12-02 10:02:06 -05:00
Atsushi Eno a3d4d19d99
[documentation] fix broken link to build-process.md. (#5336) 2020-11-27 10:30:46 +01:00
Jonathan Peppers f069c7ab39
[One .NET] exclude MSBuild targets for .dll.config files (#4896)
Running under .NET 5+, the
`BuildTest.BuildBasicApplicationCheckConfigFiles()` test fails with:

	UnnamedProject.dll.config was must be copied to Intermediate directory
	Expected: True
	But was: False

After review, it doesn't seem like Xamarin.Android needs to support
`.dll.config` files in .NET 5+ at all.

 1. `<dllmap/>` is not supported.  It was a feature of Mono.
    [`NativeLibrary`][0] is the replacement, but only exists in
    .NET Core 3.0+.

 2. `appSettings` only work via a compat NuGet package:

        <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />

    However, this NuGet package does not work in the current
    Xamarin.Android (it throws `PlatformNotSupportedException`), and
    there is no other mechanism to support `appSettings`.

All MSBuild targets related to `.config` files have been moved to
`Xamarin.Android.Legacy.targets`.

If a .NET 5+ build encounters a `.dll.config` file, an XA1024 warning
will be generated:

	warning XA1024: Ignoring configuration file 'Foo.dll.config'.
	.NET configuration files are not supported in Xamarin.Android projects that target .NET 5 or higher.

This is unfortunately an un-actionable warning message, so we may want
to reconsider this approach.

TODO/Possible answer: if we ever have a mechanism to support NuGet
package creation a'la `dotnet pack`, we could emit the XA1024 warning
at package creation if the `.dll.config` is included in the NuGet.

I added updated tests around the`_CopyConfigFiles` MSBuild target to
run under `dotnet` context.

[0]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.nativelibrary
2020-07-14 12:12:51 -04:00
Brendan Zagaeski 0342fe5698 [Xamarin.Android.Build.Tasks] Move XA4214 warning text into .resx file (#3900)
Context: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1009374/

This is a first step toward localizing the MSBuild error and warning
messages produced by `Xamarin.Android.Build.Tasks.dll`.

We will be following the [.NET Resource Localization pattern][0] and
generating satellite assemblies using [`.resx` files][1], in particular
`src/Xamarin.Android.Build.Tasks/Properties/Resources.resx`.

`Resources.resx` is an XML file, and will contain `/root/data`
elements in which `//data/@name` will start with the Xamarin.Android
error or warning code, and `//data/value` will be the error or
warning message:

        <root>
          <data name="XA4214" xml:space="preserve">
            <value>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</value>
          </data>
        </root>

An optional `//data/comment` element may be provided to describe the
meaning within the `//data/value` element to translators:

        <data name="XA4214" xml:space="preserve">
          <value>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</value>
          <comment>
            {0} - The managed type name
            {1} - Comma-separated list of all the assemblies where the managed type exists
          </comment>
        </data>

During the build, `Resources.resx` will be translated into a
`Resources.Designer.cs` file:

        namespace Xamarin.Android.Tasks.Properties {
          internal partial class Resources {
            internal static string XA4214 {
              get => ...
            }
          }
        }

The `Resources` members should be used to obtain all strings for use
in `LogCodedError()` and `LogCodedWarning()` calls:

        Log.LogCodedWarning ("XA4214", Properties.Resources.XA4214, kvp.Key, string.Join (", ", kvp.Value));

When an MSBuild error or warning code is used with more than one
output string, then a semantically meaningful suffix should be used
to distinguish between the two:

        <data name="XA4214_Result" xml:space="preserve">
          <value>References to the type `{0}` will refer to `{0}, {1}`.</value>
        </data>

Note that this infrastructure does not interoperate with C#6 string
interpolation.  Any error or warning messages currently using C#6
string interpolation will need to use .NET 1.0-style format strings.

Our translation team doesn't work directly with `.resx` files.
Instead, the translation team works with [XLIFF files][2].
`Resources.resx` is converted into a set of
`src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.*.xlf`
files via `XliffTasks.targets` from the [dotnet/xliff-tasks][3] repo.
The `Resources.*.xlf` files should be automatically updated whenever
`Resources.resx` is updated.


Other:

  * This approach leaves the error code `XA4214` as a string literal
    for now.  This differs from what dotnet/sdk and microsoft/msbuild
    do; they instead include the message code as part of the string
    resource in the `.resx` file.  That might sometimes provide useful
    additional context for the translation team, but it also requires
    using a different set of logging methods from
    `Microsoft.Build.Utilities.TaskLoggingHelper`.

  * Fix the Test MSBuild Azure Pipelines build

    Specify the `feedsToUse` and `nugetConfigPath` inputs for the
    [`NuGetCommand@2`][6] Azure Pipelines task so that the NuGet
    restore step will be able to restore XliffTasks successfully from
    the dotnet-eng Azure DevOps NuGet package feed.

    This resolves the following error:

        The nuget command failed with exit code(1) and error(Errors in packages.config projects
            Unable to find version '1.0.0-beta.19252.1' of package 'XliffTasks'.
              C:\Users\dlab14\.nuget\packages\: Package 'XliffTasks.1.0.0-beta.19252.1' is not found on source 'C:\Users\dlab14\.nuget\packages\'.
              https://api.nuget.org/v3/index.json: Package 'XliffTasks.1.0.0-beta.19252.1' is not found on source 'https://api.nuget.org/v3/index.json'.)

TODO:

  * When `Xamarin.Android.Build.Tasks.csproj` is converted into a
    [short-form project][4], add a dependency on dotnet/arcade and
    switch to using the [`GenerateResxSource` mechanism][5] instead
    of using `%(EmbeddedResource.Generator)`=ResXFileCodeGenerator
    and set `$(UsingToolXliff)`=True.  This would match dotnet/sdk.

[0]: https://docs.microsoft.com/dotnet/framework/resources/index
[1]: https://docs.microsoft.com/dotnet/framework/resources/creating-resource-files-for-desktop-apps#resources-in-resx-files
[2]: http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html
[3]: https://github.com/dotnet/xliff-tasks
[4]: https://docs.microsoft.com/visualstudio/msbuild/how-to-use-project-sdk
[5]: e67d9f0980/Documentation/ArcadeSdk.md (generateresxsource-bool)
[6]: https://docs.microsoft.com/azure/devops/pipelines/tasks/package/nuget
2019-12-07 13:58:58 -05:00
Jonathan Peppers 89ddff9180 [docs] document different ways to profile startup
I recently found the Xamarin Profiler / GUI wasn't really suitable for
profiling Xamarin.Android startup on devices.

This is basically a brain dump of every way I have found to get
different timing information.

It should be useful in timing such things as Xamarin.Forms startup,
etc.
2019-09-05 03:00:42 -07:00
Thays Grazia a59091d7d1 [docs] How-to Native Debugging of Mono (#2942)
Document how to natively debug mono using lldb, VS, Android Studio.
2019-07-16 12:13:34 -04:00
Brendan Zagaeski 494fc57ba6 [docs] Update the build instructions for Windows (#2656)
Context: https://gitter.im/xamarin/xamarin-android?at=5c4a25ba7a0f4d5b1900f7a4
Context: https://gitter.im/xamarin/xamarin-android?at=5c4a9d968ce4bb25b80795d3

The current documentation structure was found to be confusing, in
that a developer on Windows believed that they needed to install Mono
in order to build xamarin-android on Windows, which not only is not
the case, but *introduces* obscure build failures and confusion:

	CoreCompile:
	  C:\Program Files\Mono\lib\mono\msbuild\15.0\bin\Roslyn\csc.exe ...
	  error MSB6006: "csc.exe" exited with code 1.

A possible fix could be to add a Windows section to the build
dependencies page, but we thought it would be clearer if we just
completely split apart the Linux/macOS ("Unix") instructions from the
Windows instructions, instead of attempting to share contents.

Move the build dependencies and build instructions for macOS and
Linux into `Documentation/building/unix`.

Move the build instructions and *add* a build dependencies page for
Windows into `Documentation/building/windows`.

Add a link to the [Using Your Build][0] page in the Windows build
instructions to make it easier for contributors to find the next step
about how to build a Xamarin.Android application after they have
built `Xamarin.Android.sln`.

Mention the (relatively new) `Xamarin.Android.Build.Tasks.sln` as a
way to work around output assembly file locking when working on the
`Xamarin.Android.Build.Tasks.csproj` project on Windows.

[0]: 578e781ba1/Documentation/workflow/UsingYourBuild.md
2019-02-08 20:05:57 -05:00
Jonathan Peppers 4bb4b2e93c [Xamarin.Android.Build.Tasks] D8 and R8 integration (#2019)
Fixes: https://github.com/xamarin/xamarin-android/issues/1423
Fixes: https://github.com/xamarin/xamarin-android/issues/2040

Bumps to r8/d8-1.2@125b72.

~~ Overview ~~

This enables `d8` and `r8` integration for Xamarin.Android.
`d8` is a "next-generation" dex compiler (over `dx`), and
`r8` is a replacement for ProGuard.  For full details on the feature,
see `Documentation/guides/D8andR8.md`.


~~ MSBuild targets changes ~~

New MSBuild properties include:

  - `$(AndroidDexTool)` - an enum-style property with options `dx`
    and `d8`.  Defaults to `dx`.

  - `$(AndroidLinkTool)` - an enum-style property, that can be left
    blank to disable code shrinking.
    Valid values are `proguard` and `r8`.

Existing MSBuild properties still retain the old behavior:

  - `$(AndroidEnableProguard)` will set `$(AndroidLinkTool)` to
    `proguard`, although it is no longer used internally by
    Xamarin.Android targets.
  - `$(AndroidEnableDesugar)` will default to `true` if `d8` or `r8`
    are used.

New MSBuild tasks include:

  - `<D8/>`: runs `d8.jar` with the required options for
    Xamarin.Android.
  - `<R8/>`: subclasses `<D8/>`, and adds functionality for multi-dex
    and code-shrinking.

Additionally, any new MSBuild targets are placed in a new
`Xamarin.Android.D8.targets` file.  This is good first step to make
`Xamarin.Android.Common.targets` smaller.

Additionally:

  * `build.props` is now invalidated via the `$(AndroidDexTool)`
    and `$(AndroidLinkTool)` properties, instead of
    `$(AndroidEnableProguard)`
  * `build.props` is invalidated via `$(AndroidEnableDesugar)`
  * Refactored `$(IntermediateOutputPath)_dex_stamp` stamp file in
    `_CompileToDalvikWithDx` and `_CompileToDalvikWithD8` to match the
    new convention of `$(_AndroidStampDirectory)_CompileToDalvik.stamp`
  * `*.dex` files weren't in `@(FileWrites)`?!
  * `<CompileToDalvik/>` had a `DexOutputs` output property that was
    completely unused, so I removed it.  Also removed extra log messages.


~~ Test changes ~~

Tests that need to validate various combinations of properties are
now using parameters such as:

	[Values ("dx", "d8")] string dexTool, [Values ("", "proguard", "r8")] string linkTool

Set on the `XamarinAndroidApplicationProject` such as:

	var proj = new XamarinAndroidApplicationProject {
	    DexTool   = dexTool,
	    LinkTool  = linkTool,
	};

In other cases, a simple `useD8` flag was added to set `DexTool="d8"`.

Since adding test parameters, exponentially causes our test cases to
expand, I removed some non-essential parameters:

  - `BuildProguardEnabledProject()` dropped `useLatestSdk`, as it does
    not seem applicable here (and is deprecated).  Otherwise would
    have 24 test cases...
  - `BuildApplicationWithSpacesInPath()` dropped `isRelease` and
    defaulted it to `true`.  We aren't going to likely encounter
    issues with spaces in a path that happen *only* in a `Debug`
    build.  Otherwise we would have 24 test cases here...
  - `Desugar()` dropped `enableDesugar` because it is certain this
    application project will not build *without* desugar.  We don't
    need to test this, and would have 24 test cases otherwise...

Also dropped some `[TestCaseSource]` attributes where the `[Values]`
parameter was much cleaner.


~~ Changes to test/sample projects ~~

`HelloWorld` - `$(AndroidDexTool)` set to `d8` if unspecified,
so we can track the performance benefit.

`Xamarin.Forms Integration` - uses `d8` and `$(AndroidLinkTool)` set
to `r8`, using a `proguard.cfg` file for Xamarin.Forms.  Will help us
track startup performance benefits of Java code shrinking and build
performance.

`Mono.Android-Tests` - uses `d8` and `$(AndroidLinkTool)` set to
`r8`, to verify these on-device tests pass.

`Runtime-MultiDex` - `$(AndroidDexTool)` set to `d8` if unspecified,
to validate multi-dex is working properly with `d8`.


~~ xamarin-android build changes ~~

The `<DownloadUri/>` MSBuild task now has an optional `HashHeader`
property.  When set, an http HEAD request is made to the URL, and the
destination file path gets a suffix added for the value.
`DownloadUri.DestinationFiles` is  changed to an `[Output]` property,
as the destination paths could change due to the `HashHeader`.

Chromium's  `depot_tools` are downloaded the same as all of our other
dependencies.  As the `depot_tools` distribution filename is
unversioned, we use the `x-goog-hash` header to derive a "version" so
that we don't needlessly download the file.


~~ Deployment changes ~~

Three new files will need to be included in Xamarin.Android
installers:

  - `d8.jar`
  - `r8.jar`
  - `Xamarin.Android.D8.targets`


~~ General changes ~~

  * Fixed doc for `xa4304` error code
  * Added `xa4305` error code for `CompileToDalvik`, `R8`, and
    `<CreateMultiDexMainDexClassList/>`
  * Removed log messages in `<CreateMultiDexMainDexClassList/>`


~~ Performance Comparison ~~

| MSBuild Target         | Options Enabled        | Time    | APK size (bytes) | dex size (bytes) |
| ---                    | ---                    | ---:    | ---:             | ---:             |
| _CompileToDalvikWithDx | n/a                    | 11074ms | 13378157         | 3894720          |
| _CompileToDalvikWithD8 | d8, (desugar enabled)  |  8543ms | 13124205         | 3314064          |
| _CompileToDalvikWithD8 | d8, (desugar disabled) |  9550ms | 13124205         | 3314064          |
| _CompileToDalvikWithDx | multi-dex              | 15632ms | 13390498         | 3916496          |
| _CompileToDalvikWithD8 | d8, multi-dex          | 25979ms | 13054626         | 3264096          |
| _CompileToDalvikWithDx | proguard               | 11903ms | 12804717         | 2446964          |
| _CompileToDalvikWithD8 | d8, r8                 | 13799ms | 12513901         | 1835588          |
| _CompileToDalvikWithDx | multi-dex, proguard    | 17279ms | 12804770         | 2449512          |
| _CompileToDalvikWithD8 | d8, multi-dex, r8      | 13792ms | 12513954         | 1837588          |

*NOTE: desugar is enabled by default with d8/r8*

I timed this builds with [this script][powershell_script], with a
"Hello World" Xamarin.Forms app.
Build logs here: [d8andr8.zip][d8andr8_zip]

One can draw their own conclusions on which options are faster,
better, smaller.  See further detail in `D8andR8.md`.

[powershell_script]: 39e2854f6c/build.ps1
[d8andr8_zip]: https://github.com/xamarin/xamarin-android/files/2470385/d8andr8.zip

Co-authored-by: Atsushi Eno <atsushieno@gmail.com>
2018-10-30 15:40:50 -04:00
Jonathan Peppers eb642add0b [Xamarin.Android.Build.Tasks] incremental build improvements (#2320)
Fixes: https://github.com/xamarin/xamarin-android/issues/2247

We currently have two targets that fail to build incrementally:
- `_ResolveLibraryProjectImports`
- `_GeneratePackageManagerJava`

Both of these targets declare `Outputs`, but don't always update the
timestamp of the output file. They used `CopyIfChanged` logic, so they
won't write to the file if nothing changed.

However...

We can't just add `<Touch/>` calls here either, as the `Outputs` of
these targets are `Inputs` to other *slow* targets (`_CompileJava`,
`_UpdateAndroidResgen`, and friends). If we used `<Touch/>` here,
things would be worse and trigger the *slow* targets to run.

So the only option here is to use a "stamp" file, this allows these
targets to properly build incrementally and not trigger other targets.

I updated a `IncrementalBuildTest` to include a test case checking all
three of these targets.

Future changes:

- I am going to need to audit many of our MSBuild targets for this
  same problem, and so I will likely need to add many new stamp files.
- To simplify this, we should adopt a new convention of placing stamp
  files in `$(IntermediateOutputPath)stamp\` or
  `$(_AndroidStampDirectory)`.
- The stamp file should be named the same as the target where it is
  used as an `Output`.

Documentation:

I also started some initial documentation on "MSBuild Best Practices",
which we can expand upon in future PRs. See the `Stamp Files` section
on what is relevant in this PR.
2018-10-19 10:12:58 +01:00
Jonathan Pryor 3f587f51b4
[docs] Reorganize the docs (#1358)
Context: https://github.com/xamarin/xamarin-android/pull/1343

> Trying to refactor `README.md` so it's more concise...based on the
> user's goal to contribute or provide feedback when visiting the
> repository.

If we're to make `README.md` shorter, then the contents of `README.md`
need to be moved *elsewhere*.

Reorganize the Documentation, taking inspiration from dotnet/coreclr
for general organization principals:

  * Documentation/building: How do we build this thing?
  * Documentation/guides: "Product documentation" which should live
    "elsewhere", but we want here for sanity purposes.
    In particular, the Build Process documentation.
  * Documentation/project-docs: What is Xamarin.Android?
  * Documentation/workflow: How do we develop this thing?
2018-03-03 11:50:20 -05:00