Skip to content

Commit e3862a3

Browse files
committed
[msbuild][r8] add r8 support to alter dx, proguard and desugar.
See #1423 for details. multidex support is not done yet (needs to investigate what's expected there). Xamarin.Android.sln has a lot of changed lines because they had wrong ProjectTypeGuids (maybe regression from changes to .csproj from .*proj).
1 parent 181e3d0 commit e3862a3

File tree

17 files changed

+385
-37
lines changed

17 files changed

+385
-37
lines changed

Documentation/guides/BuildProcess.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ when packaing Release applications.
209209

210210
This property is `False` by default.
211211

212+
- **AndroidEnableD8** – A boolean property that determines
213+
whether or not use Google's new dexer (dx.jar alternative).
214+
212215
- **AndroidEnableMultiDex** – A boolean property that
213216
determines whether or not multi-dex support will be used in the
214217
final `.apk`.
@@ -419,6 +422,10 @@ when packaing Release applications.
419422
This property should be `True` for Debug builds, and `False` for
420423
Release projects.
421424
425+
- **AndroidUseR8** – A boolean property that determines
426+
whether or not use Google's new Java code shlinker (proguard
427+
alternative).
428+
422429
- **AotAssemblies** – A boolean property that determines
423430
whether or not assemblies will be Ahead-of-Time compiled into
424431
native code and included in the `.apk`.

