Skip to content

Commit 64bb147

Browse files
authored
Refine 16k page alignment support (#9075)
Context: ddb215b Context: https://github.com/google/bundletool/releases/tag/1.17.0 * ddb215b added an field to the `application_config` structure which specified the mask required to check whether entries in the APK that we read at run time are properly alignment at the 4k or 16k page boundary. This commi removes that code because it's possible that `bundletool` will change the package alignment **after** our code is already built. This would cause a false negative and an abort during application execution. Instead, we simply check whether the entry is 4k **or** 16k aligned. * Bump `bundletool` to 1.17.0, which now defaults to producing 16k-aligned archives. * Pass required alignment flags to Mono AOT compiler to produce properly aligned shared libraries. * Don't align 32-bit shared libraries to 16k, always use 4k alignment. This is in line with what NDK r27 does. * Verify alignment of shared libraries and issue new `XA0141` warning if any misaligned library is encountered.
1 parent baf16f1 commit 64bb147

21 files changed

+174
-48
lines changed

Configuration.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
<XABuildToolsFolder Condition="'$(XABuildToolsFolder)' == ''">35.0.0</XABuildToolsFolder>
126126
<XAPlatformToolsPackagePrefix Condition=" '$(HostOS)' == 'Darwin' "></XAPlatformToolsPackagePrefix>
127127
<XAPlatformToolsVersion>34.0.5</XAPlatformToolsVersion>
128-
<XABundleToolVersion Condition="'$(XABundleToolVersion)' == ''">1.15.1</XABundleToolVersion>
128+
<XABundleToolVersion Condition="'$(XABundleToolVersion)' == ''">1.17.0</XABundleToolVersion>
129129
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(NUGET_PACKAGES)' != ''">$(NUGET_PACKAGES)</XAPackagesDir>
130130
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(HostOS)' == 'Windows'">$(userprofile)\.nuget\packages</XAPackagesDir>
131131
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(HostOS)' != 'Windows'">$(HOME)/.nuget/packages</XAPackagesDir>

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
<MonoOptionsVersion>6.12.0.148</MonoOptionsVersion>
5353
<SystemCollectionsImmutableVersion>8.0.0</SystemCollectionsImmutableVersion>
5454
<SystemRuntimeCompilerServicesUnsafeVersion>6.0.0</SystemRuntimeCompilerServicesUnsafeVersion>
55-
<ELFSharpVersion>2.13.1</ELFSharpVersion>
55+
<ELFSharpVersion>2.17.3</ELFSharpVersion>
5656
<HumanizerVersion>2.14.1</HumanizerVersion>
5757
<MdocPackageVersion Condition=" '$(MdocPackageVersion)' == '' ">5.9.2.4</MdocPackageVersion>
5858
</PropertyGroup>

Documentation/docs-mobile/messages/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ Please file an issue with the exact error message using the 'Help->Send Feedback
102102
or 'Help->Report a Problem' in Visual Studio for Mac.
103103
+ [XA0138](xa0138.md): %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`.
104104
+ [XA0139](xa0139.md): `@(AndroidAsset)` `{0}` has invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`
105-
+ [XA0140](xa0140.md):
105+
+ [XA0140](xa0140.md):
106+
+ [XA0141](xa0141.md): NuGet package '{0}' version '{1}' contains a shared library '{2}' which is not correctly aligned. See https://developer.android.com/guide/practices/page-sizes for more details
106107

107108
## XA1xxx: Project related
108109

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: .NET for Android warning XA0141
3+
description: XA0141 warning code
4+
ms.date: 22/07/2024
5+
---
6+
# .NET for Android warning XA0141
7+
8+
## Issue
9+
10+
NuGet package '{0}' version '{1}' contains a shared library '{2}' which is not correctly aligned. See https://developer.android.com/guide/practices/page-sizes for more details
11+
12+
## Solution
13+
14+
The indicated native shared library must be recompiled and relinked with the 16k alignment, as per URL indicated in the message.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
9090
RuntimeIdentifier="$(RuntimeIdentifier)"
9191
EnableLLVM="$(EnableLLVM)"
9292
Profiles="@(AndroidAotProfile)"
93-
StripLibraries="$(_AndroidAotStripLibraries)">
93+
StripLibraries="$(_AndroidAotStripLibraries)"
94+
ZipAlignmentPages="$(AndroidZipAlignment)">
9495
<Output PropertyName="_Triple" TaskParameter="Triple" />
9596
<Output PropertyName="_ToolPrefix" TaskParameter="ToolPrefix" />
9697
<Output PropertyName="_MsymPath" TaskParameter="MsymPath" />

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,11 @@
4848

4949
<!--
5050
Android package (apt/aab) alignment, expressed as the page size in kilobytes. Two values are supported: 4 and 16.
51-
Sometime next year the default value should be changed to 16 since it's going to be a Google Play store requirement for
52-
application submissions.
51+
Sometime next year 16 is going to be a Google Play store requirement for application submissions.
5352
5453
When changing this default, change the value of `DefaultZipAlignment` in `src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs` as well
5554
-->
56-
<_AndroidZipAlignment Condition=" '$(_AndroidZipAlignment)' == '' ">4</_AndroidZipAlignment>
55+
<AndroidZipAlignment Condition=" '$(AndroidZipAlignment)' == '' ">16</AndroidZipAlignment>
5756
</PropertyGroup>
5857

5958
<!-- User-facing configuration-specific defaults -->

src/Xamarin.Android.Build.Tasks/Properties/Resources.resx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,4 +1059,12 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
10591059
{0} - NuGet package id
10601060
{1} - NuGet package version</comment>
10611061
</data>
1062-
</root>
1062+
<data name="XA0141" xml:space="preserve">
1063+
<value>NuGet package '{0}' version '{1}' contains a shared library '{2}' which is not correctly aligned. See https://developer.android.com/guide/practices/page-sizes for more details</value>
1064+
<comment>The following is a literal name and should not be translated: NuGet
1065+
{0} - NuGet package id
1066+
{1} - NuGet package version
1067+
{2} - shared library file name
1068+
</comment>
1069+
</data>
1070+
</root>

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ namespace Xamarin.Android.Tasks
77
{
88
public class AndroidZipAlign : AndroidRunToolTask
99
{
10-
// Sometime next year the default value should be changed to 16 since it's going to be a Google Play store requirement for
11-
// application submissions
12-
internal const int DefaultZipAlignment = 4;
10+
// Default to 16 since it's going to be a Google Play store requirement for application submissions sometime next year
11+
internal const int DefaultZipAlignment64Bit = 16;
12+
internal const int ZipAlignment32Bit = 4; // This must never change
1313

1414
public override string TaskPrefix => "AZA";
1515

@@ -19,7 +19,7 @@ public class AndroidZipAlign : AndroidRunToolTask
1919
[Required]
2020
public ITaskItem DestinationDirectory { get; set; }
2121

22-
int alignment = DefaultZipAlignment;
22+
int alignment = DefaultZipAlignment64Bit;
2323
public int Alignment {
2424
get {return alignment;}
2525
set {alignment = value;}

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

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ public class BuildApk : AndroidTask
107107

108108
public string ZipFlushSizeLimit { get; set; }
109109

110+
public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment64Bit;
111+
110112
[Required]
111113
public string ProjectFullPath { get; set; }
112114

@@ -683,14 +685,15 @@ sealed class LibInfo
683685
public string Link;
684686
public string Abi;
685687
public string ArchiveFileName;
688+
public ITaskItem Item;
686689
}
687690

688691
CompressionMethod GetCompressionMethod (string fileName)
689692
{
690693
return uncompressedFileExtensions.Contains (Path.GetExtension (fileName)) ? UncompressedMethod : CompressionMethod.Default;
691694
}
692695

693-
void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName)
696+
void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName, ITaskItem taskItem)
694697
{
695698
string archivePath = MakeArchiveLibPath (abi, inArchiveFileName);
696699
existingEntries.Remove (archivePath);
@@ -700,6 +703,7 @@ void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemP
700703
return;
701704
}
702705
Log.LogDebugMessage ($"Adding native library: {filesystemPath} (APK path: {archivePath})");
706+
ELFHelper.AssertValidLibraryAlignment (Log, ZipAlignmentPages, filesystemPath, taskItem);
703707
apk.AddEntryAndFlush (archivePath, File.OpenRead (filesystemPath), compressionMethod);
704708
}
705709

