Skip to content

Commit

Permalink
[msbuild][r8] add r8 support to alter dx, proguard and desugar.
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
atsushieno committed Jul 4, 2018
1 parent ccb3c80 commit d5ddba9
Show file tree
Hide file tree
Showing 17 changed files with 375 additions and 39 deletions.
7 changes: 7 additions & 0 deletions Documentation/guides/BuildProcess.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ when packaing Release applications.

This property is `False` by default.

- **AndroidEnableD8** – A boolean property that determines
whether or not use Google's new dexer (dx.jar alternative).
- **AndroidEnableMultiDex** – A boolean property that
determines whether or not multi-dex support will be used in the
final `.apk`.
Expand Down Expand Up @@ -419,6 +422,10 @@ when packaing Release applications.
This property should be `True` for Debug builds, and `False` for
Release projects.
- **AndroidUseR8** – A boolean property that determines
whether or not use Google's new Java code shlinker (proguard
alternative).

- **AotAssemblies** – A boolean property that determines
whether or not assemblies will be Ahead-of-Time compiled into
native code and included in the `.apk`.
Expand Down
8 changes: 6 additions & 2 deletions Xamarin.Android.sln
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.Andro
EndProject
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}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "r8", "src\r8\r8.csproj", "{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proprietary", "build-tools\proprietary\proprietary.csproj", "{D93CAC27-3893-42A3-99F1-2BCA72E186F4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "download-bundle", "build-tools\download-bundle\download-bundle.csproj", "{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}"
Expand Down Expand Up @@ -358,6 +359,10 @@ Global
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Debug|AnyCPU.Build.0 = Debug|AnyCPU
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B}.Release|AnyCPU.Build.0 = Release|AnyCPU
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63}.Release|AnyCPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -418,8 +423,7 @@ Global
{B8105878-D423-4159-A3E7-028298281EC6} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{1E5501E8-49C1-4659-838D-CC9720C5208F} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{D93CAC27-3893-42A3-99F1-2BCA72E186F4} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
{1DA0CB12-5508-4E83-A242-0C8D6D99A49B} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
{1BAFA0CC-0377-46CE-AB7B-7BB2E7B62F63} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {53A1F287-EFB2-4D97-A4BB-4A5E145613F6}
Expand Down
9 changes: 0 additions & 9 deletions build-tools/r8/r8.csproj

This file was deleted.

9 changes: 9 additions & 0 deletions external/depot_tools.tpnitems
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition=" '$(TpnIncludeExternalDependencies)' == 'True' ">
<ThirdPartyNotice Include="google/depot_tools">
<LicenseFile>$(MSBuildThisFileDirectory)\depot_tools\LICENSE</LicenseFile>
<SourceUrl>https://chromium.googlesource.com/chromium/tools/depot_tools.git</SourceUrl>
</ThirdPartyNotice>
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions external/r8.tpnitems
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition=" '$(TpnIncludeExternalDependencies)' == 'True' ">
<ThirdPartyNotice Include="google/r8">
<LicenseFile>$(MSBuildThisFileDirectory)\r8\LICENSE</LicenseFile>
<SourceUrl>https://r8.googlesource.com/r8/</SourceUrl>
</ThirdPartyNotice>
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions src/Mono.Android/Test/Mono.Android-Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<AndroidUseR8>true</AndroidUseR8>
<AndroidEnableD8>true</AndroidEnableD8>
</PropertyGroup>
<Import Project="..\..\..\Configuration.props" />
<PropertyGroup>
Expand Down
37 changes: 15 additions & 22 deletions src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,17 @@ public class Proguard : ToolTask
[Required]
public string ProguardJarOutput { get; set; }

[Required]
public string ProguardGeneratedReferenceConfiguration { get; set; }

[Required]
public string ProguardGeneratedApplicationConfiguration { get; set; }

[Required]
public string ProguardCommonXamarinConfiguration { get; set; }

[Required]
public string ProguardConfigurationFiles { get; set; }

public ITaskItem[] JavaLibrariesToEmbed { get; set; }

