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

Refine 16k page alignment support #9075

Merged
merged 4 commits into from
Jul 22, 2024
Merged
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
2 changes: 1 addition & 1 deletion Configuration.props
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
<XABuildToolsFolder Condition="'$(XABuildToolsFolder)' == ''">35.0.0</XABuildToolsFolder>
<XAPlatformToolsPackagePrefix Condition=" '$(HostOS)' == 'Darwin' "></XAPlatformToolsPackagePrefix>
<XAPlatformToolsVersion>34.0.5</XAPlatformToolsVersion>
<XABundleToolVersion Condition="'$(XABundleToolVersion)' == ''">1.15.1</XABundleToolVersion>
<XABundleToolVersion Condition="'$(XABundleToolVersion)' == ''">1.17.0</XABundleToolVersion>
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(NUGET_PACKAGES)' != ''">$(NUGET_PACKAGES)</XAPackagesDir>
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(HostOS)' == 'Windows'">$(userprofile)\.nuget\packages</XAPackagesDir>
<XAPackagesDir Condition=" '$(XAPackagesDir)' == '' And '$(HostOS)' != 'Windows'">$(HOME)/.nuget/packages</XAPackagesDir>
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<MonoOptionsVersion>6.12.0.148</MonoOptionsVersion>
<SystemCollectionsImmutableVersion>8.0.0</SystemCollectionsImmutableVersion>
<SystemRuntimeCompilerServicesUnsafeVersion>6.0.0</SystemRuntimeCompilerServicesUnsafeVersion>
<ELFSharpVersion>2.13.1</ELFSharpVersion>
<ELFSharpVersion>2.17.3</ELFSharpVersion>
<HumanizerVersion>2.14.1</HumanizerVersion>
<MdocPackageVersion Condition=" '$(MdocPackageVersion)' == '' ">5.9.2.4</MdocPackageVersion>
</PropertyGroup>
Expand Down
3 changes: 2 additions & 1 deletion Documentation/docs-mobile/messages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ Please file an issue with the exact error message using the 'Help->Send Feedback
or 'Help->Report a Problem' in Visual Studio for Mac.
+ [XA0138](xa0138.md): %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`.
+ [XA0139](xa0139.md): `@(AndroidAsset)` `{0}` has invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`
+ [XA0140](xa0140.md):
+ [XA0140](xa0140.md):
+ [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

## XA1xxx: Project related

Expand Down
14 changes: 14 additions & 0 deletions Documentation/docs-mobile/messages/xa0141.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: .NET for Android warning XA0141
description: XA0141 warning code
ms.date: 22/07/2024
---
# .NET for Android warning XA0141

## Issue

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

## Solution

The indicated native shared library must be recompiled and relinked with the 16k alignment, as per URL indicated in the message.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
RuntimeIdentifier="$(RuntimeIdentifier)"
EnableLLVM="$(EnableLLVM)"
Profiles="@(AndroidAotProfile)"
StripLibraries="$(_AndroidAotStripLibraries)">
StripLibraries="$(_AndroidAotStripLibraries)"
ZipAlignmentPages="$(AndroidZipAlignment)">
<Output PropertyName="_Triple" TaskParameter="Triple" />
<Output PropertyName="_ToolPrefix" TaskParameter="ToolPrefix" />
<Output PropertyName="_MsymPath" TaskParameter="MsymPath" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@

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

<!-- User-facing configuration-specific defaults -->
Expand Down
10 changes: 9 additions & 1 deletion src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1059,4 +1059,12 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
{0} - NuGet package id
{1} - NuGet package version</comment>
</data>
</root>
<data name="XA0141" xml:space="preserve">
<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>
<comment>The following is a literal name and should not be translated: NuGet
{0} - NuGet package id
{1} - NuGet package version
{2} - shared library file name
</comment>
</data>
</root>
8 changes: 4 additions & 4 deletions src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ namespace Xamarin.Android.Tasks
{
public class AndroidZipAlign : AndroidRunToolTask
{
// Sometime next year the default value should be changed to 16 since it's going to be a Google Play store requirement for
// application submissions
internal const int DefaultZipAlignment = 4;
// Default to 16 since it's going to be a Google Play store requirement for application submissions sometime next year
internal const int DefaultZipAlignment64Bit = 16;
internal const int ZipAlignment32Bit = 4; // This must never change

public override string TaskPrefix => "AZA";

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

int alignment = DefaultZipAlignment;
int alignment = DefaultZipAlignment64Bit;
public int Alignment {
get {return alignment;}
set {alignment = value;}
Expand Down
23 changes: 16 additions & 7 deletions src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public class BuildApk : AndroidTask

public string ZipFlushSizeLimit { get; set; }

public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment64Bit;

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

Expand Down Expand Up @@ -683,14 +685,15 @@ sealed class LibInfo
public string Link;
public string Abi;
public string ArchiveFileName;
public ITaskItem Item;
}

CompressionMethod GetCompressionMethod (string fileName)
{
return uncompressedFileExtensions.Contains (Path.GetExtension (fileName)) ? UncompressedMethod : CompressionMethod.Default;
}

void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName)
void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName, ITaskItem taskItem)
{
string archivePath = MakeArchiveLibPath (abi, inArchiveFileName);
existingEntries.Remove (archivePath);
Expand All @@ -700,6 +703,7 @@ void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemP
return;
}
Log.LogDebugMessage ($"Adding native library: {filesystemPath} (APK path: {archivePath})");
ELFHelper.AssertValidLibraryAlignment (Log, ZipAlignmentPages, filesystemPath, taskItem);
apk.AddEntryAndFlush (archivePath, File.OpenRead (filesystemPath), compressionMethod);
}

