Skip to content

Commit eb7ffc7

Browse files
committed
More linker command line work
* made `src/native/` components create archives in the regular output dir, so that they can be packaged. * linker response file support * added a stub for libz (Mono runtime and BCL libraries need it)
1 parent bfe4c6f commit eb7ffc7

File tree

15 files changed

+295
-112
lines changed

15 files changed

+295
-112
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ projects that use the Microsoft.Android framework in .NET 6+.
4343
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-debug-app-helper.so" />
4444
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-native-tracing.so" />
4545
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libunwind_xamarin.a" />
46+
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libruntime-base.a" />
47+
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxa-java-interop.a" />
48+
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxa-lz4.a" />
49+
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxa-shared-bits.a" />
50+
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release-static.a" />
4651
<FrameworkListFileClass Include="@(_AndroidRuntimePackAssemblies->'%(Filename)%(Extension)')" Profile="Android" />
4752
<FrameworkListFileClass Include="@(_AndroidRuntimePackAssets->'%(Filename)%(Extension)')" Profile="Android" />
4853
</ItemGroup>

build-tools/installers/create-installers.targets

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,16 @@
172172
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)ManifestOverlays\Timing.xml" />
173173
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm64\libc.so" />
174174
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm64\libm.so" />
175+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm64\libz.so" />
175176
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm\libc.so" />
176177
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm\libm.so" />
178+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-arm\libz.so" />
177179
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x64\libc.so" />
178180
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x64\libm.so" />
181+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x64\libz.so" />
179182
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x86\libc.so" />
180183
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x86\libm.so" />
184+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libstubs\android-x86\libz.so" />
181185
</ItemGroup>
182186
<ItemGroup>
183187
<_MSBuildTargetsSrcFiles Include="$(MSBuildTargetsSrcDir)\Xamarin.Android.AvailableItems.targets" />

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Contains code to build and link the native runtime at application build time.
2525
MonoComponents="@(_MonoComponent)"
2626
ResolvedNativeArchives="@(_ResolvedNativeArchive)">
2727
<Output TaskParameter="NativeArchives" ItemName="_SelectedNativeArchive" />
28+
<Output TaskParameter="RequiredLibraries" ItemName="_RequiredLinkLibraries" />
2829
</GetNativeRuntimeComponents>
2930
</Target>
3031

@@ -36,8 +37,10 @@ Contains code to build and link the native runtime at application build time.
3637
<LinkNativeRuntime
3738
MonoComponents="@(_MonoComponent)"
3839
AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"
40+
IntermediateOutputPath="$(IntermediateOutputPath)"
3941
NativeArchives="@(_SelectedNativeArchive)"
4042
NativeObjectFiles="@(_NativeAssemblyTarget)"
43+
LinkLibraries="@(_RequiredLinkLibraries)"
4144
OutputRuntimes="@(_UnifiedNativeRuntime)"
4245
SupportedAbis="@(_BuildTargetAbis)"
4346
/>

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

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,41 @@ public class GetNativeRuntimeComponents : AndroidTask
2020
[Output]
2121
public ITaskItem[] NativeArchives { get; set; }
2222

23+
[Output]
24+
public ITaskItem[] RequiredLibraries { get; set; }
25+
2326
public override bool RunTask ()
2427
{
2528
var components = new NativeRuntimeComponents (MonoComponents);
29+
var uniqueAbis = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
2630
var archives = new List<ITaskItem> ();
2731
foreach (NativeRuntimeComponents.Archive archiveItem in components.KnownArchives) {
2832
if (!archiveItem.Include) {
2933
continue;
3034
}
31-
MakeItems (archiveItem, archives);
35+
MakeItems (archiveItem, archives, uniqueAbis);
3236
}
33-
3437
NativeArchives = archives.ToArray ();
38+
39+
var libraries = new List<ITaskItem> ();
40+
foreach (string lib in components.NativeLibraries) {
41+
MakeLibraryItems (lib, libraries, uniqueAbis);
42+
}
43+
RequiredLibraries = libraries.ToArray ();
44+
3545
return !Log.HasLoggedErrors;
3646
}
3747