public ITaskItem[] ExternalJavaLibraries { get; set; }
public ITaskItem[] JavaLibrariesToReference { get; set; }

public ITaskItem[] DoNotPackageJavaLibraries { get; set; }

public bool UseProguard { get; set; }

public string JavaOptions { get; set; }
Expand Down Expand Up @@ -86,14 +80,13 @@ public override bool Execute ()
Log.LogDebugMessage (" JavaPlatformJarPath: {0}", JavaPlatformJarPath);
Log.LogDebugMessage (" ClassesOutputDirectory: {0}", ClassesOutputDirectory);
Log.LogDebugMessage (" AcwMapFile: {0}", AcwMapFile);
Log.LogDebugMessage (" ProguardGeneratedApplicationConfiguration: {0}", ProguardGeneratedApplicationConfiguration);
Log.LogDebugMessage (" ProguardJarOutput: {0}", ProguardJarOutput);
Log.LogDebugTaskItems (" ProguardGeneratedReferenceConfiguration:", ProguardGeneratedReferenceConfiguration);
Log.LogDebugTaskItems (" ProguardGeneratedApplicationConfiguration:", ProguardGeneratedApplicationConfiguration);
Log.LogDebugTaskItems (" ProguardCommonXamarinConfiguration:", ProguardCommonXamarinConfiguration);
Log.LogDebugTaskItems (" ProguardConfigurationFiles:", ProguardConfigurationFiles);
Log.LogDebugTaskItems (" ExternalJavaLibraries:", ExternalJavaLibraries);
Log.LogDebugTaskItems (" DoNotPackageJavaLibraries:", DoNotPackageJavaLibraries);
Log.LogDebugTaskItems (" JavaLibrariesToEmbed:", JavaLibrariesToEmbed);
Log.LogDebugTaskItems (" JavaLibrariesToReference:", JavaLibrariesToReference);
Log.LogDebugMessage (" UseProguard: {0}", UseProguard);
Log.LogDebugMessage (" EnableLogging: {0}", EnableLogging);
Log.LogDebugMessage (" DumpOutput: {0}", DumpOutput);
Expand Down Expand Up @@ -139,15 +132,9 @@ protected override string GenerateCommandLineCommands ()
// skip invalid lines
}

var injars = new List<string> ();
var libjars = new List<string> ();
injars.Add (classesZip);
if (JavaLibrariesToEmbed != null)
foreach (var jarfile in JavaLibrariesToEmbed)
injars.Add (jarfile.ItemSpec);

using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration))
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);

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

var injars = new List<string> ();
var libjars = new List<string> ();
injars.Add (classesZip);
if (JavaLibrariesToEmbed != null)
foreach (var jarfile in JavaLibrariesToEmbed)
injars.Add (jarfile.ItemSpec);
libjars.Add (JavaPlatformJarPath);
if (ExternalJavaLibraries != null)
foreach (var jarfile in ExternalJavaLibraries.Select (p => p.ItemSpec))
if (JavaLibrariesToReference != null)
foreach (var jarfile in JavaLibrariesToReference.Select (p => p.ItemSpec))
libjars.Add (jarfile);

cmd.AppendSwitchUnquotedIfNotNull ("-injars ", "\"'" + string.Join ($"'{ProguardInputJarFilter}{Path.PathSeparator}'", injars.Distinct ()) + $"'{ProguardInputJarFilter}\"");
Expand Down
173 changes: 173 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/R8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Copyright (C) 2018 Xamarin, Inc. All rights reserved.

