Skip to content

Commit 1b19111

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).
1 parent 9f4b0df commit 1b19111

File tree

7 files changed

+261
-25
lines changed

7 files changed

+261
-25
lines changed

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: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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 string MultiDexMainDexListFile { get; set; }
56+
57+
public string R8ExtraArguments { get; set; }
58+
59+
public override bool Execute ()
60+
{
61+
Log.LogDebugMessage ("R8 Task");
62+
Log.LogDebugTaskItems (" R8JarPath: ", R8JarPath);
63+
Log.LogDebugTaskItems (" OutputDirectory: ", OutputDirectory);
64+
Log.LogDebugTaskItems (" AndroidManifestFile: ", AndroidManifestFile);
65+
Log.LogDebugMessage (" Configuration: {0}", Configuration);
66+
Log.LogDebugTaskItems (" JavaPlatformJarPath: ", JavaPlatformJarPath);
67+
Log.LogDebugTaskItems (" ClassesZip: ", ClassesZip);
68+
Log.LogDebugTaskItems (" JavaLibrariesToEmbed: ", JavaLibrariesToEmbed);
69+
Log.LogDebugTaskItems (" JavaLibrariesToReference: ", JavaLibrariesToReference);
70+
Log.LogDebugMessage (" EnableDesugar: {0}", EnableDesugar);
71+
Log.LogDebugMessage (" EnableTreeShaking: {0}", EnableTreeShaking);
72+
Log.LogDebugTaskItems (" AndroidSdkDirectory:", AndroidSdkDirectory);
73+
Log.LogDebugTaskItems (" AcwMapFile: ", AcwMapFile);
74+
Log.LogDebugTaskItems (" ProguardGeneratedReferenceConfiguration:", ProguardGeneratedReferenceConfiguration);
75+
Log.LogDebugTaskItems (" ProguardGeneratedApplicationConfiguration:", ProguardGeneratedApplicationConfiguration);
76+
Log.LogDebugTaskItems (" ProguardCommonXamarinConfiguration:", ProguardCommonXamarinConfiguration);
77+
Log.LogDebugTaskItems (" ProguardConfigurationFiles:", ProguardConfigurationFiles);
78+
Log.LogDebugTaskItems (" ProguardMappingOutput:", ProguardMappingOutput);
79+
Log.LogDebugTaskItems (" MultiDexMainDexListFile: ", MultiDexMainDexListFile);
80+
Log.LogDebugTaskItems (" R8ExtraArguments: ", R8ExtraArguments);
81+
82+
return base.Execute ();
83+
}
84+
85+
protected override string GenerateCommandLineCommands ()
86+
{
87+
var cmd = new CommandLineBuilder ();
88+
89+
cmd.AppendSwitchIfNotNull ("-jar ", R8JarPath);
90+
91+
if (!string.IsNullOrEmpty (R8ExtraArguments))
92+
cmd.AppendSwitch (R8ExtraArguments); // it should contain "--dex".
93+
if (Configuration.Equals ("Debug", StringComparison.OrdinalIgnoreCase))
94+
cmd.AppendSwitch ("--debug");
95+
96+
// generating proguard application configuration
97+
if (EnableTreeShaking) {
98+
var acwLines = File.ReadAllLines (AcwMapFile);
99+
using (var appcfg = File.CreateText (ProguardGeneratedApplicationConfiguration))
100+
for (int i = 0; i + 2 < acwLines.Length; i += 3)
101+
try {
102+
var line = acwLines [i + 2];
103+
var java = line.Substring (line.IndexOf (';') + 1);
104+
appcfg.WriteLine ("-keep class " + java + " { *; }");
105+
} catch {
106+
// skip invalid lines
107+
}
108+
if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration))
109+
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
110+
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
111+
var configs = ProguardConfigurationFiles
112+
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
113+
.Replace ("{intermediate.common.xamarin}", ProguardCommonXamarinConfiguration)
114+
.Replace ("{intermediate.references}", ProguardGeneratedReferenceConfiguration)
115+
.Replace ("{intermediate.application}", ProguardGeneratedApplicationConfiguration)
116+
.Replace ("{project}", string.Empty) // current directory anyways.
117+
.Split (';')
118+
.Select (s => s.Trim ())
119+
.Where (s => !string.IsNullOrWhiteSpace (s));
120+
var enclosingChar = "\"";
121+
foreach (var file in configs) {
122+
if (File.Exists (file))
123+
cmd.AppendSwitchUnquotedIfNotNull ("--pg-conf ", $"{enclosingChar}{file}{enclosingChar}");
124+
else
125+
Log.LogWarning ("Proguard configuration file '{0}' was not found.", file);
126+
}
127+
cmd.AppendSwitchIfNotNull ("--pg-map-output ", ProguardMappingOutput);
128+
129+
// multidexing
130+
if (!string.IsNullOrWhiteSpace (MultiDexMainDexListFile) && File.Exists (MultiDexMainDexListFile))
131+
cmd.AppendSwitchIfNotNull ("--main-dex-list ", MultiDexMainDexListFile);
132+
}
133+
134+
// desugaring
135+
var doc = AndroidAppManifest.Load (AndroidManifestFile, MonoAndroidHelper.SupportedVersions);
136+
int minApiVersion = doc.MinSdkVersion == null ? 4 : (int)doc.MinSdkVersion;
137+
cmd.AppendSwitchIfNotNull ("--min-api ", minApiVersion.ToString ());
138+
139+
if (!EnableTreeShaking)
140+
cmd.AppendSwitch ("--no-tree-shaking");
141+
if (!EnableDesugar)
142+
cmd.AppendSwitch ("--no-desugaring");
143+
if (!EnableMinify)
144+
cmd.AppendSwitch ("--no-minification");
145+
146+
var injars = new List<string> ();
147+
var libjars = new List<string> ();
148+
injars.Add (ClassesZip);
149+
if (JavaLibrariesToEmbed != null)
150+
foreach (var jarfile in JavaLibrariesToEmbed)
151+
injars.Add (jarfile.ItemSpec);
152+
libjars.Add (JavaPlatformJarPath);
153+
if (JavaLibrariesToReference != null)
154+
foreach (var jarfile in JavaLibrariesToReference.Select (p => p.ItemSpec))
155+
libjars.Add (jarfile);
156+
157+
cmd.AppendSwitchIfNotNull ("--output ", OutputDirectory);
158+
foreach (var jar in libjars)
159+
cmd.AppendSwitchIfNotNull ("--lib ", jar);
160+
foreach (var jar in injars)
161+
cmd.AppendFileNameIfNotNull (jar);
162+
163+
return cmd.ToString ();
164+
}
165+
}
166+
167+
}

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,9 @@
554554
<Compile Include="Utilities\SatelliteAssembly.cs" />
555555
<Compile Include="Tasks\AndroidApkSigner.cs" />
556556
<Compile Include="Tasks\Desugar.cs" />
557+
<Compile Include="Tasks\R8.cs" />
557558
<Compile Include="Utilities\NuGetLogger.cs" />
559+
<None Include="*.targets" />
558560
<None Include="Resources\desugar_deploy.jar">
559561
<Link>desugar_deploy.jar</Link>
560562
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
6666
<UsingTask TaskName="Xamarin.Android.Tasks.Javac" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
6767
<UsingTask TaskName="Xamarin.Android.Tasks.Desugar" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
6868
<UsingTask TaskName="Xamarin.Android.Tasks.Dx" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
69+
<UsingTask TaskName="Xamarin.Android.Tasks.R8" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
6970
<UsingTask TaskName="Xamarin.Android.Tasks.KeyTool" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
7071
<UsingTask TaskName="Xamarin.Android.Tasks.LinkAssemblies" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
7172
<UsingTask TaskName="Xamarin.Android.Tasks.Lint" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
@@ -264,6 +265,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
264265
<AndroidEnableProguard Condition="'$(AndroidEnableProguard)'==''">$(EnableProguard)</AndroidEnableProguard>
265266
<AndroidEnableMultiDex Condition="'$(AndroidEnableMultiDex)'==''">False</AndroidEnableMultiDex>
266267
<AndroidEnableDesugar Condition="'$(AndroidEnableDesugar)'==''">False</AndroidEnableDesugar>
268+
<AndroidUseR8 Condition="'$(AndroidUseR8)'==''">False</AndroidUseR8>
267269

