Skip to content
Open
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
55 changes: 55 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/R8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public class R8 : D8
public ITaskItem []? ProguardConfigurationFiles { get; set; }
public bool UseTrimmableNativeAotProguardConfiguration { get; set; }

// User-authored AndroidJavaSource (Bind != true) .java files. These have no managed peer and are
// therefore absent from the acw-map, so they must be kept explicitly when shrinking is enabled.
public ITaskItem []? JavaSourceFiles { get; set; }

protected override string MainClass => "com.android.tools.r8.R8";

readonly List<string> tempFiles = new List<string> ();
Expand All @@ -52,6 +56,52 @@ public override bool RunTask ()
}
}

// Derive the fully-qualified Java type name from each user .java source file. Java requires the
// public top-level type name to match the file name, so '<package>.<FileNameWithoutExtension>' is
// the type to keep. Files that no longer exist are skipped.
IEnumerable<string> GetUserJavaTypes ()
{
if (JavaSourceFiles == null) {
yield break;
}
var seen = new HashSet<string> (StringComparer.Ordinal);
foreach (var item in JavaSourceFiles) {
var path = item.ItemSpec;
if (path.IsNullOrEmpty () || !File.Exists (path)) {
continue;
}
var typeName = Path.GetFileNameWithoutExtension (path);
var package = ReadJavaPackage (path);
if (!package.IsNullOrEmpty ()) {
typeName = $"{package}.{typeName}";
}
if (seen.Add (typeName)) {
yield return typeName;
}
}
}

static string? ReadJavaPackage (string path)
{
foreach (var raw in File.ReadLines (path)) {
var line = raw.Trim ();
if (line.Length == 0 || line.StartsWith ("//", StringComparison.Ordinal) || line.StartsWith ("*", StringComparison.Ordinal) || line.StartsWith ("/*", StringComparison.Ordinal)) {
continue;
}
if (line.StartsWith ("package ", StringComparison.Ordinal)) {
var end = line.IndexOf (';');
if (end > "package ".Length) {
return line.Substring ("package ".Length, end - "package ".Length).Trim ();
}
}
// The package declaration, if present, must precede any type declaration.
if (line.StartsWith ("import ", StringComparison.Ordinal) || line.Contains ("class ") || line.Contains ("interface ") || line.Contains ("enum ")) {
break;
}
}
return null;
}
Comment on lines +84 to +103

/// <summary>
/// Override CreateResponseFile to add R8-specific arguments to the response file.
/// This ensures all arguments are passed via response file to avoid command line length limits.
Expand Down Expand Up @@ -109,6 +159,11 @@ protected override string CreateResponseFile ()
foreach (var java in javaTypes) {
appcfg.WriteLine ($"-keep class {java} {{ *; }}");
}
// User-authored AndroidJavaSource (Bind != true) has no managed peer and is absent
// from the acw-map, so keep it explicitly; otherwise shrinking removes it.
foreach (var java in GetUserJavaTypes ()) {
appcfg.WriteLine ($"-keep class {java} {{ *; }}");
}
}
}
if (!ProguardCommonXamarinConfiguration.IsNullOrWhiteSpace ()) {
Expand Down
4 changes: 4 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ Copyright (C) 2018 Xamarin. All rights reserved.
<ItemGroup>
<_AndroidD8MapDiagnostics Condition=" '$(AndroidD8IgnoreWarnings)' == 'true' " Include="warning" To="info" />
<_AndroidR8MapDiagnostics Condition=" '$(AndroidR8IgnoreWarnings)' == 'true' " Include="warning" To="info" />
<!-- User-authored AndroidJavaSource (Bind != True) is not in the acw-map; pass it to R8 so it
is kept when shrinking is enabled rather than silently removed. -->
<_R8KeepJavaSource Include="@(AndroidJavaSource)" Condition=" '%(AndroidJavaSource.Bind)' != 'True' " />
</ItemGroup>

<R8
Expand All @@ -69,6 +72,7 @@ Copyright (C) 2018 Xamarin. All rights reserved.
EnableDesugar="$(AndroidEnableDesugar)"
AndroidSdkBuildToolsPath="$(AndroidSdkBuildToolsPath)"
AcwMapFile="$(_AcwMapFile)"
JavaSourceFiles="@(_R8KeepJavaSource)"
ProguardCommonXamarinConfiguration="$(IntermediateOutputPath)proguard\proguard_xamarin.cfg"
ProguardGeneratedReferenceConfiguration="$(_ProguardProjectConfiguration)"
ProguardGeneratedApplicationConfiguration="$(IntermediateOutputPath)proguard\proguard_project_primary.cfg"
Expand Down
Loading