Expand All @@ -709,7 +713,7 @@ void AddRuntimeLibraries (ZipArchiveEx apk, string [] supportedAbis)
foreach (ITaskItem item in ApplicationSharedLibraries) {
if (String.Compare (abi, item.GetMetadata ("abi"), StringComparison.Ordinal) != 0)
continue;
AddNativeLibraryToArchive (apk, abi, item.ItemSpec, Path.GetFileName (item.ItemSpec));
AddNativeLibraryToArchive (apk, abi, item.ItemSpec, Path.GetFileName (item.ItemSpec), item);
}
}
}
Expand Down Expand Up @@ -762,7 +766,8 @@ private void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis)
Path = v.ItemSpec,
Link = v.GetMetadata ("Link"),
Abi = GetNativeLibraryAbi (v),
ArchiveFileName = GetArchiveFileName (v)
ArchiveFileName = GetArchiveFileName (v),
Item = v,
});

AddNativeLibraries (files, supportedAbis, frameworkLibs);
Expand All @@ -773,7 +778,8 @@ private void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis)
Path = v.ItemSpec,
Link = v.GetMetadata ("Link"),
Abi = GetNativeLibraryAbi (v),
ArchiveFileName = GetArchiveFileName (v)
ArchiveFileName = GetArchiveFileName (v),
Item = v,
}
);

Expand Down Expand Up @@ -854,8 +860,9 @@ void AddNativeLibraries (ArchiveFileList files, string [] supportedAbis, System.
string.Join (", ", libs.Where (lib => lib.Abi == null).Select (lib => lib.Path)));
libs = libs.Where (lib => lib.Abi != null);
libs = libs.Where (lib => supportedAbis.Contains (lib.Abi));
foreach (var info in libs)
AddNativeLibrary (files, info.Path, info.Abi, info.ArchiveFileName);
foreach (var info in libs) {
AddNativeLibrary (files, info.Path, info.Abi, info.ArchiveFileName, info.Item);
}
}

