Skip to content

Commit e2f48e8

Browse files
committed
Stop using dlopen/dlsym to load Mono symbols
Since the dawn of time `Xamarin.Android` (nee `MonoAndroid`) used `dlopen/dlsym` to load Mono runtime symbols that were required for the managed applications to work on Android. This was done due to the fact that there had been no way to reliably load shared libraries referenced by the XA runtime in earlier versions of Android. However, thanks to the recent switch to API level 16 as our lowest supported level, we are now able to simply preload the shared libraries we depend on and, thus, allow the system linker to resolve all the symbols when loading `libmonodroid.so`. This, in turn, means we can now directly link `libmonosgen-2.0` on all target platforms (including all of the supported host operating systems) and, what's also very important, include Mono headers directly in our source. This makes sure we don't divert in definitions of various macros and functions that we use accross our runtime and that we continue to work with any version of Mono shipped in the Mono SDK archives. This commit removes all traces of the `DylibMono` class and it also renames all the C++ header files to have the `.hh` extension, to mirror the `.cc` source file convention and cleary mark the C++ headers as such, as opposed to the handful of C headers (`.h`) we have in our tree.
1 parent 5da8207 commit e2f48e8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+995
-2190
lines changed

Configuration.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
<MakeConcurrency Condition=" '$(MakeConcurrency)' == '' And '$(HostCpuCount)' != '' ">-j$(HostCpuCount)</MakeConcurrency>
5757
<ManagedRuntime Condition=" '$(ManagedRuntime)' == '' And '$(OS)' != 'Windows_NT' ">mono</ManagedRuntime>
5858
<ManagedRuntimeArgs Condition=" '$(ManagedRuntimeArgs)' == '' And '$(ManagedRuntime)' == 'mono' ">--debug=casts</ManagedRuntimeArgs>
59-
<MonoSgenBridgeVersion Condition=" '$(MonoSgenBridgeVersion)' == '' ">5</MonoSgenBridgeVersion>
6059
<HOME Condition=" '$(HOME)' == '' ">$(USERPROFILE)</HOME>
6160
<AndroidPreviousFrameworkVersion Condition=" '$(AndroidPreviousFrameworkVersion)' == '' ">v1.0</AndroidPreviousFrameworkVersion>
6261
<AndroidToolchainCacheDirectory Condition=" '$(AndroidToolchainCacheDirectory)' == '' ">$(HOME)\android-archives</AndroidToolchainCacheDirectory>

build-tools/scripts/PrepareWindows.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<_XAPrepareStandardArgs Condition=" '$(RunningOnCI)' == 'true' ">--no-emoji --run-mode=CI -a -v:d</_XAPrepareStandardArgs>
88
<_XAPrepareStandardArgs Condition=" '$(XA_FORCE_COMPONENT_REFRESH)' == 'true' ">$(_XAPrepareStandardArgs) -refresh</_XAPrepareStandardArgs>
99
<_XAPrepareBundleArgs Condition=" '$(BundleRootPath)' != '' ">--bundle-path=&quot;$(BundleRootPath)&quot;</_XAPrepareBundleArgs>
10+
<_XAPrepareBundleArgs Condition=" '$(RunMode)' == 'CI' ">$(_XAPrepareBundleArgs) -v:d</_XAPrepareBundleArgs>
1011
</PropertyGroup>
1112
<Import Project="$(_TopDir)\Configuration.props" />
1213
<Target Name="_BuildXAPrepare">

build-tools/xaprepare/xaprepare/Application/RuntimeFileType.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ enum RuntimeFileType
55
Other,
66
Binary,
77
StrippableBinary,
8+
SdkHeader,
89
}
910
}

build-tools/xaprepare/xaprepare/Application/Utilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ public static void DeleteDirectoryWithRetry (string directoryPath, bool recursiv
654654
return;
655655
} catch (IOException e) {
656656
ex = e;
657-
} catch (UnauthorizedAccessException e) {
657+
} catch (UnauthorizedAccessException e) {
658658
ex = e;
659659
tryResetFilePermissions = true;
660660
}

build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.MacOS.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ partial class Defaults
1818

1919
partial class Paths
2020
{
21+
const string LibMonoSgenBaseName = "libmonosgen-2.0";
22+
2123
public const string MonoCrossRuntimeInstallPath = "Darwin";
2224
public const string NdkToolchainOSTag = "darwin-x86_64";
25+
public static readonly string UnstrippedLibMonoSgenName = $"{LibMonoSgenBaseName}.d{Defaults.NativeLibraryExtension}";
26+
public static readonly string StrippedLibMonoSgenName = $"{LibMonoSgenBaseName}{Defaults.NativeLibraryExtension}";
2327
}
2428
}
2529
}

