Skip to content

Commit 1857f28

Browse files
authored
[Xamarin.Android.Build.Tasks] Move DSO wrapping code to BuildApk (#9349)
In order to avoid having to register a task object in the `<PrepareDSOWrapperState/>` task, move the DSO wrapper stub library discovery code into the `<BuildApk/>` task.
1 parent f09caed commit 1857f28

File tree

13 files changed

+96
-105
lines changed

13 files changed

+96
-105
lines changed

build-tools/create-packs/Microsoft.Android.Runtime.proj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ projects that use the Microsoft.Android framework in .NET 6+.
4242
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release.so" />
4343
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-debug-app-helper.so" />
4444
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-native-tracing.so" />
45-
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libarchive-dso-stub.so" />
4645
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libunwind_xamarin.a" />
4746
<FrameworkListFileClass Include="@(_AndroidRuntimePackAssemblies->'%(Filename)%(Extension)')" Profile="Android" />
4847
<FrameworkListFileClass Include="@(_AndroidRuntimePackAssets->'%(Filename)%(Extension)')" Profile="Android" />

build-tools/installers/create-installers.targets

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@
186186
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x64\libm.so" />
187187
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x86\libc.so" />
188188
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x86\libm.so" />
189+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)dsostubs\android-arm64\libarchive-dso-stub.so" />
190+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)dsostubs\android-arm\libarchive-dso-stub.so" />
191+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)dsostubs\android-x64\libarchive-dso-stub.so" />
192+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)dsostubs\android-x86\libarchive-dso-stub.so" />
189193
</ItemGroup>
190194
<ItemGroup>
191195
<_MSBuildTargetsSrcFiles Include="$(MSBuildTargetsSrcDir)\Xamarin.Android.AvailableItems.targets" />

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ _ResolveAssemblies MSBuild target.
1313
<UsingTask TaskName="Xamarin.Android.Tasks.ProcessAssemblies" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
1414
<UsingTask TaskName="Xamarin.Android.Tasks.ProcessNativeLibraries" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
1515
<UsingTask TaskName="Xamarin.Android.Tasks.StripNativeLibraries" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
16-
<UsingTask TaskName="Xamarin.Android.Tasks.PrepareDSOWrapperState" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
1716

1817
<!-- HACK: workaround for: https://github.com/dotnet/sdk/issues/25679 -->
1918
<Target Name="_RemoveLinuxFrameworkReferences"
@@ -124,16 +123,9 @@ _ResolveAssemblies MSBuild target.
124123
</ItemGroup>
125124

126125
<ItemGroup>
127-
<_ResolvedArchiveDSOStub Include="@(ResolvedFileToPublish)" Condition=" '%(ResolvedFileToPublish.Filename)%(ResolvedFileToPublish.Extension)' == 'libarchive-dso-stub.so' " />
128126
<ResolvedFileToPublish Remove="@(_ResolvedArchiveDSOStub)" />
129127
</ItemGroup>
130128

131-
<!-- This must run as early as possible, as soon as we have locations of the .so files and before any wrapping/packaging is done -->
132-
<PrepareDSOWrapperState
133-
ArchiveDSOStubs="@(_ResolvedArchiveDSOStub)"
134-
AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"
135-
BaseOutputDirectory="$(IntermediateOutputPath)" />
136-
137129
<!-- All assemblies must be per-RID, thus no `->Distinct()` on `InputAssemblies` or `ResolvedSymbols` items -->
138130
<ProcessAssemblies
139131
RuntimeIdentifiers="@(_RIDs)"

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

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ public class BuildApk : AndroidTask
109109

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

112+
[Required]
113+
public string AndroidBinUtilsDirectory { get; set; }
114+
115+
[Required]
116+
public string IntermediateOutputPath { get; set; }
117+
112118
[Required]
113119
public string ProjectFullPath { get; set; }
114120

@@ -141,7 +147,7 @@ protected virtual void FixupArchive (ZipArchiveEx zip) { }
141147

142148
List<Regex> includePatterns = new List<Regex> ();
143149

