Skip to content

Commit c537dd2

Browse files
authored
[Xamarin.Android.Build.Tasks] Use ProGuard config files from .aar files. (#5310)
Fixes: #3752 `.aar` [can contain `proguard.txt` files][0] > **Library dependencies** > *Location*: AAR libraries: `<library-dir>/proguard.txt` > *Description*: If an AAR library is published with its own ProGuard > rules file, and you include that AAR as a compile-time dependency, > R8 automatically applies its rules when compiling your project. Update the `@(ProguardConfiguration)` item group to include `proguard.cfg` and `proguard.txt` files in the project directory, and for Library project builds add the contents of all `@(ProguardConfiguration)` files into a `proguard.txt` entry within the generated `.aar` file (fcd7cf8). Update the `_ResolveLibraryProjectImports` target and the `<ResolveLibraryProjectImports/>` MSBuild task to look for `proguard.txt` files contained within `.aar` packages, and update the `<ReadLibraryProjectImportsCache/>` MSBuild task so that `proguard.txt` files within `.aar` packages are added to the `@(ProguardConfiguration)` item group of App builds, so that they are appropriately passed to the `_CompileToDalvik` target and used when converting Java bytecode into Dalvik bytecode. TODO? The Android documentation mentions that `.jar` files can also contain ProGuard files: > *Location*: JAR libraries: `<library-dir>/META-INF/proguard/` We do not currently use ProGuard files contained within `.jar` files. [0]: https://developer.android.com/studio/build/shrink-code
1 parent f149c25 commit c537dd2

File tree

7 files changed

+62
-14
lines changed

7 files changed

+62
-14
lines changed

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/Sdk/AutoImport.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ https://github.com/dotnet/designs/blob/4703666296f5e59964961464c25807c727282cae/
4545
<AndroidNativeLibrary Include="**\*.so" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
4646
<JavaSourceJar Include="**\*-source.jar;**\*-sources.jar;**\*-src.jar" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
4747
<AndroidJavaSource Include="**\*.java" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
48+
<ProguardConfiguration Include="**\proguard.cfg" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
49+
<ProguardConfiguration Include="**\proguard.txt" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
4850
</ItemGroup>
4951

5052
</Project>

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ projects.
4949
<_CreateAarInputs Include="@(AndroidJavaLibrary)" />
5050
<_CreateAarInputs Include="@(EmbeddedJar)" />
5151
<_CreateAarInputs Include="@(EmbeddedNativeLibrary)" />
52+
<_CreateAarInputs Include="@(ProguardConfiguration)" />
5253
</ItemGroup>
5354
<Hash
5455
ItemsToHash="@(_CreateAarInputs)"
@@ -80,6 +81,7 @@ projects.
8081
AndroidEnvironment="@(AndroidEnvironment)"
8182
JarFiles="@(AndroidJavaLibrary);@(EmbeddedJar)"
8283
NativeLibraries="@(EmbeddedNativeLibrary)"
84+
ProguardConfigurationFiles="@(ProguardConfiguration)"
8385
OutputFile="$(_AarOutputPath)"
8486
/>
8587
<ItemGroup>

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class CreateAar : AndroidTask
2323

2424
public ITaskItem [] NativeLibraries { get; set; }
2525

26+
public ITaskItem [] ProguardConfigurationFiles { get; set; }
27+
2628
[Required]
2729
public string AssetDirectory { get; set; }
2830

@@ -103,6 +105,13 @@ public override bool RunTask ()
103105
existingEntries.Remove (archivePath);
104106
}
105107
}
108+
if (ProguardConfigurationFiles != null) {
109+
var sb = new StringBuilder ();
110+
foreach (var file in ProguardConfigurationFiles) {
111+
sb.AppendLine (File.ReadAllText (file.ItemSpec));
112+
}
113+
aar.AddEntry ("proguard.txt", sb.ToString (), Files.UTF8withoutBOM);
114+
}
106115
foreach (var entry in existingEntries) {
107116
Log.LogDebugMessage ($"Removing {entry} as it is not longer required.");
108117
aar.DeleteEntry (entry);

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
//
1+
//
22
// ReadLibraryProjectImportsCache.cs
3-
//
3+
//
44
// Author:
55
// Dean Ellis <[email protected]>
6-
//
6+
//
77
// Copyright (c) 2015 Xamarin Inc.
8-
//
8+
//
99
// Permission is hereby granted, free of charge, to any person obtaining a copy
1010
// of this software and associated documentation files (the "Software"), to deal
1111
// in the Software without restriction, including without limitation the rights
1212
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1313
// copies of the Software, and to permit persons to whom the Software is
1414
// furnished to do so, subject to the following conditions:
15-
//
15+
//
1616
// The above copyright notice and this permission notice shall be included in
1717
// all copies or substantial portions of the Software.
18-
//
18+
//
1919
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2020
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2121
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -38,7 +38,7 @@ public class ReadLibraryProjectImportsCache : AndroidTask
3838
public override string TaskPrefix => "RLC";
3939

4040
[Required]
41-
public string CacheFile { get; set;}
41+
public string CacheFile { get; set;}
4242

4343
[Output]
4444
public ITaskItem [] Jars { get; set; }
@@ -55,6 +55,9 @@ public class ReadLibraryProjectImportsCache : AndroidTask
5555
[Output]
5656
public ITaskItem [] ResolvedResourceDirectoryStamps { get; set; }
5757

58+
[Output]
59+
public ITaskItem [] ProguardConfigFiles { get; set; }
60+
5861
public override bool RunTask ()
5962
{
6063
Log.LogDebugMessage ("Task ReadLibraryProjectImportsCache");
@@ -70,12 +73,14 @@ public override bool RunTask ()
7073
ResolvedEnvironmentFiles = doc.GetPathsAsTaskItems ("ResolvedEnvironmentFiles", "ResolvedEnvironmentFile");
7174
ResolvedResourceDirectoryStamps = doc.GetPathsAsTaskItems ("ResolvedResourceDirectoryStamps"
7275
, "ResolvedResourceDirectoryStamp");
73-
76+
ProguardConfigFiles = doc.GetPathsAsTaskItems ("ProguardConfigFiles", "ProguardConfigFile");
77+
7478
Log.LogDebugTaskItems (" Jars: ", Jars);
7579
Log.LogDebugTaskItems (" ResolvedAssetDirectories: ", ResolvedAssetDirectories);
7680
Log.LogDebugTaskItems (" ResolvedResourceDirectories: ", ResolvedResourceDirectories);
7781
Log.LogDebugTaskItems (" ResolvedEnvironmentFiles: ", ResolvedEnvironmentFiles);
7882
Log.LogDebugTaskItems (" ResolvedResourceDirectoryStamps: ", ResolvedResourceDirectoryStamps);
83+
Log.LogDebugTaskItems (" ProguardConfigFiles: ", ProguardConfigFiles);
7984

8085
return !Log.HasLoggedErrors;
8186
}

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public class ResolveLibraryProjectImports : AndroidTask
5959
[Output]
6060
public ITaskItem [] ResolvedResourceDirectoryStamps { get; set; }
6161

62+
[Output]
63+
public ITaskItem [] ProguardConfigFiles { get; set; }
64+
6265
internal const string OriginalFile = "OriginalFile";
6366
internal const string AndroidSkipResourceProcessing = "AndroidSkipResourceProcessing";
6467

@@ -83,10 +86,11 @@ public override bool RunTask ()
8386
var resolvedResourceDirectories = new List<ITaskItem> ();
8487
var resolvedAssetDirectories = new List<ITaskItem> ();
8588
var resolvedEnvironmentFiles = new List<ITaskItem> ();
89+
var proguardConfigFiles = new List<ITaskItem> ();
8690

8791
assemblyMap.Load (AssemblyIdentityMapFile);
8892
try {
89-
Extract (jars, resolvedResourceDirectories, resolvedAssetDirectories, resolvedEnvironmentFiles);
93+
Extract (jars, resolvedResourceDirectories, resolvedAssetDirectories, resolvedEnvironmentFiles, proguardConfigFiles);
9094
} catch (ZipIOException ex) {
9195
Log.LogCodedError ("XA1004", ex.Message);
9296
Log.LogDebugMessage (ex.ToString ());
@@ -96,6 +100,7 @@ public override bool RunTask ()
96100
ResolvedResourceDirectories = resolvedResourceDirectories.ToArray ();
97101
ResolvedAssetDirectories = resolvedAssetDirectories.ToArray ();
98102
ResolvedEnvironmentFiles = resolvedEnvironmentFiles.ToArray ();
103+
ProguardConfigFiles = proguardConfigFiles.ToArray ();
99104

100105
ResolvedResourceDirectoryStamps = ResolvedResourceDirectories
101106
.Select (s => new TaskItem (Path.GetFullPath (Path.Combine (s.ItemSpec, "../..")) + ".stamp"))
@@ -116,14 +121,15 @@ public override bool RunTask ()
116121
new XElement ("Jars",
117122
Jars.Select(e => new XElement ("Jar", e))),
118123
new XElement ("ResolvedResourceDirectories",
119-
ResolvedResourceDirectories.ToXElements ("ResolvedResourceDirectory", knownMetadata)
120-
),
124+
ResolvedResourceDirectories.ToXElements ("ResolvedResourceDirectory", knownMetadata)),
121125
new XElement ("ResolvedAssetDirectories",
122126
ResolvedAssetDirectories.ToXElements ("ResolvedAssetDirectory", knownMetadata)),
123127
new XElement ("ResolvedEnvironmentFiles",
124128
ResolvedEnvironmentFiles.ToXElements ("ResolvedEnvironmentFile", knownMetadata)),
125129
new XElement ("ResolvedResourceDirectoryStamps",
126-
ResolvedResourceDirectoryStamps.ToXElements ("ResolvedResourceDirectoryStamp", knownMetadata))
130+
ResolvedResourceDirectoryStamps.ToXElements ("ResolvedResourceDirectoryStamp", knownMetadata)),
131+
new XElement ("ProguardConfigFiles",
132+
ProguardConfigFiles.ToXElements ("ProguardConfigFile", knownMetadata))
127133
));
128134
document.SaveIfChanged (CacheFile);
129135
}
@@ -135,6 +141,7 @@ public override bool RunTask ()
135141
Log.LogDebugTaskItems (" ResolvedAssetDirectories: ", ResolvedAssetDirectories);
136142
Log.LogDebugTaskItems (" ResolvedEnvironmentFiles: ", ResolvedEnvironmentFiles);
137143
Log.LogDebugTaskItems (" ResolvedResourceDirectoryStamps: ", ResolvedResourceDirectoryStamps);
144+
Log.LogDebugTaskItems (" ProguardConfigFiles:", ProguardConfigFiles);
138145