build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Unix.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ partial class Paths
2121

2222
public static string BCLTestsSourceDir => GetCachedPath (ref bclTestsSourceDir, () => Path.Combine (MonoProfileDir, "tests"));
2323
public static string BCLAssembliesSourceDir => MonoProfileDir;
24+
public static string HostRuntimeDir => GetCachedPath (ref hostRuntimeDir, () => Path.Combine (XAInstallPrefix, "xbuild", "Xamarin", "Android", "lib", $"host-{ctx.OS.Type}"));
2425

2526
public static readonly string MonoRuntimeHostMingwNativeLibraryPrefix = Path.Combine ("..", "bin");
27+
28+
static string hostRuntimeDir;
2629
}
2730
}
2831
}

build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ public static partial class Paths
267267
public static readonly string ExternalXamarinAndroidToolsSln = Path.Combine (ExternalDir, "xamarin-android-tools", "Xamarin.Android.Tools.sln");
268268
public static readonly string MxeSourceDir = Path.Combine (ExternalDir, "mxe");
269269
public static readonly string MonoSDKSRelativeOutputDir = Path.Combine ("sdks", "out");
270+
public static readonly string MonoSDKRelativeIncludeSourceDir = Path.Combine ("include", "mono-2.0", "mono");
270271
public static readonly string RuntimeInstallRelativeLibDir = "lib";
271272
public static readonly string PackageImageDependenciesTemplate = Path.Combine (BuildToolsScriptsDir, "prepare-image-dependencies.sh.in");
272273
public static readonly string PackageImageDependenciesOutput = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "prepare-image-dependencies.sh");
@@ -278,6 +279,7 @@ public static partial class Paths
278279
public static string MonoSDKSOutputDir => GetCachedPath (ref monoSDKsOutputDir, () => Path.Combine (MonoSourceFullPath, MonoSDKSRelativeOutputDir));
279280
public static string MonoProfileDir => GetCachedPath (ref monoProfileDir, () => Path.Combine (MonoSDKSOutputDir, "android-bcl", "monodroid"));
280281
public static string MonoProfileToolsDir => GetCachedPath (ref monoProfileToolsDir, () => Path.Combine (MonoSDKSOutputDir, "android-bcl", "monodroid_tools"));
282+
public static string MonoSDKIncludeDestinationDir => GetCachedPath (ref monoSDKSIncludeDestDir, () => Path.Combine (OutputIncludeDir, "mono-2.0", "mono"));
281283