38-
void MakeItems (NativeRuntimeComponents.Archive archive, List<ITaskItem> archives)
48+
void MakeLibraryItems (string libName, List<ITaskItem> libraries, HashSet<string> uniqueAbis)
49+
{
50+
foreach (string abi in uniqueAbis) {
51+
var item = new TaskItem (libName);
52+
item.SetMetadata ("Abi", abi);
53+
libraries.Add (item);
54+
}
55+
}
56+
57+
void MakeItems (NativeRuntimeComponents.Archive archive, List<ITaskItem> archives, HashSet<string> uniqueAbis)
3958
{
4059
foreach (ITaskItem resolvedArchive in ResolvedNativeArchives) {
4160
string fileName = Path.GetFileName (resolvedArchive.ItemSpec);
@@ -48,6 +67,7 @@ ITaskItem DoMakeItem (ITaskItem resolved)
4867
{
4968
var ret = new TaskItem (resolved.ItemSpec);
5069
string abi = MonoAndroidHelper.RidToAbi (resolved.GetRequiredMetadata ("_ResolvedNativeArchive", "RuntimeIdentifier", Log));
70+
uniqueAbis.Add (abi);
5171
ret.SetMetadata ("Abi", abi);
5272

5373
return ret;

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,11 @@ IEnumerable<Config> GetLinkerConfigs ()
173173
targetLinkerArgs.Add (elf_arch);
174174

175175
foreach (string file in inputs.ObjectFiles) {
176-
targetLinkerArgs.Add (QuoteFileName (file));
176+
targetLinkerArgs.Add (MonoAndroidHelper.QuoteFileNameArgument (file));
177177
}
178178

179179
targetLinkerArgs.Add ("-o");
180-
targetLinkerArgs.Add (QuoteFileName (inputs.OutputSharedLibrary));
180+
targetLinkerArgs.Add (MonoAndroidHelper.QuoteFileNameArgument (inputs.OutputSharedLibrary));
181181

182182
if (inputs.ExtraLibraries != null) {
183183
foreach (string lib in inputs.ExtraLibraries) {
@@ -238,12 +238,5 @@ void OnErrorData (string linkerName, object sender, DataReceivedEventArgs e)
238238
if (e.Data != null)
239239
LogMessage ($"[{linkerName} stderr] {e.Data}");
240240
}
241-
242-
static string QuoteFileName (string fileName)
243-
{
244-
var builder = new CommandLineBuilder ();
245-
builder.AppendFileNameIfNotNull (fileName);
246-
return builder.ToString ();
247-
}
248241
}
249242
}

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
43
using System.IO;
5-
using System.Text;
6-
using System.Threading;
74

85
using Microsoft.Build.Framework;
96
using Microsoft.Build.Utilities;
107

11-
using Xamarin.Android.Tools;
12-
using Xamarin.Build;
138
using Microsoft.Android.Build.Tasks;
149

1510
namespace Xamarin.Android.Tasks;
@@ -23,6 +18,12 @@ public class LinkNativeRuntime : AndroidAsyncTask
2318
[Required]
2419
public string AndroidBinUtilsDirectory { get; set; }
2520

21+
[Required]
22+
public string IntermediateOutputPath { get; set; }
23+
24+
[Required]
25+
public ITaskItem[] LinkLibraries { get; set; }
26+
2627
[Required]
2728
public ITaskItem[] NativeArchives { get; set; }
2829

@@ -44,11 +45,18 @@ void LinkRuntime (ITaskItem abiItem)
4445
{
4546
string abi = abiItem.ItemSpec;
4647
Log.LogDebugMessage ($"LinkRuntime ({abi})");
47-
var linker = new NativeLinker (Log, abi);
48+
ITaskItem outputRuntime = GetFirstAbiItem (OutputRuntimes, "_UnifiedNativeRuntime", abi);
49+
string soname = Path.GetFileNameWithoutExtension (outputRuntime.ItemSpec);
50+
if (soname.StartsWith ("lib", StringComparison.OrdinalIgnoreCase)) {
51+
soname = soname.Substring (3);
52+
}
53+
54+
var linker = new NativeLinker (Log, abi, soname, AndroidBinUtilsDirectory, IntermediateOutputPath);
4855
linker.Link (
49-
GetFirstAbiItem (OutputRuntimes, "_UnifiedNativeRuntime", abi),
56+
outputRuntime,
5057
GetAbiItems (NativeObjectFiles, "_NativeAssemblyTarget", abi),
51-
GetAbiItems (NativeArchives, "_SelectedNativeArchive", abi)
58+
GetAbiItems (NativeArchives, "_SelectedNativeArchive", abi),
59+
GetAbiItems (LinkLibraries, "_RequiredLinkLibraries", abi)
5260
);
5361
}
5462

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,5 +724,12 @@ internal static void DumpMarshalMethodsToConsole (string heading, IDictionary<st
724724
}
725725
}
726726
}
727+
728+
public static string QuoteFileNameArgument (string fileName)
729+
{
730+
var builder = new CommandLineBuilder ();
731+
builder.AppendFileNameIfNotNull (fileName);
732+
return builder.ToString ();
733+
}
727734
}
728735
}

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

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.IO;
23
using System.Collections.Generic;
4+
using System.Text;
35

