Skip to content

Commit c97af07

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 d9348eb commit c97af07

Some content is hidden

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

45 files changed

+973
-2221
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
[submodule "external/Java.Interop"]
1010
path = external/Java.Interop
1111
url = https://github.com/xamarin/java.interop.git
12-
branch = master
12+
branch = drop-dylibmono
1313
[submodule "external/libzip"]
1414
path = external/libzip
1515
url = https://github.com/nih-at/libzip.git

Configuration.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
<MakeConcurrency Condition=" '$(MakeConcurrency)' == '' And '$(HostCpuCount)' != '' ">-j$(HostCpuCount)</MakeConcurrency>
6161
<ManagedRuntime Condition=" '$(ManagedRuntime)' == '' And '$(OS)' != 'Windows_NT' ">mono</ManagedRuntime>
6262
<ManagedRuntimeArgs Condition=" '$(ManagedRuntimeArgs)' == '' And '$(ManagedRuntime)' == 'mono' ">--debug=casts</ManagedRuntimeArgs>
63-
<MonoSgenBridgeVersion Condition=" '$(MonoSgenBridgeVersion)' == '' ">5</MonoSgenBridgeVersion>
6463
<HOME Condition=" '$(HOME)' == '' ">$(USERPROFILE)</HOME>
6564
<AndroidPreviousFrameworkVersion Condition=" '$(AndroidPreviousFrameworkVersion)' == '' ">v1.0</AndroidPreviousFrameworkVersion>
6665
<AndroidToolchainCacheDirectory Condition=" '$(AndroidToolchainCacheDirectory)' == '' ">$(HOME)\android-archives</AndroidToolchainCacheDirectory>