282284
public static string BCLFacadeAssembliesSourceDir => GetCachedPath (ref bclFacadeAssembliesSourceDir, () => Path.Combine (BCLAssembliesSourceDir, "Facades"));
283285
public static string BCLHostAssembliesSourceDir => BCLAssembliesSourceDir;
@@ -422,6 +424,7 @@ static string GetCachedPath (ref string variable, Func<string> creator)
422424
static string externalJavaInteropDir;
423425
static string monoSdksTpnPath;
424426
static string monoSdksTpnExternalPath;
427+
static string monoSDKSIncludeDestDir;
425428
}
426429
}
427430
}
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
6+
namespace Xamarin.Android.Prepare
7+
{
8+
partial class Runtimes
9+
{
10+
static Context ctx => Context.Instance;
11+
12+
static string GetMonoUtilitySourcePath (string utilityName)
13+
{
14+
return Path.Combine (Configurables.Paths.MonoProfileToolsDir, utilityName);
15+
}
16+
17+
static string GetLlvmOutputSourcePath (Runtime runtime)
18+
{
19+
var llvmRuntime = EnsureRuntimeType<LlvmRuntime> (runtime, "LLVM");
20+
return Path.Combine (GetLlvmInputDir (runtime), "bin");
21+
}
22+
23+
static string GetLlvmOutputDestinationPath (Runtime runtime)
24+
{
25+
var llvmRuntime = EnsureRuntimeType<LlvmRuntime> (runtime, "LLVM");
26+
return llvmRuntime.InstallPath;
27+
}
28+
29+
static string GetMonoPosixHelperOutputSourcePath (Runtime runtime)
30+
{
31+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
32+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"{monoRuntime.OutputMonoPosixHelperFilename}{monoRuntime.NativeLibraryExtension}");
33+
}
34+
35+
static string GetMonoPosixHelperOutputDestinationPath (Runtime runtime, bool debug)
36+
{
37+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
38+
return Path.Combine (GetRuntimeOutputDir (runtime), $"{monoRuntime.OutputMonoPosixHelperFilename}{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
39+
}
40+
41+
static string GetMonoBtlsOutputSourcePath (Runtime runtime)
42+
{
43+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
44+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"{monoRuntime.OutputMonoBtlsFilename}{monoRuntime.NativeLibraryExtension}");
45+
}
46+
47+
static string GetMonoBtlsOutputDestinationPath (Runtime runtime, bool debug)
48+
{
49+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
50+
return Path.Combine (GetRuntimeOutputDir (runtime), $"{monoRuntime.OutputMonoBtlsFilename}{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
51+
}
52+
53+
static string GetAotProfilerOutputSourcePath (Runtime runtime)
54+
{
55+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
56+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"{monoRuntime.OutputAotProfilerFilename}{monoRuntime.NativeLibraryExtension}");
57+
}
58+
59+
static string GetAotProfilerOutputDestinationPath (Runtime runtime, bool debug)
60+
{
61+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
62+
return Path.Combine (GetRuntimeOutputDir (runtime), $"{monoRuntime.OutputAotProfilerFilename}{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
63+
}
64+
65+
static string GetProfilerOutputSourcePath (Runtime runtime)
66+
{
67+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
68+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"{monoRuntime.OutputProfilerFilename}{monoRuntime.NativeLibraryExtension}");
69+
}
70+
71+
static string GetProfilerOutputDestinationPath (Runtime runtime, bool debug)
72+
{
73+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
74+
return Path.Combine (GetRuntimeOutputDir (runtime), $"{monoRuntime.OutputProfilerFilename}{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
75+
}
76+
77+
static string GetCrossRuntimeOutputSourcePath (Runtime runtime)
78+
{
79+
var crossRuntime = EnsureRuntimeType<MonoCrossRuntime> (runtime, "cross compilation");
80+
return Path.Combine (MonoRuntimesHelpers.GetRootDir (runtime), "bin", $"{crossRuntime.ExePrefix}mono-sgen{crossRuntime.ExeSuffix}");
81+
}
82+
83+
static string GetCrossRuntimeOutputDestinationPath (Runtime runtime, bool debug)
84+
{
85+
var crossRuntime = EnsureRuntimeType<MonoCrossRuntime> (runtime, "cross compilation");
86+
string runtimeName = $"{crossRuntime.CrossMonoName}{GetDebugInfix (debug)}{crossRuntime.ExeSuffix}";
87+
if (String.IsNullOrEmpty (crossRuntime.InstallPath))
88+
return runtimeName;
89+
90+
return Path.Combine (crossRuntime.InstallPath, runtimeName);
91+
}
92+
93+
static string GetRuntimeOutputSourcePath (Runtime runtime)
94+
{
95+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
96+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"{monoRuntime.OutputRuntimeFilename}{monoRuntime.NativeLibraryExtension}");
97+
}
98+
99+
static string GetRuntimeOutputDestinationPath (Runtime runtime, bool debug)
100+
{
101+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
102+
return Path.Combine (GetRuntimeOutputDir (runtime), $"{monoRuntime.OutputRuntimeFilename}{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
103+
}
104+
105+
static string GetMonoNativeOutputSourcePath (Runtime runtime)
106+
{
107+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
108+
if (IsAbi (runtime, AbiNames.HostJit.Darwin))
109+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"libmono-native-compat{monoRuntime.NativeLibraryExtension}");
110+
111+
return Path.Combine (GetAndroidInputLibDir (runtime), monoRuntime.NativeLibraryDirPrefix, $"libmono-native{monoRuntime.NativeLibraryExtension}");
112+
}
113+
114+
static string GetMonoNativeOutputDestinationPath (Runtime runtime, bool debug)
115+
{
116+
var monoRuntime = EnsureRuntimeType<MonoRuntime> (runtime, "Mono");
117+
return Path.Combine (GetRuntimeOutputDir (runtime), $"libmono-native{GetDebugInfix (debug)}{monoRuntime.NativeLibraryExtension}");
118+
}
119+
120+
static string GetDebugInfix (bool debug)
121+
{
122+
return debug ? Configurables.Defaults.DebugBinaryInfix : String.Empty;
123+
}
124+
125+
static bool IsHostOrTargetRuntime (Runtime runtime)
126+
{
127+
return IsRuntimeType<MonoJitRuntime> (runtime) || IsRuntimeType<MonoHostRuntime> (runtime);
128+
}
129+
130+
static T EnsureRuntimeType<T> (Runtime runtime, string typeName) where T: Runtime
131+
{
132+
var ret = runtime.As<T> ();
133+
if (ret == null)
134+
throw new InvalidOperationException ($"Runtime {runtime.Name} is not a {typeName} runtime");
135+
136+
return ret;
137+
}
138+
139+
static bool IsRuntimeType <T> (Runtime runtime) where T: Runtime
140+
{
141+
return runtime.As<T>() != null;
142+
}
143+
144+
static bool IsWindowsRuntime (Runtime runtime)
145+
{
146+
return String.Compare (runtime.ExeSuffix, Configurables.Defaults.WindowsExecutableSuffix, StringComparison.Ordinal) == 0;
147+
}
148+
149+
static bool IsAbi (Runtime runtime, string abiName, params string[] furtherAbiNames)
150+
{
151+
if (ExpectedAbi (abiName))
152+
return true;
153+
154+
if (furtherAbiNames == null)
155+
return false;
156+
157+
foreach (string a in furtherAbiNames) {
158+
if (ExpectedAbi (a))
159+
return true;
160+
}
161+
162+
return false;
163+
164+
bool ExpectedAbi (string abi)
165+
{
166+
if (String.IsNullOrEmpty (abi))
167+
return false;
168+
169+
return String.Compare (abi, runtime.Name ?? String.Empty, StringComparison.Ordinal) == 0;
170+
}
171+
}
172+
173+
static string GetLlvmInputDir (Runtime runtime)
174+
{
175+
return GetLlvmInputRootDir (runtime);
176+
}
177+
178+
static string GetLlvmInputRootDir (Runtime runtime)
179+
{
180+
return Path.Combine (Configurables.Paths.MonoSDKSRelativeOutputDir, $"llvm-{runtime.PrefixedName}");
181+
}
182+
183+
static string GetAndroidInputLibDir (Runtime runtime)
184+
{
185+
return Path.Combine (MonoRuntimesHelpers.GetRootDir (runtime), "lib");
186+
}
187+
188+
static string GetRuntimeOutputDir (Runtime runtime)
189+
{
190+
return Path.Combine (Configurables.Paths.RuntimeInstallRelativeLibDir, runtime.PrefixedName);
191+
}
192+
193+
static bool IsLlvmRuntimeEnabled (Context ctx, string llvmAbi)
194+
{
195+
bool enabled = false;
196+
bool windows = ctx.IsLlvmWindowsAbi (llvmAbi);
197+
bool is64Bit = ctx.Is64BitLlvmAbi (llvmAbi);
198+
199+
HashSet<string> targets;
200+
if (windows)
201+
targets = is64Bit ? AbiNames.All64BitWindowsAotAbis : AbiNames.All32BitWindowsAotAbis;
202+
else
203+
targets = is64Bit ? AbiNames.All64BitHostAotAbis : AbiNames.All32BitHostAotAbis;
204+
205+
foreach (string target in targets) {
206+
if (Context.Instance.IsTargetAotAbiEnabled (target)) {
207+
enabled = true;
208+
break;
209+
}
210+
}
211+
212+
return enabled && (!is64Bit || Context.Instance.OS.Is64Bit);
213+
}
214+
215+
public Runtimes ()
216+
{
217+
Context c = ctx;
218+
foreach (Runtime runtime in Items) {
219+
runtime.Init (c);
220+
}
221+
222+
DesignerHostBclFilesToInstall = new List<BclFile> ();
223+
DesignerWindowsBclFilesToInstall = new List<BclFile> ();
224+
225+
PopulateDesignerBclFiles (DesignerHostBclFilesToInstall, DesignerWindowsBclFilesToInstall);
226+
}
227+
228+
List<BclFile> BclToDesigner (BclFileTarget ignoreForTarget)
229+
{
230+
return BclFilesToInstall.Where (bf => ShouldIncludeDesignerBcl (bf)).Select (bf => new BclFile (bf.Name, bf.Type, excludeDebugSymbols: true, version: bf.Version, target: ignoreForTarget)).ToList ();
231+
232+
bool ShouldIncludeDesignerBcl (BclFile bf)
233+
{
234+
if (DesignerIgnoreFiles == null || !DesignerIgnoreFiles.TryGetValue (bf.Name, out (BclFileType Type, BclFileTarget Target) bft)) {
235+
return true;
236+
}
237+
238+
if (bf.Type != bft.Type || bft.Target != ignoreForTarget)
239+
return true;
240+
241+
Log.Instance.DebugLine ($"BCL file {bf.Name} will NOT be included in the installed Designer BCL files ({ignoreForTarget})");
242+
return false;
243+
}
244+
}
245+
246+
partial void PopulateDesignerBclFiles (List<BclFile> designerHostBclFilesToInstall, List<BclFile> designerWindowsBclFilesToInstall);
247+
248+
List<BundleItem> bundleItems;
249+
}
250+
}

0 commit comments

Comments
 (0)