144-
void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOutputPath, bool debug, bool compress, IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo, string assemblyStoreApkName)
150+
void ExecuteWithAbi (DSOWrapperGenerator.Config dsoWrapperConfig, string [] supportedAbis, string apkInputPath, string apkOutputPath, bool debug, bool compress, IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo, string assemblyStoreApkName)
145151
{
146152
ArchiveFileList files = new ArchiveFileList ();
147153
bool refresh = true;
@@ -208,11 +214,11 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut
208214
}
209215

210216
if (EmbedAssemblies) {
211-
AddAssemblies (apk, debug, compress, compressedAssembliesInfo, assemblyStoreApkName);
217+
AddAssemblies (dsoWrapperConfig, apk, debug, compress, compressedAssembliesInfo, assemblyStoreApkName);
212218
apk.Flush ();
213219
}
214220

215-
AddRuntimeConfigBlob (apk);
221+
AddRuntimeConfigBlob (dsoWrapperConfig, apk);
216222
AddRuntimeLibraries (apk, supportedAbis);
217223
apk.Flush();
218224
AddNativeLibraries (files, supportedAbis);
@@ -354,14 +360,17 @@ public override bool RunTask ()
354360
throw new InvalidOperationException ($"Assembly compression info not found for key '{key}'. Compression will not be performed.");
355361
}
356362

357-
ExecuteWithAbi (SupportedAbis, ApkInputPath, ApkOutputPath, debug, compress, compressedAssembliesInfo, assemblyStoreApkName: null);
363+
DSOWrapperGenerator.Config dsoWrapperConfig = DSOWrapperGenerator.GetConfig (Log, AndroidBinUtilsDirectory, IntermediateOutputPath);
364+
ExecuteWithAbi (dsoWrapperConfig, SupportedAbis, ApkInputPath, ApkOutputPath, debug, compress, compressedAssembliesInfo, assemblyStoreApkName: null);
358365
outputFiles.Add (ApkOutputPath);
359366
if (CreatePackagePerAbi && SupportedAbis.Length > 1) {
367+
var abiArray = new string[] { String.Empty };
360368
foreach (var abi in SupportedAbis) {
361369
existingEntries.Clear ();
362370
var path = Path.GetDirectoryName (ApkOutputPath);
363371
var apk = Path.GetFileNameWithoutExtension (ApkOutputPath);
364-
ExecuteWithAbi (new [] { abi }, String.Format ("{0}-{1}", ApkInputPath, abi),
372+
abiArray[0] = abi;
373+
ExecuteWithAbi (dsoWrapperConfig, abiArray, String.Format ("{0}-{1}", ApkInputPath, abi),
365374
Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)),
366375
debug, compress, compressedAssembliesInfo, assemblyStoreApkName: abi);
367376
outputFiles.Add (Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)));
@@ -371,20 +380,11 @@ public override bool RunTask ()
371380
OutputFiles = outputFiles.Select (a => new TaskItem (a)).ToArray ();
372381

373382
Log.LogDebugTaskItems (" [Output] OutputFiles :", OutputFiles);
374-
DSOWrapperGenerator.CleanUp (this);
383+
DSOWrapperGenerator.CleanUp (dsoWrapperConfig);
375384

376385
return !Log.HasLoggedErrors;
377386
}
378387

379-
internal DSOWrapperGenerator.Config EnsureConfig ()
380-
{
381-
var config = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal<DSOWrapperGenerator.Config> (ProjectSpecificTaskObjectKey (DSOWrapperGenerator.RegisteredConfigKey), RegisteredTaskObjectLifetime.Build);
382-
if (config is null) {
383-
throw new InvalidOperationException ("Internal error: no registered config found");
384-
}
385-
return config;
386-
}
387-
388388
static Regex FileGlobToRegEx (string fileGlob, RegexOptions options)
389389
{
390390
StringBuilder sb = new StringBuilder ();
@@ -403,7 +403,7 @@ static Regex FileGlobToRegEx (string fileGlob, RegexOptions options)
403403
return new Regex (sb.ToString (), options);
404404
}
405405