private void AddAdditionalNativeLibraries (ArchiveFileList files, string [] supportedAbis)
Expand All @@ -868,12 +875,13 @@ private void AddAdditionalNativeLibraries (ArchiveFileList files, string [] supp
Path = l.ItemSpec,
Abi = AndroidRidAbiHelper.GetNativeLibraryAbi (l),
ArchiveFileName = l.GetMetadata ("ArchiveFileName"),
Item = l,
});

AddNativeLibraries (files, supportedAbis, libs);
}

void AddNativeLibrary (ArchiveFileList files, string path, string abi, string archiveFileName)
void AddNativeLibrary (ArchiveFileList files, string path, string abi, string archiveFileName, ITaskItem? taskItem = null)
{
string fileName = string.IsNullOrEmpty (archiveFileName) ? Path.GetFileName (path) : archiveFileName;
var item = (filePath: path, archivePath: MakeArchiveLibPath (abi, fileName));
Expand All @@ -882,6 +890,7 @@ void AddNativeLibrary (ArchiveFileList files, string path, string abi, string ar
return;
}

ELFHelper.AssertValidLibraryAlignment (Log, ZipAlignmentPages, path, taskItem);
if (!ELFHelper.IsEmptyAOTLibrary (Log, item.filePath)) {
files.Add (item);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ public class GeneratePackageManagerJava : AndroidTask
public string AndroidSequencePointsMode { get; set; }
public bool EnableSGenConcurrent { get; set; }
public string? CustomBundleConfigFile { get; set; }
public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment;

[Output]
public string BuildId { get; set; }
Expand Down Expand Up @@ -335,7 +334,6 @@ void AddEnvironment ()

bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath);
var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal<GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfo> (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build);
uint zipAlignmentMask = MonoAndroidHelper.ZipAlignmentToMask (ZipAlignmentPages);
var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) {
UsesMonoAOT = usesMonoAOT,
UsesMonoLLVM = EnableLLVM,
Expand All @@ -359,7 +357,6 @@ void AddEnvironment ()
JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token,
JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount,
JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount,
ZipAlignmentMask = zipAlignmentMask,
MarshalMethodsEnabled = EnableMarshalMethods,
IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (),
};
Expand Down
25 changes: 25 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public abstract class GetAotArguments : AsyncTask

public ITaskItem [] Profiles { get; set; } = Array.Empty<ITaskItem> ();

public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment64Bit;

[Required, Output]
public ITaskItem [] ResolvedAssemblies { get; set; } = Array.Empty<ITaskItem> ();

Expand Down Expand Up @@ -325,6 +327,29 @@ string GetLdFlags (NdkTools ndk, AndroidTargetArch arch, int level, string toolP
ldFlags.Append ("-s");
}

uint maxPageSize;
switch (arch) {
case AndroidTargetArch.Arm64:
case AndroidTargetArch.X86_64:
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (ZipAlignmentPages);
break;

case AndroidTargetArch.Arm:
case AndroidTargetArch.X86:
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (AndroidZipAlign.ZipAlignment32Bit);
break;

default:
throw new InvalidOperationException ($"Internal error: unsupported target architecture {arch}");
}

if (ldFlags.Length > 0) {
ldFlags.Append (' ');
}

ldFlags.Append ("-z ");
ldFlags.Append ($"max-page-size={maxPageSize}");

return ldFlags.ToString ();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ sealed class InputFiles
[Required]
public string AndroidBinUtilsDirectory { get; set; }

public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment;
public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment64Bit;