using System;
using System.Linq;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Text;
using System.Collections.Generic;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
{

public class R8 : JavaToolTask
{
[Required]
public string R8JarPath { get; set; }

[Required]
public string OutputDirectory { get; set; }

public string Configuration { get; set; }

// It is loaded to calculate --min-api, which is used by desugaring part to determine which levels of desugaring it performs.
[Required]
public string AndroidManifestFile { get; set; }

// general r8 feature options.
public bool EnableDesugar { get; set; }
public bool EnableMinify { get; set; } // The Task has the option, but it is not supported at all.
public bool EnableTreeShaking { get; set; }

// Java libraries to embed or reference
[Required]
public string ClassesZip { get; set; }
[Required]
public string JavaPlatformJarPath { get; set; }
public ITaskItem [] JavaLibrariesToEmbed { get; set; }
public ITaskItem [] JavaLibrariesToReference { get; set; }

// used for proguard configuration settings
[Required]
public string AndroidSdkDirectory { get; set; }
[Required]
public string AcwMapFile { get; set; }
public string ProguardGeneratedReferenceConfiguration { get; set; }
public string ProguardGeneratedApplicationConfiguration { get; set; }
public string ProguardCommonXamarinConfiguration { get; set; }
[Required]
public string ProguardConfigurationFiles { get; set; }
public string ProguardMappingOutput { get; set; }

// multidex
public bool EnableMultiDex { get; set; }
public string MultiDexMainDexListFile { get; set; }

public string R8ExtraArguments { get; set; }

public override bool Execute ()
{
Log.LogDebugMessage ("R8 Task");
Log.LogDebugTaskItems (" R8JarPath: ", R8JarPath);
Log.LogDebugTaskItems (" OutputDirectory: ", OutputDirectory);
Log.LogDebugTaskItems (" AndroidManifestFile: ", AndroidManifestFile);
Log.LogDebugMessage (" Configuration: {0}", Configuration);
Log.LogDebugTaskItems (" JavaPlatformJarPath: ", JavaPlatformJarPath);
Log.LogDebugTaskItems (" ClassesZip: ", ClassesZip);
Log.LogDebugTaskItems (" JavaLibrariesToEmbed: ", JavaLibrariesToEmbed);
Log.LogDebugTaskItems (" JavaLibrariesToReference: ", JavaLibrariesToReference);
Log.LogDebugMessage (" EnableDesugar: {0}", EnableDesugar);
Log.LogDebugMessage (" EnableTreeShaking: {0}", EnableTreeShaking);
Log.LogDebugTaskItems (" AndroidSdkDirectory:", AndroidSdkDirectory);
Log.LogDebugTaskItems (" AcwMapFile: ", AcwMapFile);
Log.LogDebugTaskItems (" ProguardGeneratedReferenceConfiguration:", ProguardGeneratedReferenceConfiguration);
Log.LogDebugTaskItems (" ProguardGeneratedApplicationConfiguration:", ProguardGeneratedApplicationConfiguration);
Log.LogDebugTaskItems (" ProguardCommonXamarinConfiguration:", ProguardCommonXamarinConfiguration);
Log.LogDebugTaskItems (" ProguardConfigurationFiles:", ProguardConfigurationFiles);
Log.LogDebugTaskItems (" ProguardMappingOutput:", ProguardMappingOutput);
Log.LogDebugMessage (" EnableMultiDex: {0}", EnableMultiDex);
Log.LogDebugTaskItems (" MultiDexMainDexListFile: ", MultiDexMainDexListFile);
Log.LogDebugTaskItems (" R8ExtraArguments: ", R8ExtraArguments);

return base.Execute ();
}

protected override string GenerateCommandLineCommands ()
{
var cmd = new CommandLineBuilder ();

cmd.AppendSwitchIfNotNull ("-jar ", R8JarPath);

if (!string.IsNullOrEmpty (R8ExtraArguments))
cmd.AppendSwitch (R8ExtraArguments); // it should contain "--dex".
if (Configuration.Equals ("Debug", StringComparison.OrdinalIgnoreCase))
cmd.AppendSwitch ("--debug");

// generating proguard application configuration
if (EnableTreeShaking) {
var acwLines = File.ReadAllLines (AcwMapFile);
using (var appcfg = File.CreateText (ProguardGeneratedApplicationConfiguration))
for (int i = 0; i + 2 < acwLines.Length; i += 3)
try {
var line = acwLines [i + 2];
var java = line.Substring (line.IndexOf (';') + 1);
appcfg.WriteLine ("-keep class " + java + " { *; }");
} catch {
// skip invalid lines
}
if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration))
using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration))
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
var configs = ProguardConfigurationFiles
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
.Replace ("{intermediate.common.xamarin}", ProguardCommonXamarinConfiguration)
.Replace ("{intermediate.references}", ProguardGeneratedReferenceConfiguration)
.Replace ("{intermediate.application}", ProguardGeneratedApplicationConfiguration)
.Replace ("{project}", string.Empty) // current directory anyways.
.Split (';')
.Select (s => s.Trim ())
.Where (s => !string.IsNullOrWhiteSpace (s));
var enclosingChar = "\"";
foreach (var file in configs) {
if (File.Exists (file))
cmd.AppendSwitchIfNotNull ("--pg-conf ", file);
else
Log.LogWarning ("Proguard configuration file '{0}' was not found.", file);
}
cmd.AppendSwitchIfNotNull ("--pg-map-output ", ProguardMappingOutput);