406-
void AddRuntimeConfigBlob (ZipArchiveEx apk)
406+
void AddRuntimeConfigBlob (DSOWrapperGenerator.Config dsoWrapperConfig, ZipArchiveEx apk)
407407
{
408408
// We will place rc.bin in the `lib` directory next to the blob, to make startup slightly faster, as we will find the config file right after we encounter
409409
// our assembly store. Not only that, but also we'll be able to skip scanning the `base.apk` archive when split configs are enabled (which they are in 99%
@@ -414,13 +414,13 @@ void AddRuntimeConfigBlob (ZipArchiveEx apk)
414414
// Prefix it with `a` because bundletool sorts entries alphabetically, and this will place it right next to `assemblies.*.blob.so`, which is what we
415415
// like since we can finish scanning the zip central directory earlier at startup.
416416
string inArchivePath = MakeArchiveLibPath (abi, "libarc.bin.so");
417-
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (MonoAndroidHelper.AbiToTargetArch (abi), RuntimeConfigBinFilePath, Path.GetFileName (inArchivePath), this);
417+
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, MonoAndroidHelper.AbiToTargetArch (abi), RuntimeConfigBinFilePath, Path.GetFileName (inArchivePath));
418418
AddFileToArchiveIfNewer (apk, wrappedSourcePath, inArchivePath, compressionMethod: GetCompressionMethod (inArchivePath));
419419
}
420420
}
421421
}
422422

423-
void AddAssemblies (ZipArchiveEx apk, bool debug, bool compress, IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo, string assemblyStoreApkName)
423+
void AddAssemblies (DSOWrapperGenerator.Config dsoWrapperConfig, ZipArchiveEx apk, bool debug, bool compress, IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo, string assemblyStoreApkName)
424424
{
425425
string sourcePath;
426426
AssemblyCompression.AssemblyData compressedAssembly = null;
@@ -455,7 +455,7 @@ void AddAssemblies (ZipArchiveEx apk, bool debug, bool compress, IDictionary<And
455455
foreach (var kvp in assemblyStorePaths) {
456456
string abi = MonoAndroidHelper.ArchToAbi (kvp.Key);
457457
inArchivePath = MakeArchiveLibPath (abi, "lib" + Path.GetFileName (kvp.Value));
458-
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (kvp.Key, kvp.Value, Path.GetFileName (inArchivePath), this);
458+
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, kvp.Key, kvp.Value, Path.GetFileName (inArchivePath));
459459
AddFileToArchiveIfNewer (apk, wrappedSourcePath, inArchivePath, GetCompressionMethod (inArchivePath));
460460
}
461461

@@ -474,12 +474,12 @@ void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch
474474

475475
// Add assembly
476476
(string assemblyPath, string assemblyDirectory) = GetInArchiveAssemblyPath (assembly);
477-
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (arch, sourcePath, Path.GetFileName (assemblyPath), this);
477+
string wrappedSourcePath = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, arch, sourcePath, Path.GetFileName (assemblyPath));
478478
AddFileToArchiveIfNewer (apk, wrappedSourcePath, assemblyPath, compressionMethod: GetCompressionMethod (assemblyPath));
479479

480480
// Try to add config if exists
481481
var config = Path.ChangeExtension (assembly.ItemSpec, "dll.config");
482-
AddAssemblyConfigEntry (apk, arch, assemblyDirectory, config);
482+
AddAssemblyConfigEntry (dsoWrapperConfig, apk, arch, assemblyDirectory, config);
483483