@@ -709,7 +713,7 @@ void AddRuntimeLibraries (ZipArchiveEx apk, string [] supportedAbis)
709713
foreach (ITaskItem item in ApplicationSharedLibraries) {
710714
if (String.Compare (abi, item.GetMetadata ("abi"), StringComparison.Ordinal) != 0)
711715
continue;
712-
AddNativeLibraryToArchive (apk, abi, item.ItemSpec, Path.GetFileName (item.ItemSpec));
716+
AddNativeLibraryToArchive (apk, abi, item.ItemSpec, Path.GetFileName (item.ItemSpec), item);
713717
}
714718
}
715719
}
@@ -762,7 +766,8 @@ private void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis)
762766
Path = v.ItemSpec,
763767
Link = v.GetMetadata ("Link"),
764768
Abi = GetNativeLibraryAbi (v),
765-
ArchiveFileName = GetArchiveFileName (v)
769+
ArchiveFileName = GetArchiveFileName (v),
770+
Item = v,
766771
});
767772

768773
AddNativeLibraries (files, supportedAbis, frameworkLibs);
@@ -773,7 +778,8 @@ private void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis)
773778
Path = v.ItemSpec,
774779
Link = v.GetMetadata ("Link"),
775780
Abi = GetNativeLibraryAbi (v),
776-
ArchiveFileName = GetArchiveFileName (v)
781+
ArchiveFileName = GetArchiveFileName (v),
782+
Item = v,
777783
}
778784
);
779785