46
using Microsoft.Build.Framework;
57
using Microsoft.Build.Utilities;
@@ -9,21 +11,113 @@ namespace Xamarin.Android.Tasks;
911

1012
class NativeLinker
1113
{
14+
static readonly List<string> standardArgs = new () {
15+
"--shared",
16+
"--as-needed",
17+
"--allow-shlib-undefined",
18+
"--compress-debug-sections",
19+
// TODO: test the commented-out flags
20+
// "--gc-sections",
21+
// "--icf=safe",
22+
// "--lto=full|thin",
23+
"--export-dynamic",
24+
"-z relro",
25+
"-z noexecstack",
26+
"--enable-new-dtags",
27+
"--build-id",
28+
"--warn-shared-textrel",
29+
"--fatal-warnings"
30+
};
31+
32+
readonly List<string> extraArgs = new ();
1233
readonly TaskLoggingHelper log;
1334
readonly string abi;
35+
readonly string ld;
36+
readonly string intermediateDir;
37+
38+
public bool StripDebugSymbols { get; set; }
39+
public bool SaveDebugSymbols { get; set; }
1440

15-
public NativeLinker (TaskLoggingHelper log, string abi)
41+
public NativeLinker (TaskLoggingHelper log, string abi, string soname, string binutilsDir, string intermediateDir)
1642
{
1743
this.log = log;
1844
this.abi = abi;
45+
this.intermediateDir = intermediateDir;
46+
47+
ld = Path.Combine (binutilsDir, MonoAndroidHelper.GetExecutablePath (binutilsDir, "ld"));
48+
49+
extraArgs.Add ($"-soname {soname}");
50+
51+
string? elfArch = null;
52+
switch (abi) {
53+
case "armeabi-v7a":
54+
extraArgs.Add ("-X");
55+
elfArch = "armelf_linux_eabi";
56+
break;
57+
58+
case "arm64":
59+
case "arm64-v8a":
60+
case "aarch64":
61+
extraArgs.Add ("--fix-cortex-a53-843419");
62+
elfArch = "aarch64linux";
63+
break;
64+
65+
case "x86":
66+
elfArch = "elf_i386";
67+
break;
68+
69+
case "x86_64":
70+
elfArch = "elf_x86_64";
71+
break;
72+
73+
default:
74+
throw new NotSupportedException ($"Unsupported Android target architecture ABI: {abi}");
75+
}
76+
77+
if (!String.IsNullOrEmpty (elfArch)) {
78+
extraArgs.Add ($"-m {elfArch}");
79+
}
1980
}
2081

21-
public void Link (ITaskItem outputLibraryPath, List<ITaskItem> objectFiles, List<ITaskItem> archives)
82+
public void Link (ITaskItem outputLibraryPath, List<ITaskItem> objectFiles, List<ITaskItem> archives, List<ITaskItem> libraries)
2283
{
2384
log.LogDebugMessage ($"Linking: {outputLibraryPath}");
2485
EnsureCorrectAbi (outputLibraryPath);
2586
EnsureCorrectAbi (objectFiles);
2687
EnsureCorrectAbi (archives);
88+
EnsureCorrectAbi (libraries);
89+
90+
string respFilePath = Path.Combine (intermediateDir, $"ld.{abi}.rsp");
91+
using (var sw = new StreamWriter (File.Open (respFilePath, FileMode.Create, FileAccess.Write, FileShare.Read), new UTF8Encoding (false))) {
92+
foreach (string arg in standardArgs) {
93+
sw.WriteLine (arg);
94+
}
95+
96+
foreach (string arg in extraArgs) {
97+
sw.WriteLine (arg);
98+
}
99+
100+
if (StripDebugSymbols && !SaveDebugSymbols) {
101+
sw.WriteLine ("-s");
102+
}
103+
104+
sw.Write ("-o ");
105+
sw.WriteLine (MonoAndroidHelper.QuoteFileNameArgument (outputLibraryPath.ItemSpec));
106+
107+
WriteFilesToResponseFile (sw, objectFiles);
108+
WriteFilesToResponseFile (sw, archives);
109+
110+
sw.Flush ();
111+
}
112+
113+
log.LogDebugMessage ($" Command line: {ld} @{respFilePath}");
114+
115+
void WriteFilesToResponseFile (StreamWriter sw, List<ITaskItem> files)
116+
{
117+
foreach (ITaskItem file in files) {
118+
sw.WriteLine (MonoAndroidHelper.QuoteFileNameArgument (file.ItemSpec));
119+
}
120+
}
27121
}
28122

29123
void EnsureCorrectAbi (ITaskItem item)

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,41 @@ public MonoComponentArchive (string name, string componentName, Func<Archive, bo
3535
readonly ITaskItem[] monoComponents;
3636

3737
public readonly List<Archive> KnownArchives;
38+
public readonly List<string> NativeLibraries;
3839

3940
public NativeRuntimeComponents (ITaskItem[] monoComponents)
4041
{
4142
this.monoComponents = monoComponents;
4243
KnownArchives = new () {
44+
// Mono components
4345
new MonoComponentArchive ("libmono-component-diagnostics_tracing-static.a", "diagnostics_tracing", MonoComponentPresent),
4446
new MonoComponentArchive ("libmono-component-diagnostics_tracing-stub-static.a", "diagnostics_tracing", MonoComponentAbsent),
4547
new MonoComponentArchive ("libmono-component-marshal-ilgen-static.a", "marshal-ilgen", MonoComponentPresent),
4648
new MonoComponentArchive ("libmono-component-marshal-ilgen-stub-static.a", "marshal-ilgen", MonoComponentAbsent),
4749

50+
// MonoVM runtime + BCL
4851
new Archive ("libmonosgen-2.0.a"),
4952
new Archive ("libSystem.Globalization.Native.a"),
5053
new Archive ("libSystem.IO.Compression.Native.a"),
5154
new Archive ("libSystem.Native.a"),
5255
new Archive ("libSystem.Security.Cryptography.Native.Android.a"),
56+
57+
// .NET for Android
58+
new Archive ("libruntime-base.a"),
59+
new Archive ("libxa-java-interop.a"),
60+
new Archive ("libxa-lz4.a"),
61+
new Archive ("libxa-shared-bits.a"),
62+
new Archive ("libmono-android.release-static.a"),
63+
};
64+
65+
// Just the base names of libraries to link into the unified runtime. Must have all the dependencies of all the static archives we
66+
// link into the final library.
67+
NativeLibraries = new () {
68+
"c",
69+
"dl",
70+
"m",
71+
"z",
72+
"log",
5373
};
5474
}
5575

src/native/java-interop/CMakeLists.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ target_compile_options(
3737
${XA_COMMON_CXX_ARGS}
3838
)
3939

40-
set_target_properties(
41-
${LIB_NAME}
42-
PROPERTIES
43-
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
44-
)
40+
if(DEBUG_BUILD)
41+
set_target_properties(
42+
${LIB_NAME}
43+
PROPERTIES
44+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
45+
)
46+
endif()
4547

4648
xa_add_compile_definitions(${LIB_NAME})

0 commit comments

Comments
 (0)