484484
// Try to add symbols if Debug
485485
if (!debug) {
@@ -492,7 +492,7 @@ void DoAddAssembliesFromArchCollection (TaskLoggingHelper log, AndroidTargetArch
492492
}
493493

494494
string archiveSymbolsPath = assemblyDirectory + MonoAndroidHelper.MakeDiscreteAssembliesEntryName (Path.GetFileName (symbols));
495-
string wrappedSymbolsPath = DSOWrapperGenerator.WrapIt (arch, symbols, Path.GetFileName (archiveSymbolsPath), this);
495+
string wrappedSymbolsPath = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, arch, symbols, Path.GetFileName (archiveSymbolsPath));
496496
AddFileToArchiveIfNewer (
497497
apk,
498498
wrappedSymbolsPath,
@@ -531,7 +531,7 @@ bool AddFileToArchiveIfNewer (ZipArchiveEx apk, string file, string inArchivePat
531531
return true;
532532
}
533533

534-
void AddAssemblyConfigEntry (ZipArchiveEx apk, AndroidTargetArch arch, string assemblyPath, string configFile)
534+
void AddAssemblyConfigEntry (DSOWrapperGenerator.Config dsoWrapperConfig, ZipArchiveEx apk, AndroidTargetArch arch, string assemblyPath, string configFile)
535535
{
536536
string inArchivePath = MonoAndroidHelper.MakeDiscreteAssembliesEntryName (assemblyPath + Path.GetFileName (configFile));
537537
existingEntries.Remove (inArchivePath);
@@ -547,7 +547,7 @@ void AddAssemblyConfigEntry (ZipArchiveEx apk, AndroidTargetArch arch, string as
547547
}
548548

549549
Log.LogDebugMessage ($"Adding {configFile} as the archive file is out of date.");
550-
string wrappedConfigFile = DSOWrapperGenerator.WrapIt (arch, configFile, Path.GetFileName (inArchivePath), this);
550+
string wrappedConfigFile = DSOWrapperGenerator.WrapIt (Log, dsoWrapperConfig, arch, configFile, Path.GetFileName (inArchivePath));
551551
apk.AddFileAndFlush (wrappedConfigFile, inArchivePath, compressionMethod);
552552
}
553553

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

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/Xamarin.Android.Build.Tasks/Utilities/DSOWrapperGenerator.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ class DSOWrapperGenerator
3636

3737
internal class Config
3838
{
39-
public Dictionary<AndroidTargetArch, ITaskItem> DSOStubPaths { get; }
39+
public Dictionary<AndroidTargetArch, string> DSOStubPaths { get; }
4040
public string AndroidBinUtilsDirectory { get; }
4141
public string BaseOutputDirectory { get; }
4242

43-
public Config (Dictionary<AndroidTargetArch, ITaskItem> stubPaths, string androidBinUtilsDirectory, string baseOutputDirectory)
43+
public Config (Dictionary<AndroidTargetArch, string> stubPaths, string androidBinUtilsDirectory, string baseOutputDirectory)
4444
{
4545
DSOStubPaths = stubPaths;
4646
AndroidBinUtilsDirectory = androidBinUtilsDirectory;
@@ -53,6 +53,30 @@ public Config (Dictionary<AndroidTargetArch, ITaskItem> stubPaths, string androi
5353
//
5454
const ulong PayloadSectionAlignment = 0x4000;
5555

56+
public static Config GetConfig (TaskLoggingHelper log, string androidBinUtilsDirectory, string baseOutputDirectory)
57+
{
58+
var stubPaths = new Dictionary<AndroidTargetArch, string> ();
59+
string archiveDSOStubsRootDir = MonoAndroidHelper.GetDSOStubsRootDirectoryPath (androidBinUtilsDirectory);
60+
61+
foreach (string dir in Directory.EnumerateDirectories (archiveDSOStubsRootDir, "android-*")) {
62+
string rid = Path.GetFileName (dir);
63+
AndroidTargetArch arch = MonoAndroidHelper.RidToArchMaybe (rid);
64+
if (arch == AndroidTargetArch.None) {
65+
log.LogDebugMessage ($"Unable to extract a supported RID name from directory path '{dir}'");
66+
continue;
67+
}
68+
69+
string stubPath = Path.Combine (dir, "libarchive-dso-stub.so");
70+
if (!File.Exists (stubPath)) {
71+
throw new InvalidOperationException ($"Internal error: archive DSO stub file '{stubPath}' does not exist");
72+
}
73+
74+
stubPaths.Add (arch, stubPath);
75+
}
76+
77+
return new Config (stubPaths, androidBinUtilsDirectory, baseOutputDirectory);
78+
}
79+
5680
static string GetArchOutputPath (AndroidTargetArch targetArch, Config config)
5781
{
5882
return Path.Combine (config.BaseOutputDirectory, MonoAndroidHelper.ArchToRid (targetArch), "wrapped");
@@ -62,22 +86,20 @@ static string GetArchOutputPath (AndroidTargetArch targetArch, Config config)
6286
/// Puts the indicated file (<paramref name="payloadFilePath"/>) inside an ELF shared library and returns
6387
/// path to the wrapped file.
6488
/// </summary>
65-
public static string WrapIt (AndroidTargetArch targetArch, string payloadFilePath, string outputFileName, BuildApk task)
89+
public static string WrapIt (TaskLoggingHelper log, Config config, AndroidTargetArch targetArch, string payloadFilePath, string outputFileName)
6690
{
67-
TaskLoggingHelper log = task.Log;
6891
log.LogDebugMessage ($"[{targetArch}] Putting '{payloadFilePath}' inside ELF shared library '{outputFileName}'");
69-
Config config = task.EnsureConfig ();
7092
string outputDir = GetArchOutputPath (targetArch, config);
7193
Directory.CreateDirectory (outputDir);
7294

7395
string outputFile = Path.Combine (outputDir, outputFileName);
7496
log.LogDebugMessage ($" output file path: {outputFile}");
7597

76-
if (!config.DSOStubPaths.TryGetValue (targetArch, out ITaskItem? stubItem)) {
98+
if (!config.DSOStubPaths.TryGetValue (targetArch, out string? stubPath)) {
7799
throw new InvalidOperationException ($"Internal error: archive DSO stub location not known for architecture '{targetArch}'");
78100
}
79101

80-
File.Copy (stubItem.ItemSpec, outputFile, overwrite: true);
102+
File.Copy (stubPath, outputFile, overwrite: true);
81103

82104
string quotedOutputFile = MonoAndroidHelper.QuoteFileNameArgument (outputFile);
83105
string objcopy = Path.Combine (config.AndroidBinUtilsDirectory, MonoAndroidHelper.GetExecutablePath (config.AndroidBinUtilsDirectory, "llvm-objcopy"));
@@ -107,10 +129,8 @@ public static string WrapIt (AndroidTargetArch targetArch, string payloadFilePat
107129
/// created by this class. The reason to do so is to ensure that we don't package any "stale" content and those
108130
/// wrapper files aren't part of any dependency chain so it's hard to check their up to date state.
109131
/// </summary>
110-
public static void CleanUp (BuildApk task)
132+
public static void CleanUp (Config config)
111133
{
112-
Config config = task.EnsureConfig();
113-
114134
foreach (var kvp in config.DSOStubPaths) {
115135
string outputDir = GetArchOutputPath (kvp.Key, config);
116136
if (!Directory.Exists (outputDir)) {

src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.Basic.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,19 @@ public static string RidToAbi (string rid)
111111
return abi;
112112
}
113113

114-
public static AndroidTargetArch RidToArch (string rid)
114+
public static AndroidTargetArch RidToArchMaybe (string rid)
115115
{
116116
if (!RidToArchMap.TryGetValue (rid, out AndroidTargetArch arch)) {
117+
return AndroidTargetArch.None;
118+
};
119+
120+
return arch;
121+
}
122+
123+
public static AndroidTargetArch RidToArch (string rid)
124+
{
125+
AndroidTargetArch arch = RidToArchMaybe (rid);
126+
if (arch == AndroidTargetArch.None) {
117127
throw new NotSupportedException ($"Internal error: unsupported Runtime Identifier '{rid}'");
118128
};
119129

src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,12 @@ public static string GetLibstubsRootDirectoryPath (string androidBinUtilsDirecto
625625
return Path.GetFullPath (Path.Combine (androidBinUtilsDirectory, relPath, "libstubs"));
626626
}
627627

628+
public static string GetDSOStubsRootDirectoryPath (string androidBinUtilsDirectory)
629+
{
630+
string relPath = GetToolsRootDirectoryRelativePath (androidBinUtilsDirectory);
631+
return Path.GetFullPath (Path.Combine (androidBinUtilsDirectory, relPath, "dsostubs"));
632+
}
633+
628634
public static string GetNativeLibsRootDirectoryPath (string androidBinUtilsDirectory)
629635
{
630636
string relPath = GetToolsRootDirectoryRelativePath (androidBinUtilsDirectory);

0 commit comments

Comments
 (0)