// multidexing
if (EnableMultiDex) {
if (!string.IsNullOrWhiteSpace (MultiDexMainDexListFile) && File.Exists (MultiDexMainDexListFile))
cmd.AppendSwitchIfNotNull ("--main-dex-list ", MultiDexMainDexListFile);
else
Log.LogWarning ($"MultiDex is enabled, but main dex list file '{MultiDexMainDexListFile}' does not exist.");
}
}

// desugaring
var doc = AndroidAppManifest.Load (AndroidManifestFile, MonoAndroidHelper.SupportedVersions);
int minApiVersion = doc.MinSdkVersion == null ? 4 : (int)doc.MinSdkVersion;
cmd.AppendSwitchIfNotNull ("--min-api ", minApiVersion.ToString ());

if (!EnableTreeShaking)
cmd.AppendSwitch ("--no-tree-shaking");
if (!EnableDesugar)
cmd.AppendSwitch ("--no-desugaring");
if (!EnableMinify)
cmd.AppendSwitch ("--no-minification");

var injars = new List<string> ();
var libjars = new List<string> ();
injars.Add (ClassesZip);
if (JavaLibrariesToEmbed != null)
foreach (var jarfile in JavaLibrariesToEmbed)
injars.Add (jarfile.ItemSpec);
libjars.Add (JavaPlatformJarPath);
if (JavaLibrariesToReference != null)
foreach (var jarfile in JavaLibrariesToReference.Select (p => p.ItemSpec))
libjars.Add (jarfile);

cmd.AppendSwitchIfNotNull ("--output ", OutputDirectory);
foreach (var jar in libjars)
cmd.AppendSwitchIfNotNull ("--lib ", jar);
foreach (var jar in injars)
cmd.AppendFileNameIfNotNull (jar);

return cmd.ToString ();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,49 @@ public partial class BuildTest : BaseTest
/* isRelease */ true,
/* enableProguard */ true,
/* useLatestSdk */ true,
/* useR8 */ false,
},
new Object [] {
/* isRelease */ true,
/* enableProguard */ false,
/* useLatestSdk */ true,
/* useR8 */ false,
},
new Object [] {
/* isRelease */ false,
/* enableProguard */ true,
/* useLatestSdk */ true,
/* useR8 */ false,
},
new Object [] {
/* isRelease */ false,
/* enableProguard */ false,
/* useLatestSdk */ true,
/* useR8 */ false,
},
new Object [] {
/* isRelease */ true,
/* enableProguard */ true,
/* useLatestSdk */ true,
/* useR8 */ true,
},
new Object [] {
/* isRelease */ true,
/* enableProguard */ false,
/* useLatestSdk */ true,
/* useR8 */ true,
},
new Object [] {
/* isRelease */ false,
/* enableProguard */ true,
/* useLatestSdk */ true,
/* useR8 */ true,
},
new Object [] {
/* isRelease */ false,
/* enableProguard */ false,
/* useLatestSdk */ true,
/* useR8 */ true,
},
};
static object [] TakeSimpleFlag = new object [] {
Expand Down
Loading

0 comments on commit d5ddba9

Please sign in to comment.