268270
<!-- Default Java heap size to 1GB (-Xmx1G) if not specified-->
269271
<JavaMaximumHeapSize Condition=" '$(JavaMaximumHeapSize)' == '' ">1G</JavaMaximumHeapSize>
@@ -853,12 +855,36 @@ because xbuild doesn't support framework reference assemblies.
853855
/>
854856
</CreateProperty>
855857

858+
<CreateProperty Condition="'$(AndroidEnableD8)' == 'True'" Value="$(MonoAndroidToolsDirectory)\d8.jar">
859+
<Output TaskParameter="Value" PropertyName="DxJarPath"
860+
Condition="'$(DxJarPath)' == ''"
861+
/>
862+
</CreateProperty>
863+
856864
<CreateProperty Value="$(MonoAndroidToolsDirectory)\desugar_deploy.jar">
857865
<Output TaskParameter="Value" PropertyName="DesugarJarPath"
858866
Condition="'$(DesugarJarPath)' == ''"
859867
/>
860868
</CreateProperty>
861869

870+
<CreateProperty Value="$(MonoAndroidToolsDirectory)\r8.jar">
871+
<Output TaskParameter="Value" PropertyName="R8JarPath"
872+
Condition="'$(R8JarPath)' == ''"
873+
/>
874+
</CreateProperty>
875+
876+
<CreateProperty Value="--debug">
877+
<Output TaskParameter="Value" PropertyName="DxExtraArguments"
878+
Condition="'$(DxExtraArguments)' == '' And '$(AndroidEnableD8)' == 'True' And '$(Configuration)' == 'Debug'"
879+
/>
880+
</CreateProperty>
881+
882+
<CreateProperty Value="--release">
883+
<Output TaskParameter="Value" PropertyName="DxExtraArguments"
884+
Condition="'$(DxExtraArguments)' == '' And '$(AndroidEnableD8)' == 'True' And '$(Configuration)' != 'Debug'"
885+
/>
886+
</CreateProperty>
887+
862888
<CreateProperty Value="--dex --no-strict">
863889
<Output TaskParameter="Value" PropertyName="DxExtraArguments"
864890
Condition="'$(DxExtraArguments)' == ''"
@@ -2177,6 +2203,7 @@ because xbuild doesn't support framework reference assemblies.
21772203
</PropertyGroup>
21782204