@@ -854,8 +860,9 @@ void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis, System.
854860
string.Join (", ", libs.Where (lib => lib.Abi == null).Select (lib => lib.Path)));
855861
libs = libs.Where (lib => lib.Abi != null);
856862
libs = libs.Where (lib => supportedAbis.Contains (lib.Abi));
857-
foreach (var info in libs)
858-
AddNativeLibrary (files, info.Path, info.Abi, info.ArchiveFileName);
863+
foreach (var info in libs) {
864+
AddNativeLibrary (files, info.Path, info.Abi, info.ArchiveFileName, info.Item);
865+
}
859866
}
860867

861868
private void AddAdditionalNativeLibraries (ArchiveFileList files, string [] supportedAbis)
@@ -868,12 +875,13 @@ private void AddAdditionalNativeLibraries (ArchiveFileList files, string [] supp
868875
Path = l.ItemSpec,
869876
Abi = AndroidRidAbiHelper.GetNativeLibraryAbi (l),
870877
ArchiveFileName = l.GetMetadata ("ArchiveFileName"),
878+
Item = l,
871879
});
872880

873881
AddNativeLibraries (files, supportedAbis, libs);
874882
}
875883

876-
void AddNativeLibrary (ArchiveFileList files, string path, string abi, string archiveFileName)
884+
void AddNativeLibrary (ArchiveFileList files, string path, string abi, string archiveFileName, ITaskItem? taskItem = null)
877885
{
878886
string fileName = string.IsNullOrEmpty (archiveFileName) ? Path.GetFileName (path) : archiveFileName;
879887
var item = (filePath: path, archivePath: MakeArchiveLibPath (abi, fileName));
@@ -882,6 +890,7 @@ void AddNativeLibrary (ArchiveFileList files, string path, string abi, string ar
882890
return;
883891
}
884892

893+
ELFHelper.AssertValidLibraryAlignment (Log, ZipAlignmentPages, path, taskItem);
885894
if (!ELFHelper.IsEmptyAOTLibrary (Log, item.filePath)) {
886895
files.Add (item);
887896
} else {

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ public class GeneratePackageManagerJava : AndroidTask
8080
public string AndroidSequencePointsMode { get; set; }
8181
public bool EnableSGenConcurrent { get; set; }
8282
public string? CustomBundleConfigFile { get; set; }
83-
public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment;
8483

8584
[Output]
8685
public string BuildId { get; set; }
@@ -335,7 +334,6 @@ void AddEnvironment ()
335334

336335
bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath);
337336
var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal<GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfo> (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build);
338-
uint zipAlignmentMask = MonoAndroidHelper.ZipAlignmentToMask (ZipAlignmentPages);
339337
var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) {
340338
UsesMonoAOT = usesMonoAOT,
341339
UsesMonoLLVM = EnableLLVM,
@@ -359,7 +357,6 @@ void AddEnvironment ()
359357
JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token,
360358
JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount,
361359
JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount,
362-
ZipAlignmentMask = zipAlignmentMask,
363360
MarshalMethodsEnabled = EnableMarshalMethods,
364361
IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (),
365362
};

0 commit comments

Comments
 (0)