Xamarin.Android.sln

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.Andro
123123
EndProject
124124
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.AndroidSdk-Tests", "external\xamarin-android-tools\src\Xamarin.Android.Tools.AndroidSdk\Tests\Xamarin.Android.Tools.AndroidSdk-Tests.csproj", "{1E5501E8-49C1-4659-838D-CC9720C5208F}"
125125
EndProject
126+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "r8", "src\r8\r8.csproj", "{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}"
126127
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proprietary", "build-tools\proprietary\proprietary.csproj", "{D93CAC27-3893-42A3-99F1-2BCA72E186F4}"
127128
EndProject
128129
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "download-bundle", "build-tools\download-bundle\download-bundle.csproj", "{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}"
@@ -358,6 +359,18 @@ Global
358359
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Debug|AnyCPU.Build.0 = Debug|AnyCPU
359360
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
360361
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Release|AnyCPU.Build.0 = Release|AnyCPU
362+
{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
363+
{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Debug|AnyCPU.Build.0 = Debug|Any CPU
364+
{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Release|AnyCPU.ActiveCfg = Release|Any CPU
365+
{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Release|AnyCPU.Build.0 = Release|Any CPU
366+
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
367+
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Debug|AnyCPU.Build.0 = Debug|Any CPU
368+
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Release|AnyCPU.ActiveCfg = Release|Any CPU
369+
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Release|AnyCPU.Build.0 = Release|Any CPU
370+
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
371+
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Debug|AnyCPU.Build.0 = Debug|Any CPU
372+
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Release|AnyCPU.ActiveCfg = Release|Any CPU
373+
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Release|AnyCPU.Build.0 = Release|Any CPU
361374
EndGlobalSection
362375
GlobalSection(SolutionProperties) = preSolution
363376
HideSolutionNode = FALSE
@@ -420,6 +433,9 @@ Global
420433
{1E5501E8-49C1-4659-838D-CC9720C5208F} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
421434
{D93CAC27-3893-42A3-99F1-2BCA72E186F4} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
422435
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
436+
{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D} = {864062D3-A415-4A6F-9324-5820237BA058}
437+
{53E4ABF0-1085-45F9-B964-DCAE4B819998} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
438+
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
423439
EndGlobalSection
424440
GlobalSection(ExtensibilityGlobals) = postSolution
425441
SolutionGuid = {53A1F287-EFB2-4D97-A4BB-4A5E145613F6}

build-tools/r8/r8.csproj

Lines changed: 0 additions & 9 deletions
This file was deleted.

external/depot_tools.tpnitems

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Condition=" '$(TpnIncludeExternalDependencies)' == 'True' ">
4+
<ThirdPartyNotice Include="google/depot_tools">
5+
<LicenseFile>$(MSBuildThisFileDirectory)\depot_tools\LICENSE</LicenseFile>
6+
<SourceUrl>https://chromium.googlesource.com/chromium/tools/depot_tools.git</SourceUrl>
7+
</ThirdPartyNotice>
8+
</ItemGroup>
9+
</Project>

external/r8.tpnitems

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Condition=" '$(TpnIncludeExternalDependencies)' == 'True' ">
4+
<ThirdPartyNotice Include="google/r8">
5+
<LicenseFile>$(MSBuildThisFileDirectory)\r8\LICENSE</LicenseFile>
6+
<SourceUrl>https://r8.googlesource.com/r8/</SourceUrl>
7+
</ThirdPartyNotice>
8+
</ItemGroup>
9+
</Project>

src/Mono.Android/Test/Mono.Android-Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
2020
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
2121
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
22+
<AndroidUseR8>true</AndroidUseR8>
23+
<AndroidEnableD8>true</AndroidEnableD8>
2224
</PropertyGroup>
2325
<Import Project="..\..\..\Configuration.props" />
2426
<PropertyGroup>

src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,17 @@ public class Proguard : ToolTask
4141
[Required]
4242
public string ProguardJarOutput { get; set; }
4343

44-
[Required]
4544
public string ProguardGeneratedReferenceConfiguration { get; set; }
46-
47-
[Required]
4845
public string ProguardGeneratedApplicationConfiguration { get; set; }
49-
50-
[Required]
5146
public string ProguardCommonXamarinConfiguration { get; set; }
5247

48+
[Required]
5349
public string ProguardConfigurationFiles { get; set; }
5450

5551
public ITaskItem[] JavaLibrariesToEmbed { get; set; }
5652

57-
public ITaskItem[] ExternalJavaLibraries { get; set; }
53+
public ITaskItem[] JavaLibrariesToReference { get; set; }
5854

59-
public ITaskItem[] DoNotPackageJavaLibraries { get; set; }
60-
6155
public bool UseProguard { get; set; }
6256

6357
public string JavaOptions { get; set; }
@@ -86,14 +80,13 @@ public override bool Execute ()
8680
Log.LogDebugMessage (" JavaPlatformJarPath: {0}", JavaPlatformJarPath);
8781
Log.LogDebugMessage (" ClassesOutputDirectory: {0}", ClassesOutputDirectory);
8882
Log.LogDebugMessage (" AcwMapFile: {0}", AcwMapFile);
89-
Log.LogDebugMessage (" ProguardGeneratedApplicationConfiguration: {0}", ProguardGeneratedApplicationConfiguration);
9083
Log.LogDebugMessage (" ProguardJarOutput: {0}", ProguardJarOutput);
9184
Log.LogDebugTaskItems (" ProguardGeneratedReferenceConfiguration:", ProguardGeneratedReferenceConfiguration);
9285
Log.LogDebugTaskItems (" ProguardGeneratedApplicationConfiguration:", ProguardGeneratedApplicationConfiguration);
9386
Log.LogDebugTaskItems (" ProguardCommonXamarinConfiguration:", ProguardCommonXamarinConfiguration);
9487
Log.LogDebugTaskItems (" ProguardConfigurationFiles:", ProguardConfigurationFiles);
95-
Log.LogDebugTaskItems (" ExternalJavaLibraries:", ExternalJavaLibraries);
96-
Log.LogDebugTaskItems (" DoNotPackageJavaLibraries:", DoNotPackageJavaLibraries);
88+
Log.LogDebugTaskItems (" JavaLibrariesToEmbed:", JavaLibrariesToEmbed);
89+
Log.LogDebugTaskItems (" JavaLibrariesToReference:", JavaLibrariesToReference);
9790
Log.LogDebugMessage (" UseProguard: {0}", UseProguard);
9891
Log.LogDebugMessage (" EnableLogging: {0}", EnableLogging);
9992
Log.LogDebugMessage (" DumpOutput: {0}", DumpOutput);
@@ -139,15 +132,9 @@ protected override string GenerateCommandLineCommands ()
139132
// skip invalid lines
140133
}
141134

142-
var injars = new List<string> ();
143-
var libjars = new List<string> ();
144-
injars.Add (classesZip);
145-
if (JavaLibrariesToEmbed != null)
146-
foreach (var jarfile in JavaLibrariesToEmbed)
147-
injars.Add (jarfile.ItemSpec);
148-
149-
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
150-
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
135+
if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration))
136+
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
137+
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
151138

152139
var configs = ProguardConfigurationFiles
153140
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
@@ -168,9 +155,15 @@ protected override string GenerateCommandLineCommands ()
168155
Log.LogWarning ("Proguard configuration file '{0}' was not found.", file);
169156
}
170157

158+
var injars = new List<string> ();
159+
var libjars = new List<string> ();
160+
injars.Add (classesZip);
161+
if (JavaLibrariesToEmbed != null)
162+
foreach (var jarfile in JavaLibrariesToEmbed)
163+
injars.Add (jarfile.ItemSpec);
171164
libjars.Add (JavaPlatformJarPath);
172-
if (ExternalJavaLibraries != null)
173-
foreach (var jarfile in ExternalJavaLibraries.Select (p => p.ItemSpec))
165+
if (JavaLibrariesToReference != null)
166+
foreach (var jarfile in JavaLibrariesToReference.Select (p => p.ItemSpec))
174167
libjars.Add (jarfile);
175168