21792205
<Target Name="_CompileToDalvikWithDx"
2206+
Condition="'$(AndroidUseR8)' != 'True'"
21802207
DependsOnTargets="$(_CompileToDalvikDependsOnTargets)"
21812208
Inputs="$(_CompileToDalvikInputs)"
21822209
Outputs="$(IntermediateOutputPath)_dex_stamp">
@@ -2227,8 +2254,7 @@ because xbuild doesn't support framework reference assemblies.
22272254
ProguardGeneratedApplicationConfiguration="$(IntermediateOutputPath)proguard\proguard_project_primary.cfg"
22282255
ProguardConfigurationFiles="$(ProguardConfigFiles)"
22292256
JavaLibrariesToEmbed="@(_JarsToProguard);@(_InstantRunJavaReference)"
2230-
ExternalJavaLibraries="@(AndroidExternalJavaLibrary)"
2231-
DoNotPackageJavaLibraries="@(_ResolvedDoNotPackageAttributes)"
2257+
JavaLibrariesToReference="@(AndroidExternalJavaLibrary)"
22322258
ProguardJarOutput="$(IntermediateOutputPath)proguard\__proguard_output__.jar"
22332259
EnableLogging="$(ProguardEnableLogging)"
22342260
DumpOutput="$(IntermediateOutputPath)proguard\dump.txt"
@@ -2286,8 +2312,51 @@ because xbuild doesn't support framework reference assemblies.
22862312