build-tools/automation/azure-pipelines.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ stages:
168168
inputs:
169169
solution: Xamarin.Android.sln
170170
configuration: $(XA.Build.Configuration)
171-
msbuildArguments: $(AutoProvisionArgs) $(AndroidTargetAbiArgs) /t:Prepare /bl:$(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\msbuild-prepare.binlog /p:BundleRootPath=$(System.DefaultWorkingDirectory)
171+
msbuildArguments: $(AutoProvisionArgs) $(AndroidTargetAbiArgs) /t:Prepare /bl:$(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\msbuild-prepare.binlog /p:BundleRootPath=$(System.DefaultWorkingDirectory) /p:RunMode=CI
172172

173173
- task: MSBuild@1
174174
displayName: msbuild Xamarin.Android /t:Build

build-tools/scripts/PrepareWindows.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<_XAPrepareExe>$(MSBuildThisFileDirectory)..\xaprepare\xaprepare\bin\$(Configuration)\xaprepare.exe</_XAPrepareExe>
77
<_XAPrepareStandardArgs>--no-emoji --run-mode=CI -a</_XAPrepareStandardArgs>
88
<_XAPrepareBundleArgs Condition=" '$(BundleRootPath)' != '' ">--bundle-path=&quot;$(BundleRootPath)&quot;</_XAPrepareBundleArgs>
9+
<_XAPrepareBundleArgs Condition=" '$(RunMode)' == 'CI' ">$(_XAPrepareBundleArgs) -v:d</_XAPrepareBundleArgs>
910
</PropertyGroup>
1011
<Import Project="$(_TopDir)\Configuration.props" />
1112
<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/ConfigAndData/Configurables.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ public static partial class Paths
257257
public static readonly string ExternalXamarinAndroidToolsSln = Path.Combine (ExternalDir, "xamarin-android-tools", "Xamarin.Android.Tools.sln");
258258
public static readonly string MxeSourceDir = Path.Combine (ExternalDir, "mxe");
259259
public static readonly string MonoSDKSRelativeOutputDir = Path.Combine ("sdks", "out");
260+
public static readonly string MonoSDKRelativeIncludeSourceDir = Path.Combine ("include", "mono-2.0", "mono");
260261
public static readonly string RuntimeInstallRelativeLibDir = "lib";
261262
public static readonly string PackageImageDependenciesTemplate = Path.Combine (BuildToolsScriptsDir, "prepare-image-dependencies.sh.in");
262263
public static readonly string PackageImageDependenciesOutput = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "prepare-image-dependencies.sh");
@@ -268,6 +269,7 @@ public static partial class Paths
268269
public static string MonoSDKSOutputDir => GetCachedPath (ref monoSDKsOutputDir, () => Path.Combine (MonoSourceFullPath, MonoSDKSRelativeOutputDir));
269270
public static string MonoProfileDir => GetCachedPath (ref monoProfileDir, () => Path.Combine (MonoSDKSOutputDir, "android-bcl", "monodroid"));
270271
public static string MonoProfileToolsDir => GetCachedPath (ref monoProfileToolsDir, () => Path.Combine (MonoSDKSOutputDir, "android-bcl", "monodroid_tools"));
272+
public static string MonoSDKIncludeDestinationDir => GetCachedPath (ref monoSDKSIncludeDestDir, () => Path.Combine (OutputIncludeDir, "mono-2.0", "mono"));
271273

272274
public static string BCLFacadeAssembliesSourceDir => GetCachedPath (ref bclFacadeAssembliesSourceDir, () => Path.Combine (BCLAssembliesSourceDir, "Facades"));
273275
public static string BCLHostAssembliesSourceDir => BCLAssembliesSourceDir;
@@ -342,8 +344,8 @@ public static partial class Paths
342344
// * The "file" part must always be a valid glob pattern
343345
//
344346
public static readonly List<string> BundleVersionHashFiles = new List<string> {
345-
Path.Combine (BuildToolsScriptsDir, "BuildEverything.mk"),
346347
Path.Combine (BuildPaths.XAPrepareSourceDir, "ConfigAndData", "BuildAndroidPlatforms.cs"),
348+
Path.Combine (BuildPaths.XAPrepareSourceDir, "ConfigAndData", "Runtimes.cs"),
347349
};
348350

349351
public static string AndroidToolchainBinDirectory => EnsureAndroidToolchainBinDirectories ();
@@ -409,6 +411,7 @@ static string GetCachedPath (ref string variable, Func<string> creator)
409411
static string installBCLDesignerDir;
410412
static string monoAndroidFrameworksRootDir;
411413
static string externalJavaInteropDir;
414+
static string monoSDKSIncludeDestDir;
412415
}
413416
}
414417
}
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
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 IsAbi (Runtime runtime, string abiName, params string[] furtherAbiNames)
145+
{
146+
if (ExpectedAbi (abiName))
147+
return true;
148+
149+
if (furtherAbiNames == null)
150+
return false;
151+
152+
foreach (string a in furtherAbiNames) {
153+
if (ExpectedAbi (a))
154+
return true;
155+
}
156+
157+
return false;
158+
159+
bool ExpectedAbi (string abi)
160+
{
161+
if (String.IsNullOrEmpty (abi))
162+
return false;
163+
164+
return String.Compare (abi, runtime.Name ?? String.Empty, StringComparison.Ordinal) == 0;
165+
}
166+
}
167+
168+
static string GetLlvmInputDir (Runtime runtime)
169+
{
170+
return GetLlvmInputRootDir (runtime);
171+
}
172+
173+
static string GetLlvmInputRootDir (Runtime runtime)
174+
{
175+
return Path.Combine (Configurables.Paths.MonoSDKSRelativeOutputDir, $"llvm-{runtime.PrefixedName}");
176+
}
177+
178+
static string GetAndroidInputLibDir (Runtime runtime)
179+
{
180+
return Path.Combine (MonoRuntimesHelpers.GetRootDir (runtime), "lib");
181+
}
182+
183+
static string GetRuntimeOutputDir (Runtime runtime)
184+
{
185+
return Path.Combine (Configurables.Paths.RuntimeInstallRelativeLibDir, runtime.PrefixedName);
186+
}
187+
188+
static bool IsLlvmRuntimeEnabled (Context ctx, string llvmAbi)
189+
{
190+
bool enabled = false;
191+
bool windows = ctx.IsLlvmWindowsAbi (llvmAbi);
192+
bool is64Bit = ctx.Is64BitLlvmAbi (llvmAbi);
193+
194+
HashSet<string> targets;
195+
if (windows)
196+
targets = is64Bit ? AbiNames.All64BitWindowsAotAbis : AbiNames.All32BitWindowsAotAbis;
197+
else
198+
targets = is64Bit ? AbiNames.All64BitHostAotAbis : AbiNames.All32BitHostAotAbis;
199+
200+
foreach (string target in targets) {
201+
if (Context.Instance.IsTargetAotAbiEnabled (target)) {
202+
enabled = true;
203+
break;
204+
}
205+
}
206+
207+
return enabled && (!is64Bit || Context.Instance.OS.Is64Bit);
208+
}
209+
210+
public Runtimes ()
211+
{
212+
Context c = ctx;
213+
foreach (Runtime runtime in Items) {
214+
runtime.Init (c);
215+
}
216+
217+
DesignerHostBclFilesToInstall = BclToDesigner (BclFileTarget.DesignerHost);
218+
DesignerWindowsBclFilesToInstall = BclToDesigner (BclFileTarget.DesignerWindows);
219+
220+
List<BclFile> BclToDesigner (BclFileTarget ignoreForTarget)
221+
{
222+
return BclFilesToInstall.Where (bf => ShouldInclude (bf, ignoreForTarget)).Select (bf => new BclFile (bf.Name, bf.Type, excludeDebugSymbols: true, version: bf.Version, target: ignoreForTarget)).ToList ();
223+
}
224+
225+
bool ShouldInclude (BclFile bf, BclFileTarget ignoreForTarget)
226+
{
227+
if (DesignerIgnoreFiles == null || !DesignerIgnoreFiles.TryGetValue (bf.Name, out (BclFileType Type, BclFileTarget Target) bft)) {
228+
return true;
229+
}
230+
231+
if (bf.Type != bft.Type || bft.Target != ignoreForTarget)
232+
return true;
233+
234+
Log.Instance.DebugLine ($"BCL file {bf.Name} will NOT be included in the installed Designer BCL files ({ignoreForTarget})");
235+
return false;
236+
}
237+
}
238+
239+
List<BundleItem> bundleItems;
240+
}
241+
}

0 commit comments

Comments
 (0)