139146
return !Log.HasLoggedErrors;
140147
}
@@ -145,7 +152,8 @@ void Extract (
145152
IDictionary<string, ITaskItem> jars,
146153
ICollection<ITaskItem> resolvedResourceDirectories,
147154
ICollection<ITaskItem> resolvedAssetDirectories,
148-
ICollection<ITaskItem> resolvedEnvironments)
155+
ICollection<ITaskItem> resolvedEnvironments,
156+
ICollection<ITaskItem> proguardConfigFiles)
149157
{
150158
// lets "upgrade" the old directory.
151159
string oldPath = Path.GetFullPath (Path.Combine (OutputImportDirectory, "..", "__library_projects__"));
@@ -345,6 +353,7 @@ void Extract (
345353
string resDir = Path.Combine (importsDir, "res");
346354
string resDirArchive = Path.Combine (resDir, "..", "res.zip");
347355
string assetsDir = Path.Combine (importsDir, "assets");
356+
string proguardFile = Path.Combine (importsDir, "proguard.txt");
348357

349358
bool updated = false;
350359
string aarHash = Files.HashFile (aarFile.ItemSpec);
@@ -431,6 +440,11 @@ void Extract (
431440
resolvedAssetDirectories.Add (new TaskItem (Path.GetFullPath (assetsDir), new Dictionary<string, string> {
432441
{ OriginalFile, aarFullPath },
433442
}));
443+
if (File.Exists (proguardFile)) {
444+
proguardConfigFiles.Add (new TaskItem (Path.GetFullPath (proguardFile), new Dictionary<string, string> {
445+
{ OriginalFile, aarFullPath },
446+
}));
447+
}
434448
}
435449
}
436450

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public void DotNetBuildLibrary (bool isRelease, bool duplicateAar)
6262
new AndroidItem.AndroidResource (() => "Resources\\drawable\\IMALLCAPS.png") {
6363
BinaryContent = () => XamarinAndroidApplicationProject.icon_binary_mdpi,
6464
},
65+
new AndroidItem.ProguardConfiguration ("proguard.txt") {
66+
TextContent = () => @"-ignorewarnings",
67+
},
6568
}
6669
};
6770
libC.OtherBuildItems.Add (new AndroidItem.AndroidAsset ("Assets\\bar\\bar.txt") {
@@ -73,6 +76,13 @@ public void DotNetBuildLibrary (bool isRelease, bool duplicateAar)
7376
var libCBuilder = CreateDotNetBuilder (libC, Path.Combine (path, libC.ProjectName));
7477
Assert.IsTrue (libCBuilder.Build (), $"{libC.ProjectName} should succeed");
7578

79+
var aarPath = Path.Combine (FullProjectDirectory, libC.OutputPath, $"{libC.ProjectName}.aar");
80+
FileAssert.Exists (aarPath);
81+
using (var aar = ZipHelper.OpenZip (aarPath)) {
82+
aar.AssertContainsEntry (aarPath, "assets/bar/bar.txt");
83+
aar.AssertContainsEntry (aarPath, "proguard.txt");
84+
}
85+
7686
var libB = new XASdkProject (outputType: "Library") {
7787
ProjectName = "LibraryB",
7888
IsRelease = isRelease,
@@ -111,6 +121,9 @@ public Foo ()
111121
Encoding = Encoding.ASCII,
112122
TextContent = () => ResourceData.JavaSourceTestExtension,
113123
},
124+
new AndroidItem.ProguardConfiguration ("proguard.txt") {
125+
TextContent = () => @"-ignorewarnings",
126+
},
114127
}
115128
};
116129
libB.OtherBuildItems.Add (new AndroidItem.AndroidEnvironment ("env.txt") {
@@ -140,7 +153,7 @@ public Foo ()
140153

141154
// Check .aar file for class library
142155
var libBOutputPath = Path.Combine (FullProjectDirectory, libB.OutputPath);
143-
var aarPath = Path.Combine (libBOutputPath, $"{libB.ProjectName}.aar");
156+
aarPath = Path.Combine (libBOutputPath, $"{libB.ProjectName}.aar");
144157
FileAssert.Exists (aarPath);
145158
FileAssert.Exists (Path.Combine (libBOutputPath, "bar.aar"));
146159
using (var aar = ZipHelper.OpenZip (aarPath)) {
@@ -196,6 +209,8 @@ public Foo ()
196209
var intermediate = Path.Combine (FullProjectDirectory, appA.IntermediateOutputPath);
197210
var dexFile = Path.Combine (intermediate, "android", "bin", "classes.dex");
198211
FileAssert.Exists (dexFile);
212+
var proguardFiles = Directory.GetFiles (Path.Combine (intermediate, "lp"), "proguard.txt", SearchOption.AllDirectories);
213+
Assert.AreEqual (2, proguardFiles.Length, "There should be only two proguard.txt files.");
199214
string className = "Lcom/xamarin/android/test/msbuildtest/JavaSourceJarTest;";
200215
Assert.IsTrue (DexUtils.ContainsClass (className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!");
201216
className = "Lcom/xamarin/android/test/msbuildtest/JavaSourceTestExtension;";

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ This file is used by all project types, including binding projects.
5555
<Output TaskParameter="ResolvedAssetDirectories" ItemName="LibraryAssetDirectories" />
5656
<Output TaskParameter="ResolvedEnvironmentFiles" ItemName="LibraryEnvironments" />
5757
<Output TaskParameter="ResolvedResourceDirectoryStamps" ItemName="_LibraryResourceDirectoryStamps" />
58+
<Output TaskParameter="ProguardConfigFiles" ItemName="ProguardConfiguration" />
5859
</ReadLibraryProjectImportsCache>
5960
<ItemGroup>
6061
<FileWrites Include="@(ResolvedResourceDirectories->'%(ResourceDirectoryArchive)')"

0 commit comments

Comments
 (0)