176169
cmd.AppendSwitchUnquotedIfNotNull ("-injars ", "\"'" + string.Join ($"'{ProguardInputJarFilter}{Path.PathSeparator}'", injars.Distinct ()) + $"'{ProguardInputJarFilter}\"");
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// Copyright (C) 2018 Xamarin, Inc. All rights reserved.
2+
3+
using System;
4+
using System.Linq;
5+
using System.IO;
6+
using Microsoft.Build.Framework;
7+
using Microsoft.Build.Utilities;
8+
using System.Text;
9+
using System.Collections.Generic;
10+
using Xamarin.Android.Tools;
11+
12+
namespace Xamarin.Android.Tasks
13+
{
14+
15+
public class R8 : JavaToolTask
16+
{
17+
[Required]
18+
public string R8JarPath { get; set; }
19+
20+
[Required]
21+
public string OutputDirectory { get; set; }
22+
23+
public string Configuration { get; set; }
24+
25+
// It is loaded to calculate --min-api, which is used by desugaring part to determine which levels of desugaring it performs.
26+
[Required]
27+
public string AndroidManifestFile { get; set; }
28+
29+
// general r8 feature options.
30+
public bool EnableDesugar { get; set; }
31+
public bool EnableMinify { get; set; } // The Task has the option, but it is not supported at all.
32+
public bool EnableTreeShaking { get; set; }
33+
34+
// Java libraries to embed or reference
35+
[Required]
36+
public string ClassesZip { get; set; }
37+
[Required]
38+
public string JavaPlatformJarPath { get; set; }
39+
public ITaskItem [] JavaLibrariesToEmbed { get; set; }
40+
public ITaskItem [] JavaLibrariesToReference { get; set; }
41+
42+
// used for proguard configuration settings
43+
[Required]
44+
public string AndroidSdkDirectory { get; set; }
45+
[Required]
46+
public string AcwMapFile { get; set; }
47+
public string ProguardGeneratedReferenceConfiguration { get; set; }
48+
public string ProguardGeneratedApplicationConfiguration { get; set; }
49+
public string ProguardCommonXamarinConfiguration { get; set; }
50+
[Required]
51+
public string ProguardConfigurationFiles { get; set; }
52+
public string ProguardMappingOutput { get; set; }
53+
54+
// multidex
55+
public bool EnableMultiDex { get; set; }
56+
public string MultiDexMainDexListFile { get; set; }
57+
58+
public string R8ExtraArguments { get; set; }
59+
60+
public override bool Execute ()
61+
{
62+
Log.LogDebugMessage ("R8 Task");
63+
Log.LogDebugTaskItems (" R8JarPath: ", R8JarPath);
64+
Log.LogDebugTaskItems (" OutputDirectory: ", OutputDirectory);
65+
Log.LogDebugTaskItems (" AndroidManifestFile: ", AndroidManifestFile);
66+
Log.LogDebugMessage (" Configuration: {0}", Configuration);
67+
Log.LogDebugTaskItems (" JavaPlatformJarPath: ", JavaPlatformJarPath);
68+
Log.LogDebugTaskItems (" ClassesZip: ", ClassesZip);
69+
Log.LogDebugTaskItems (" JavaLibrariesToEmbed: ", JavaLibrariesToEmbed);
70+
Log.LogDebugTaskItems (" JavaLibrariesToReference: ", JavaLibrariesToReference);
71+
Log.LogDebugMessage (" EnableDesugar: {0}", EnableDesugar);
72+
Log.LogDebugMessage (" EnableTreeShaking: {0}", EnableTreeShaking);
73+
Log.LogDebugTaskItems (" AndroidSdkDirectory:", AndroidSdkDirectory);
74+
Log.LogDebugTaskItems (" AcwMapFile: ", AcwMapFile);
75+
Log.LogDebugTaskItems (" ProguardGeneratedReferenceConfiguration:", ProguardGeneratedReferenceConfiguration);
76+
Log.LogDebugTaskItems (" ProguardGeneratedApplicationConfiguration:", ProguardGeneratedApplicationConfiguration);
77+
Log.LogDebugTaskItems (" ProguardCommonXamarinConfiguration:", ProguardCommonXamarinConfiguration);
78+
Log.LogDebugTaskItems (" ProguardConfigurationFiles:", ProguardConfigurationFiles);
79+
Log.LogDebugTaskItems (" ProguardMappingOutput:", ProguardMappingOutput);
80+
Log.LogDebugMessage (" EnableMultiDex: {0}", EnableMultiDex);
81+
Log.LogDebugTaskItems (" MultiDexMainDexListFile: ", MultiDexMainDexListFile);
82+
Log.LogDebugTaskItems (" R8ExtraArguments: ", R8ExtraArguments);
83+
84+
return base.Execute ();
85+
}
86+
87+
protected override string GenerateCommandLineCommands ()
88+
{
89+
var cmd = new CommandLineBuilder ();
90+
91+
cmd.AppendSwitchIfNotNull ("-jar ", R8JarPath);
92+
93+
if (!string.IsNullOrEmpty (R8ExtraArguments))
94+
cmd.AppendSwitch (R8ExtraArguments); // it should contain "--dex".
95+
if (Configuration.Equals ("Debug", StringComparison.OrdinalIgnoreCase))
96+
cmd.AppendSwitch ("--debug");
97+
98+
// generating proguard application configuration
99+
if (EnableTreeShaking) {
100+
var acwLines = File.ReadAllLines (AcwMapFile);
101+
using (var appcfg = File.CreateText (ProguardGeneratedApplicationConfiguration))
102+
for (int i = 0; i + 2 < acwLines.Length; i += 3)
103+
try {
104+
var line = acwLines [i + 2];
105+
var java = line.Substring (line.IndexOf (';') + 1);
106+
appcfg.WriteLine ("-keep class " + java + " { *; }");
107+
} catch {
108+
// skip invalid lines
109+
}
110+
if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration))
111+
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
112+
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
113+
var configs = ProguardConfigurationFiles
114+
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
115+
.Replace ("{intermediate.common.xamarin}", ProguardCommonXamarinConfiguration)
116+
.Replace ("{intermediate.references}", ProguardGeneratedReferenceConfiguration)
117+
.Replace ("{intermediate.application}", ProguardGeneratedApplicationConfiguration)
118+
.Replace ("{project}", string.Empty) // current directory anyways.
119+
.Split (';')
120+
.Select (s => s.Trim ())
121+
.Where (s => !string.IsNullOrWhiteSpace (s));
122+
var enclosingChar = "\"";
123+
foreach (var file in configs) {
124+
if (File.Exists (file))
125+
cmd.AppendSwitchIfNotNull ("--pg-conf ", file);
126+
else
127+
Log.LogWarning ("Proguard configuration file '{0}' was not found.", file);
128+
}
129+
cmd.AppendSwitchIfNotNull ("--pg-map-output ", ProguardMappingOutput);
130+
131+
// multidexing
132+
if (EnableMultiDex) {
133+
if (!string.IsNullOrWhiteSpace (MultiDexMainDexListFile) && File.Exists (MultiDexMainDexListFile))
134+
cmd.AppendSwitchIfNotNull ("--main-dex-list ", MultiDexMainDexListFile);
135+
else
136+
Log.LogWarning ($"MultiDex is enabled, but main dex list file '{MultiDexMainDexListFile}' does not exist.");
137+
}
138+
}
139+
140+
// desugaring
141+
var doc = AndroidAppManifest.Load (AndroidManifestFile, MonoAndroidHelper.SupportedVersions);
142+
int minApiVersion = doc.MinSdkVersion == null ? 4 : (int)doc.MinSdkVersion;
143+
cmd.AppendSwitchIfNotNull ("--min-api ", minApiVersion.ToString ());
144+
145+
if (!EnableTreeShaking)
146+
cmd.AppendSwitch ("--no-tree-shaking");
147+
if (!EnableDesugar)
148+
cmd.AppendSwitch ("--no-desugaring");
149+
if (!EnableMinify)
150+
cmd.AppendSwitch ("--no-minification");
151+
152+
var injars = new List<string> ();
153+
var libjars = new List<string> ();
154+
injars.Add (ClassesZip);
155+
if (JavaLibrariesToEmbed != null)
156+
foreach (var jarfile in JavaLibrariesToEmbed)
157+
injars.Add (jarfile.ItemSpec);
158+
libjars.Add (JavaPlatformJarPath);
159+
if (JavaLibrariesToReference != null)
160+
foreach (var jarfile in JavaLibrariesToReference.Select (p => p.ItemSpec))
161+
libjars.Add (jarfile);
162+
163+
cmd.AppendSwitchIfNotNull ("--output ", OutputDirectory);
164+
foreach (var jar in libjars)
165+
cmd.AppendSwitchIfNotNull ("--lib ", jar);
166+
foreach (var jar in injars)
167+
cmd.AppendFileNameIfNotNull (jar);
168+
169+
return cmd.ToString ();
170+
}
171+
}
172+
173+
}

0 commit comments

Comments
 (0)