22872313
</Target>
22882314

2315+
<Target Name="_CompileToDalvikWithR8"
2316+
Condition="'$(AndroidUseR8)' == 'True'"
2317+
DependsOnTargets="$(_CompileToDalvikDependsOnTargets)"
2318+
Inputs="$(_CompileToDalvikInputs)"
2319+
Outputs="$(IntermediateOutputPath)_dex_stamp">
2320+
2321+
<Error
2322+
Condition="!Exists('$(R8JarPath)')"
2323+
Text="r8.jar does not exist (R8JarPath property has to point to a valid file (current value: '$(R8JarPath)')." />
2324+
2325+
<!-- remove existing dex files that may be previous multidex outputs. -->
2326+
<Delete Files="$(IntermediateOutputPath)android\bin\classes\*.dex" />
2327+
2328+
<MakeDir Directories="$(IntermediateOutputPath)proguard" />
2329+
2330+
<R8
2331+
ToolPath="$(JavaToolPath)"
2332+
JavaMaximumHeapSize="$(JavaMaximumHeapSize)"
2333+
JavaOptions="$(JavaOptions)"
2334+
R8JarPath="$(R8JarPath)"
2335+
AndroidManifestFile="$(IntermediateOutputPath)android\AndroidManifest.xml"
2336+
OutputDirectory="$(IntermediateOutputPath)android\"
2337+
Configuration="$(Configuration)"
2338+
JavaPlatformJarPath="$(JavaPlatformJarPath)"
2339+
ClassesZip="$(IntermediateOutputPath)android\bin\classes.zip"
2340+
JavaLibrariesToEmbed="@(_JavaLibrariesToCompile);@(_InstantRunJavaReference)"
2341+
JavaLibrariesToReference="@(AndroidExternalJavaLibrary)"
2342+
EnableDesugar="$(AndroidEnableDesugar)"
2343+
EnableTreeShaking="$(AndroidEnableProguard)"
2344+
AndroidSdkDirectory="$(_AndroidSdkDirectory)"
2345+
AcwMapFile="$(_AcwMapFile)"
2346+
ProguardCommonXamarinConfiguration="$(IntermediateOutputPath)proguard\proguard_xamarin.cfg"
2347+
ProguardGeneratedReferenceConfiguration="$(_ProguardProjectConfiguration)"
2348+
ProguardGeneratedApplicationConfiguration="$(IntermediateOutputPath)proguard\proguard_project_primary.cfg"
2349+
ProguardConfigurationFiles="$(ProguardConfigFiles)"
2350+
MultiDexMainDexListFile="$(_AndroidMainDexListFile)"
2351+
R8ExtraArguments="$(R8ExtraArguments)"
2352+
/>
2353+
2354+
<Touch Files="$(IntermediateOutputPath)_dex_stamp" AlwaysCreate="true" />
2355+
2356+
</Target>
2357+
22892358
<Target Name="_CompileDex"
2290-
DependsOnTargets="_CompileToDalvikWithDx">
2359+
DependsOnTargets="_CompileToDalvikWithDx;_CompileToDalvikWithR8">
22912360

22922361
<ItemGroup>
22932362
<_DexFile Include="$(IntermediateOutputPath)android\bin\dex\*.dex" />
File renamed without changes.
File renamed without changes.

build-tools/r8/r8.targets renamed to src/r8/r8.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
</Target>
5555

5656
<Target Name="_CopyR8">
57+
<Copy
58+
SourceFiles="..\..\external\r8\build\libs\d8.jar"
59+
DestinationFolder="$(XAInstallPrefix)\xbuild\Xamarin\Android\"
60+
SkipUnchangedFiles="true"
61+
/>
5762
<Copy
5863
SourceFiles="..\..\external\r8\build\libs\r8.jar"
5964
DestinationFolder="$(XAInstallPrefix)\xbuild\Xamarin\Android\"

0 commit comments

Comments
 (0)