public override System.Threading.Tasks.Task RunTaskAsync ()
{
Expand Down Expand Up @@ -145,25 +145,30 @@ IEnumerable<Config> GetLinkerConfigs ()

targetLinkerArgs.Clear ();
string elf_arch;
uint maxPageSize;
switch (abi) {
case "armeabi-v7a":
targetLinkerArgs.Add ("-X");
elf_arch = "armelf_linux_eabi";
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (AndroidZipAlign.ZipAlignment32Bit);
break;

case "arm64":
case "arm64-v8a":
case "aarch64":
targetLinkerArgs.Add ("--fix-cortex-a53-843419");
elf_arch = "aarch64linux";
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (ZipAlignmentPages);
break;

case "x86":
elf_arch = "elf_i386";
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (AndroidZipAlign.ZipAlignment32Bit);
break;

case "x86_64":
elf_arch = "elf_x86_64";
maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (ZipAlignmentPages);
break;

default:
Expand All @@ -186,7 +191,6 @@ IEnumerable<Config> GetLinkerConfigs ()
}
}

uint maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (ZipAlignmentPages);
targetLinkerArgs.Add ("-z");
targetLinkerArgs.Add ($"max-page-size={maxPageSize}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,11 @@ public sealed class ApplicationConfig
public uint jnienv_registerjninatives_method_token;
public uint jni_remapping_replacement_type_count;
public uint jni_remapping_replacement_method_index_entry_count;
public uint zip_alignment_mask;
public uint mono_components_mask;
public string android_package_name = String.Empty;
}

const uint ApplicationConfigFieldCount = 27;
const uint ApplicationConfigFieldCount = 26;

const string ApplicationConfigSymbolName = "application_config";
const string AppEnvironmentVariablesSymbolName = "app_environment_variables";
Expand Down Expand Up @@ -327,17 +326,12 @@ static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile)
ret.jni_remapping_replacement_method_index_entry_count = ConvertFieldToUInt32 ("jni_remapping_replacement_method_index_entry_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]);
break;

case 24: // zip_alignment_mask: uint32_t / .word | .long
Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}");
ret.zip_alignment_mask = ConvertFieldToUInt32 ("zip_alignment_mask", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]);
break;

case 25: // mono_components_mask: uint32_t / .word | .long
case 24: // mono_components_mask: uint32_t / .word | .long
Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}");
ret.mono_components_mask = ConvertFieldToUInt32 ("mono_components_mask", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]);
break;

case 26: // android_package_name: string / [pointer type]
case 25: // android_package_name: string / [pointer type]
Assert.IsTrue (expectedPointerTypes.Contains (field [0]), $"Unexpected pointer field type in '{envFile.Path}:{item.LineNumber}': {field [0]}");
pointers.Add (field [1].Trim ());
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ sealed class ApplicationConfig
public uint jni_remapping_replacement_type_count;
public uint jni_remapping_replacement_method_index_entry_count;

// 3, for 4-byte alignment (4k memory pages); 15, for 16-byte alignment (16k memory pages)
public uint zip_alignment_mask;

[NativeAssembler (NumberFormat = LLVMIR.LlvmIrVariableNumberFormat.Hexadecimal)]
public uint mono_components_mask;
public string android_package_name = String.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ sealed class XamarinAndroidBundledAssembly
public int JNIEnvRegisterJniNativesToken { get; set; }
public int JniRemappingReplacementTypeCount { get; set; }
public int JniRemappingReplacementMethodIndexEntryCount { get; set; }
public uint ZipAlignmentMask { get; set; }
public MonoComponent MonoComponents { get; set; }
public PackageNamingPolicy PackageNamingPolicy { get; set; }
public List<ITaskItem> NativeLibraries { get; set; }
Expand Down Expand Up @@ -245,7 +244,6 @@ protected override void Construct (LlvmIrModule module)
jnienv_registerjninatives_method_token = (uint)JNIEnvRegisterJniNativesToken,
jni_remapping_replacement_type_count = (uint)JniRemappingReplacementTypeCount,
jni_remapping_replacement_method_index_entry_count = (uint)JniRemappingReplacementMethodIndexEntryCount,
zip_alignment_mask = ZipAlignmentMask,
mono_components_mask = (uint)MonoComponents,
android_package_name = AndroidPackageName,
};
Expand Down
Loading
Loading