Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R8 integration #1489

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
path = external/xamarin-android-tools
url = https://github.com/xamarin/xamarin-android-tools
branch = master
[submodule "external/depot_tools"]
path = external/depot_tools
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
[submodule "external/r8"]
path = external/r8
url = https://r8.googlesource.com/r8
[submodule "external/dlfcn-win32"]
path = external/dlfcn-win32
url = https://github.com/dlfcn-win32/dlfcn-win32.git
Expand Down
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
1 change: 1 addition & 0 deletions external/depot_tools
Submodule depot_tools added at a16b4c
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>
1 change: 1 addition & 0 deletions external/r8
Submodule r8 added at d7c62c
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 = "\"";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atsushieno this might depend on the platform, I seem to remember on windows vs Mac we had to use different enclosing chars. Might be worth double checking to be on the safe side. We've been bitten by this before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're kind of right, I saw the switch when the relevant files were passed in single argument in older proguard. I should simply use AppendSwitchIfNotNull() here.

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