[mtouch] Move mtouch's GenerateMain to shared Target code.

This means moving a lot of supporting code to shared code as well.
This commit is contained in:
Rolf Bjarne Kvinge 2020-10-22 21:05:58 +02:00
Родитель f513501443
Коммит 6240e848f3
12 изменённых файлов: 415 добавлений и 405 удалений

Просмотреть файл

@ -79,6 +79,8 @@ namespace Xamarin.Bundler {
public bool IsExtension;
public ApplePlatform Platform { get { return Driver.TargetFramework.Platform; } }
public List<string> InterpretedAssemblies = new List<string> ();
// Linker config
public LinkMode LinkMode = LinkMode.Full;
public List<string> LinkSkipped = new List<string> ();
@ -112,6 +114,80 @@ namespace Xamarin.Bundler {
public bool? DisableOmitFramePointer = null; // Only applicable to Xamarin.Mac
public string CustomBundleName = "MonoBundle"; // Only applicable to Xamarin.Mac
public bool? UseMonoFramework;
public BitCodeMode BitCodeMode { get; set; }
public bool EnableAsmOnlyBitCode { get { return BitCodeMode == BitCodeMode.ASMOnly; } }
public bool EnableLLVMOnlyBitCode { get { return BitCodeMode == BitCodeMode.LLVMOnly; } }
public bool EnableMarkerOnlyBitCode { get { return BitCodeMode == BitCodeMode.MarkerOnly; } }
public bool EnableBitCode { get { return BitCodeMode != BitCodeMode.None; } }
Dictionary<string, Tuple<AssemblyBuildTarget, string>> assembly_build_targets = new Dictionary<string, Tuple<AssemblyBuildTarget, string>> ();
public AssemblyBuildTarget LibMonoLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks || UseMonoFramework.Value) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibXamarinLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibPInvokesLinkMode => LibXamarinLinkMode;
public AssemblyBuildTarget LibProfilerLinkMode => OnlyStaticLibraries ? AssemblyBuildTarget.StaticObject : AssemblyBuildTarget.DynamicLibrary;
public AssemblyBuildTarget LibMonoNativeLinkMode => HasDynamicLibraries ? AssemblyBuildTarget.DynamicLibrary : AssemblyBuildTarget.StaticObject;
public bool OnlyStaticLibraries {
get {
return assembly_build_targets.All ((abt) => abt.Value.Item1 == AssemblyBuildTarget.StaticObject);
}
}
public bool HasDynamicLibraries {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.DynamicLibrary);
}
}
public bool HasFrameworks {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.Framework);
}
}
public bool HasFrameworksDirectory {
get {
if (Platform == ApplePlatform.MacOSX)
return false;
if (!IsExtension)
return true;
if (IsWatchExtension && Platform == ApplePlatform.WatchOS)
return true;
return false;
}
}
bool RequiresXcodeHeaders {
get {
switch (Platform) {
@ -1108,5 +1184,49 @@ namespace Xamarin.Bundler {
break;
}
}
public bool IsInterpreted (string assembly)
{
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both.
if (!UseInterpreter)
return false;
// Go through the list of assemblies to interpret in reverse order,
// so that the last option passed to mtouch takes precedence.
for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) {
var opt = InterpretedAssemblies [i];
if (opt == "all")
return true;
else if (opt == "-all")
return false;
else if (opt == assembly)
return true;
else if (opt [0] == '-' && opt.Substring (1) == assembly)
return false;
}
// There's an implicit 'all' at the start of the list.
return true;
}
public bool IsAOTCompiled (string assembly)
{
if (!UseInterpreter)
return true;
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both:
// - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work
// - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not)
if (assembly == "mscorlib")
return true;
return !IsInterpreted (assembly);
}
public string AssemblyName {
get {
return Path.GetFileName (RootAssemblies [0]);
}
}
}
}

Просмотреть файл

@ -48,6 +48,9 @@ namespace Xamarin.Bundler {
public partial class Assembly
{
public AssemblyBuildTarget BuildTarget;
public string BuildTargetName;
public bool IsCodeShared;
public List<string> Satellites;
public Application App { get { return Target.App; } }
@ -722,6 +725,12 @@ namespace Xamarin.Bundler {
Application.UpdateFile (config_src, config_target, true);
}
}
public bool IsAOTCompiled {
get {
return App.IsAOTCompiled (Identity);
}
}
}
public sealed class NormalizedStringComparer : IEqualityComparer<string>

Просмотреть файл

@ -0,0 +1,8 @@
namespace Xamarin.Bundler {
public enum BitCodeMode {
None = 0,
ASMOnly = 1,
LLVMOnly = 2,
MarkerOnly = 3,
}
}

Просмотреть файл

@ -559,5 +559,270 @@ namespace Xamarin.Bundler {
return sb.ToString ();
}
// note: this is executed under Parallel.ForEach
public string GenerateIOSMain (Abi abi, string main_source, IList<string> registration_methods)
{
var app = App;
var assemblies = Assemblies;
var assembly_name = App.AssemblyName;
var assembly_externs = new StringBuilder ();
var assembly_aot_modules = new StringBuilder ();
var register_assemblies = new StringBuilder ();
var assembly_location = new StringBuilder ();
var assembly_location_count = 0;
var enable_llvm = (abi & Abi.LLVM) != 0;
register_assemblies.AppendLine ("\tguint32 exception_gchandle = 0;");
foreach (var s in assemblies) {
if (!s.IsAOTCompiled)
continue;
if ((abi & Abi.SimulatorArchMask) == 0) {
var info = s.AssemblyDefinition.Name.Name;
info = EncodeAotSymbol (info);
assembly_externs.Append ("extern void *mono_aot_module_").Append (info).AppendLine ("_info;");
assembly_aot_modules.Append ("\tmono_aot_register_module (mono_aot_module_").Append (info).AppendLine ("_info);");
}
string sname = s.FileName;
if (assembly_name != sname && IsBoundAssembly (s)) {
register_assemblies.Append ("\txamarin_open_and_register (\"").Append (sname).Append ("\", &exception_gchandle);").AppendLine ();
register_assemblies.AppendLine ("\txamarin_process_managed_exception_gchandle (exception_gchandle);");
}
}
if ((abi & Abi.SimulatorArchMask) == 0 || app.Embeddinator) {
var frameworks = assemblies.Where ((a) => a.BuildTarget == AssemblyBuildTarget.Framework)
.OrderBy ((a) => a.Identity, StringComparer.Ordinal);
foreach (var asm_fw in frameworks) {
var asm_name = asm_fw.Identity;
if (asm_fw.BuildTargetName == asm_name)
continue; // this is deduceable
var prefix = string.Empty;
if (!app.HasFrameworksDirectory && asm_fw.IsCodeShared)
prefix = "../../";
var suffix = string.Empty;
if (app.IsSimulatorBuild)
suffix = "/simulator";
assembly_location.AppendFormat ("\t{{ \"{0}\", \"{2}Frameworks/{1}.framework/MonoBundle{3}\" }},\n", asm_name, asm_fw.BuildTargetName, prefix, suffix);
assembly_location_count++;
}
}
try {
StringBuilder sb = new StringBuilder ();
using (var sw = new StringWriter (sb)) {
sw.WriteLine ("#include \"xamarin/xamarin.h\"");
if (assembly_location.Length > 0) {
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocation assembly_location_entries [] = {");
sw.WriteLine (assembly_location);
sw.WriteLine ("};");
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocations assembly_locations = {{ {0}, assembly_location_entries }};", assembly_location_count);
}
sw.WriteLine ();
sw.WriteLine (assembly_externs);
sw.WriteLine ("void xamarin_register_modules_impl ()");
sw.WriteLine ("{");
sw.WriteLine (assembly_aot_modules);
sw.WriteLine ("}");
sw.WriteLine ();
sw.WriteLine ("void xamarin_register_assemblies_impl ()");
sw.WriteLine ("{");
sw.WriteLine (register_assemblies);
sw.WriteLine ("}");
sw.WriteLine ();
if (registration_methods != null) {
foreach (var method in registration_methods) {
sw.Write ("extern \"C\" void ");
sw.Write (method);
sw.WriteLine ("();");
}
}
// Burn in a reference to the profiling symbol so that the native linker doesn't remove it
// On iOS we can pass -u to the native linker, but that doesn't work on tvOS, where
// we're building with bitcode (even when bitcode is disabled, we still build with the
// bitcode marker, which makes the linker reject -u).
if (app.EnableProfiling) {
sw.WriteLine ("extern \"C\" { void mono_profiler_init_log (); }");
sw.WriteLine ("typedef void (*xamarin_profiler_symbol_def)();");
sw.WriteLine ("extern xamarin_profiler_symbol_def xamarin_profiler_symbol;");
sw.WriteLine ("xamarin_profiler_symbol_def xamarin_profiler_symbol = NULL;");
}
if (app.UseInterpreter) {
sw.WriteLine ("extern \"C\" { void mono_ee_interp_init (const char *); }");
sw.WriteLine ("extern \"C\" { void mono_icall_table_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_marshal_ilgen_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_method_builder_ilgen_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_sgen_mono_ilgen_init (void); }");
}
sw.WriteLine ("void xamarin_setup_impl ()");
sw.WriteLine ("{");
if (app.EnableProfiling)
sw.WriteLine ("\txamarin_profiler_symbol = mono_profiler_init_log;");
if (app.EnableLLVMOnlyBitCode)
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);");
else if (app.UseInterpreter) {
sw.WriteLine ("\tmono_icall_table_init ();");
sw.WriteLine ("\tmono_marshal_ilgen_init ();");
sw.WriteLine ("\tmono_method_builder_ilgen_init ();");
sw.WriteLine ("\tmono_sgen_mono_ilgen_init ();");
sw.WriteLine ("\tmono_ee_interp_init (NULL);");
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_INTERP);");
} else if (app.IsDeviceBuild)
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
if (assembly_location.Length > 0)
sw.WriteLine ("\txamarin_set_assembly_directories (&assembly_locations);");
if (registration_methods != null) {
for (int i = 0; i < registration_methods.Count; i++) {
sw.Write ("\t");
sw.Write (registration_methods [i]);
sw.WriteLine ("();");
}
}
if (app.MonoNativeMode != MonoNativeMode.None) {
string mono_native_lib;
if (app.LibMonoNativeLinkMode == AssemblyBuildTarget.StaticObject)
mono_native_lib = "__Internal";
else
mono_native_lib = app.GetLibNativeName () + ".dylib";
sw.WriteLine ();
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Native\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Security.Cryptography.Native.Apple\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Net.Security.Native\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ();
}
if (app.EnableDebug)
sw.WriteLine ("\txamarin_gc_pump = {0};", app.DebugTrack.Value ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_init_mono_debug = {0};", app.PackageManagedDebugSymbols ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_executable_name = \"{0}\";", assembly_name);
sw.WriteLine ("\tmono_use_llvm = {0};", enable_llvm ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_log_level = {0};", Driver.Verbosity.ToString (CultureInfo.InvariantCulture));
sw.WriteLine ("\txamarin_arch_name = \"{0}\";", abi.AsArchString ());
if (!app.IsDefaultMarshalManagedExceptionMode)
sw.WriteLine ("\txamarin_marshal_managed_exception_mode = MarshalManagedExceptionMode{0};", app.MarshalManagedExceptions);
sw.WriteLine ("\txamarin_marshal_objectivec_exception_mode = MarshalObjectiveCExceptionMode{0};", app.MarshalObjectiveCExceptions);
if (app.EnableDebug)
sw.WriteLine ("\txamarin_debug_mode = TRUE;");
if (!string.IsNullOrEmpty (app.MonoGCParams))
sw.WriteLine ("\tsetenv (\"MONO_GC_PARAMS\", \"{0}\", 1);", app.MonoGCParams);
foreach (var kvp in app.EnvironmentVariables)
sw.WriteLine ("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace ("\"", "\\\""), kvp.Value.Replace ("\"", "\\\""));
sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE");
sw.WriteLine ("}");
sw.WriteLine ();
sw.Write ("int ");
sw.Write (app.IsWatchExtension ? "xamarin_watchextension_main" : "main");
sw.WriteLine (" (int argc, char **argv)");
sw.WriteLine ("{");
sw.WriteLine ("\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];");
if (app.IsExtension) {
// the name of the executable must be the bundle id (reverse dns notation)
// but we do not want to impose that (ugly) restriction to the managed .exe / project name / ...
sw.WriteLine ("\targv [0] = (char *) \"{0}\";", Path.GetFileNameWithoutExtension (app.RootAssemblies [0]));
sw.WriteLine ("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeExtension);");
} else {
sw.WriteLine ("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeApp);");
}
sw.WriteLine ("\t[pool drain];");
sw.WriteLine ("\treturn rv;");
sw.WriteLine ("}");
string extension_main = null;
if (app.Platform == ApplePlatform.WatchOS && app.IsWatchExtension) {
// We're building a watch extension, and we have multiple scenarios, depending on the watchOS version we're executing on:
//
// * watchOS 2.0 -> 5.*: we must call a `main` function provided in the WatchKit framework.
// * watchOS 6.0 -> * : we must call a `WKExtensionMain` function provided in the WatchKit framework.
// * watchOS 7.0 -> * : The `WKExtensionMain` function uses dlsym to find any `main` functions in the
// main executable, and calls that function (otherwise WKExtensionMain will call
// UIApplicationMain and normal startup occurs)
//
// * We can't call our entry point "main", because we call WKExtensionMain, and then we run into an
// infinite loop on watchOS 7.0. So we call it xamarin_watch_extension_main.
// * The watchOS 6+ SDK helpfully provides a static library (WKExtensionMainLegacy) that has a
// WKExtensionMain function, which we use when the deployment target is earlier than watchOS 6.0.
// This means that calling WKExtensionMain works everywhere (as long as we're using the
// watchOS 6+ SDK to build; otherwise we just call "main" directly and don't link with the
// WKExtensionMainLegacy library)
if (app.SdkVersion.Major >= 6) {
extension_main = "WKExtensionMain";
} else {
extension_main = "main";
}
}
if (!string.IsNullOrEmpty (extension_main)) {
sw.WriteLine ($"extern \"C\" {{ int {extension_main} (int argc, char* argv[]); }}");
sw.WriteLine ();
}
sw.WriteLine ();
sw.WriteLine ("void xamarin_initialize_callbacks () __attribute__ ((constructor));");
sw.WriteLine ("void xamarin_initialize_callbacks ()");
sw.WriteLine ("{");
sw.WriteLine ("\txamarin_setup = xamarin_setup_impl;");
sw.WriteLine ("\txamarin_register_assemblies = xamarin_register_assemblies_impl;");
sw.WriteLine ("\txamarin_register_modules = xamarin_register_modules_impl;");
if (!string.IsNullOrEmpty (extension_main))
sw.WriteLine ($"\txamarin_extension_main = {extension_main};");
sw.WriteLine ("}");
}
Driver.WriteIfDifferent (main_source, sb.ToString (), true);
} catch (ProductException) {
throw;
} catch (Exception e) {
throw new ProductException (4001, true, e, Errors.MT4001, main_source);
}
return main_source;
}
static string EncodeAotSymbol (string symbol)
{
var sb = new StringBuilder ();
/* This mimics what the aot-compiler does */
foreach (var b in System.Text.Encoding.UTF8.GetBytes (symbol)) {
char c = (char) b;
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z')) {
sb.Append (c);
continue;
}
sb.Append ('_');
}
return sb.ToString ();
}
static bool IsBoundAssembly (Assembly s)
{
if (s.IsFrameworkAssembly == true)
return false;
AssemblyDefinition ad = s.AssemblyDefinition;
foreach (ModuleDefinition md in ad.Modules)
foreach (TypeDefinition td in md.Types)
if (td.IsNSObject (s.Target.LinkContext))
return true;
return false;
}
}
}

Просмотреть файл

@ -57,14 +57,6 @@ namespace Xamarin.Bundler {
Driver.Log (1, $"Registrar mode: {Registrar}");
}
public AssemblyBuildTarget LibMonoLinkMode {
get { throw new NotImplementedException (); }
}
public AssemblyBuildTarget LibXamarinLinkMode {
get { throw new NotImplementedException (); }
}
public bool HasAnyDynamicLibraries {
get { throw new NotImplementedException (); }
}

Просмотреть файл

@ -182,6 +182,9 @@
<Compile Include="..\..\external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs">
<Link>external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs</Link>
</Compile>
<Compile Include="..\common\BitCodeMode.cs">
<Link>external\tools\common\BitCodeMode.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\mtouch\Errors.resx">

Просмотреть файл

@ -455,6 +455,12 @@
<Compile Include="..\mtouch\Stripper.cs">
<Link>external\tools\mtouch\Stripper.cs</Link>
</Compile>
<Compile Include="..\common\AssemblyBuildTarget.cs">
<Link>tools\common\AssemblyBuildTarget.cs</Link>
</Compile>
<Compile Include="..\common\BitCodeMode.cs">
<Link>tools\common\BitCodeMode.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

Просмотреть файл

@ -17,13 +17,6 @@ using Xamarin.Utils;
namespace Xamarin.Bundler {
public enum BitCodeMode {
None = 0,
ASMOnly = 1,
LLVMOnly = 2,
MarkerOnly = 3,
}
public enum DlsymOptions
{
Default,
@ -57,7 +50,6 @@ namespace Xamarin.Bundler {
public DlsymOptions DlsymOptions;
public List<Tuple<string, bool>> DlsymAssemblies;
public bool? UseMonoFramework;
public bool? PackageMonoFramework;
public bool NoFastSim;
@ -69,7 +61,6 @@ namespace Xamarin.Bundler {
public List<string> AotOtherArguments = null;
public bool? LLVMAsmWriter;
public Dictionary<string, string> LLVMOptimizations = new Dictionary<string, string> ();
public List<string> InterpretedAssemblies = new List<string> ();
//
// Linker config
@ -80,44 +71,6 @@ namespace Xamarin.Bundler {
public bool? BuildDSym;
public bool IsInterpreted (string assembly)
{
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both.
if (!UseInterpreter)
return false;
// Go through the list of assemblies to interpret in reverse order,
// so that the last option passed to mtouch takes precedence.
for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) {
var opt = InterpretedAssemblies [i];
if (opt == "all")
return true;
else if (opt == "-all")
return false;
else if (opt == assembly)
return true;
else if (opt [0] == '-' && opt.Substring (1) == assembly)
return false;
}
// There's an implicit 'all' at the start of the list.
return true;
}
public bool IsAOTCompiled (string assembly)
{
if (!UseInterpreter)
return true;
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both:
// - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work
// - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not)
if (assembly == "mscorlib")
return true;
return !IsInterpreted (assembly);
}
public List<string> UserGccFlags;
// If we didn't link the final executable because the existing binary is up-to-date.
@ -136,52 +89,8 @@ namespace Xamarin.Bundler {
BuildTasks build_tasks;
BuildTask final_build_task; // either lipo or file copy (to final destination)
Dictionary<string, Tuple<AssemblyBuildTarget, string>> assembly_build_targets = new Dictionary<string, Tuple<AssemblyBuildTarget, string>> ();
public AssemblyBuildTarget LibMonoLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks || UseMonoFramework.Value) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibXamarinLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibPInvokesLinkMode => LibXamarinLinkMode;
public AssemblyBuildTarget LibProfilerLinkMode => OnlyStaticLibraries ? AssemblyBuildTarget.StaticObject : AssemblyBuildTarget.DynamicLibrary;
public AssemblyBuildTarget LibMonoNativeLinkMode => HasDynamicLibraries ? AssemblyBuildTarget.DynamicLibrary : AssemblyBuildTarget.StaticObject;
Dictionary<string, BundleFileInfo> bundle_files = new Dictionary<string, BundleFileInfo> ();
public bool OnlyStaticLibraries {
get {
return assembly_build_targets.All ((abt) => abt.Value.Item1 == AssemblyBuildTarget.StaticObject);
}
}
public bool HasDynamicLibraries {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.DynamicLibrary);
}
}
public bool HasAnyDynamicLibraries {
get {
if (LibMonoLinkMode == AssemblyBuildTarget.DynamicLibrary)
@ -198,12 +107,6 @@ namespace Xamarin.Bundler {
}
}
public bool HasFrameworks {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.Framework);
}
}
public void ClearAssemblyBuildTargets ()
{
assembly_build_targets.Clear ();
@ -455,13 +358,6 @@ namespace Xamarin.Bundler {
}
}
public BitCodeMode BitCodeMode { get; set; }
public bool EnableAsmOnlyBitCode { get { return BitCodeMode == BitCodeMode.ASMOnly; } }
public bool EnableLLVMOnlyBitCode { get { return BitCodeMode == BitCodeMode.LLVMOnly; } }
public bool EnableMarkerOnlyBitCode { get { return BitCodeMode == BitCodeMode.MarkerOnly; } }
public bool EnableBitCode { get { return BitCodeMode != BitCodeMode.None; } }
public ICollection<Abi> AllArchitectures {
get {
if (all_architectures == null) {
@ -477,19 +373,6 @@ namespace Xamarin.Bundler {
}
}
public bool HasFrameworksDirectory {
get {
if (!IsExtension)
return true;
if (IsWatchExtension && Platform == ApplePlatform.WatchOS)
return true;
return false;
}
}
public string BundleId {
get {
return GetStringFromInfoPList ("CFBundleIdentifier");
@ -1125,12 +1008,6 @@ namespace Xamarin.Bundler {
return rv;
}
public string AssemblyName {
get {
return Path.GetFileName (RootAssemblies [0]);
}
}
public string Executable {
get {
if (Embeddinator)

Просмотреть файл

@ -23,9 +23,6 @@ namespace Xamarin.Bundler {
public partial class Assembly
{
public AssemblyBuildTarget BuildTarget;
public string BuildTargetName;
public bool IsCodeShared;
public bool BundleInContainerApp;
public Dictionary<Abi, AotInfo> AotInfos = new Dictionary<Abi, AotInfo> ();
@ -45,12 +42,6 @@ namespace Xamarin.Bundler {
}
}
public bool IsAOTCompiled {
get {
return App.IsAOTCompiled (Identity);
}
}
// Recursively list all the assemblies the specified assembly depends on.
HashSet<string> ComputeDependencies (List<Exception> warnings)
{

Просмотреть файл

@ -83,7 +83,7 @@ namespace Xamarin.Bundler
protected override void Execute ()
{
Driver.GenerateMain (Target, Target.Assemblies, Target.App.AssemblyName, Abi, MainM, RegistrationMethods);
Target.GenerateIOSMain (Abi, MainM, RegistrationMethods);
}
}

Просмотреть файл

@ -294,255 +294,6 @@ namespace Xamarin.Bundler
return args;
}
static string EncodeAotSymbol (string symbol)
{
var sb = new StringBuilder ();
/* This mimics what the aot-compiler does */
foreach (var b in System.Text.Encoding.UTF8.GetBytes (symbol)) {
char c = (char) b;
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z')) {
sb.Append (c);
continue;
}
sb.Append ('_');
}
return sb.ToString ();
}
// note: this is executed under Parallel.ForEach
public static string GenerateMain (Target target, IEnumerable<Assembly> assemblies, string assembly_name, Abi abi, string main_source, IList<string> registration_methods)
{
var app = target.App;
var assembly_externs = new StringBuilder ();
var assembly_aot_modules = new StringBuilder ();
var register_assemblies = new StringBuilder ();
var assembly_location = new StringBuilder ();
var assembly_location_count = 0;
var enable_llvm = (abi & Abi.LLVM) != 0;
register_assemblies.AppendLine ("\tguint32 exception_gchandle = 0;");
foreach (var s in assemblies) {
if (!s.IsAOTCompiled)
continue;
if ((abi & Abi.SimulatorArchMask) == 0) {
var info = s.AssemblyDefinition.Name.Name;
info = EncodeAotSymbol (info);
assembly_externs.Append ("extern void *mono_aot_module_").Append (info).AppendLine ("_info;");
assembly_aot_modules.Append ("\tmono_aot_register_module (mono_aot_module_").Append (info).AppendLine ("_info);");
}
string sname = s.FileName;
if (assembly_name != sname && IsBoundAssembly (s)) {
register_assemblies.Append ("\txamarin_open_and_register (\"").Append (sname).Append ("\", &exception_gchandle);").AppendLine ();
register_assemblies.AppendLine ("\txamarin_process_managed_exception_gchandle (exception_gchandle);");
}
}
if ((abi & Abi.SimulatorArchMask) == 0 || app.Embeddinator) {
var frameworks = assemblies.Where ((a) => a.BuildTarget == AssemblyBuildTarget.Framework)
.OrderBy ((a) => a.Identity, StringComparer.Ordinal);
foreach (var asm_fw in frameworks) {
var asm_name = asm_fw.Identity;
if (asm_fw.BuildTargetName == asm_name)
continue; // this is deduceable
var prefix = string.Empty;
if (!app.HasFrameworksDirectory && asm_fw.IsCodeShared)
prefix = "../../";
var suffix = string.Empty;
if (app.IsSimulatorBuild)
suffix = "/simulator";
assembly_location.AppendFormat ("\t{{ \"{0}\", \"{2}Frameworks/{1}.framework/MonoBundle{3}\" }},\n", asm_name, asm_fw.BuildTargetName, prefix, suffix);
assembly_location_count++;
}
}
try {
StringBuilder sb = new StringBuilder ();
using (var sw = new StringWriter (sb)) {
sw.WriteLine ("#include \"xamarin/xamarin.h\"");
if (assembly_location.Length > 0) {
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocation assembly_location_entries [] = {");
sw.WriteLine (assembly_location);
sw.WriteLine ("};");
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocations assembly_locations = {{ {0}, assembly_location_entries }};", assembly_location_count);
}
sw.WriteLine ();
sw.WriteLine (assembly_externs);
sw.WriteLine ("void xamarin_register_modules_impl ()");
sw.WriteLine ("{");
sw.WriteLine (assembly_aot_modules);
sw.WriteLine ("}");
sw.WriteLine ();
sw.WriteLine ("void xamarin_register_assemblies_impl ()");
sw.WriteLine ("{");
sw.WriteLine (register_assemblies);
sw.WriteLine ("}");
sw.WriteLine ();
if (registration_methods != null) {
foreach (var method in registration_methods) {
sw.Write ("extern \"C\" void ");
sw.Write (method);
sw.WriteLine ("();");
}
}
// Burn in a reference to the profiling symbol so that the native linker doesn't remove it
// On iOS we can pass -u to the native linker, but that doesn't work on tvOS, where
// we're building with bitcode (even when bitcode is disabled, we still build with the
// bitcode marker, which makes the linker reject -u).
if (app.EnableProfiling) {
sw.WriteLine ("extern \"C\" { void mono_profiler_init_log (); }");
sw.WriteLine ("typedef void (*xamarin_profiler_symbol_def)();");
sw.WriteLine ("extern xamarin_profiler_symbol_def xamarin_profiler_symbol;");
sw.WriteLine ("xamarin_profiler_symbol_def xamarin_profiler_symbol = NULL;");
}
if (app.UseInterpreter) {
sw.WriteLine ("extern \"C\" { void mono_ee_interp_init (const char *); }");
sw.WriteLine ("extern \"C\" { void mono_icall_table_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_marshal_ilgen_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_method_builder_ilgen_init (void); }");
sw.WriteLine ("extern \"C\" { void mono_sgen_mono_ilgen_init (void); }");
}
sw.WriteLine ("void xamarin_setup_impl ()");
sw.WriteLine ("{");
if (app.EnableProfiling)
sw.WriteLine ("\txamarin_profiler_symbol = mono_profiler_init_log;");
if (app.EnableLLVMOnlyBitCode)
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);");
else if (app.UseInterpreter) {
sw.WriteLine ("\tmono_icall_table_init ();");
sw.WriteLine ("\tmono_marshal_ilgen_init ();");
sw.WriteLine ("\tmono_method_builder_ilgen_init ();");
sw.WriteLine ("\tmono_sgen_mono_ilgen_init ();");
sw.WriteLine ("\tmono_ee_interp_init (NULL);");
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_INTERP);");
} else if (app.IsDeviceBuild)
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
if (assembly_location.Length > 0)
sw.WriteLine ("\txamarin_set_assembly_directories (&assembly_locations);");
if (registration_methods != null) {
for (int i = 0; i < registration_methods.Count; i++) {
sw.Write ("\t");
sw.Write (registration_methods [i]);
sw.WriteLine ("();");
}
}
if (app.MonoNativeMode != MonoNativeMode.None) {
string mono_native_lib;
if (app.LibMonoNativeLinkMode == AssemblyBuildTarget.StaticObject)
mono_native_lib = "__Internal";
else
mono_native_lib = app.GetLibNativeName () + ".dylib";
sw.WriteLine ();
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Native\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Security.Cryptography.Native.Apple\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ($"\tmono_dllmap_insert (NULL, \"System.Net.Security.Native\", NULL, \"{mono_native_lib}\", NULL);");
sw.WriteLine ();
}
if (app.EnableDebug)
sw.WriteLine ("\txamarin_gc_pump = {0};", app.DebugTrack.Value ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_init_mono_debug = {0};", app.PackageManagedDebugSymbols ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_executable_name = \"{0}\";", assembly_name);
sw.WriteLine ("\tmono_use_llvm = {0};", enable_llvm ? "TRUE" : "FALSE");
sw.WriteLine ("\txamarin_log_level = {0};", Verbosity.ToString (CultureInfo.InvariantCulture));
sw.WriteLine ("\txamarin_arch_name = \"{0}\";", abi.AsArchString ());
if (!app.IsDefaultMarshalManagedExceptionMode)
sw.WriteLine ("\txamarin_marshal_managed_exception_mode = MarshalManagedExceptionMode{0};", app.MarshalManagedExceptions);
sw.WriteLine ("\txamarin_marshal_objectivec_exception_mode = MarshalObjectiveCExceptionMode{0};", app.MarshalObjectiveCExceptions);
if (app.EnableDebug)
sw.WriteLine ("\txamarin_debug_mode = TRUE;");
if (!string.IsNullOrEmpty (app.MonoGCParams))
sw.WriteLine ("\tsetenv (\"MONO_GC_PARAMS\", \"{0}\", 1);", app.MonoGCParams);
foreach (var kvp in app.EnvironmentVariables)
sw.WriteLine ("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace ("\"", "\\\""), kvp.Value.Replace ("\"", "\\\""));
sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE");
sw.WriteLine ("}");
sw.WriteLine ();
sw.Write ("int ");
sw.Write (app.IsWatchExtension ? "xamarin_watchextension_main" : "main");
sw.WriteLine (" (int argc, char **argv)");
sw.WriteLine ("{");
sw.WriteLine ("\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];");
if (app.IsExtension) {
// the name of the executable must be the bundle id (reverse dns notation)
// but we do not want to impose that (ugly) restriction to the managed .exe / project name / ...
sw.WriteLine ("\targv [0] = (char *) \"{0}\";", Path.GetFileNameWithoutExtension (app.RootAssemblies [0]));
sw.WriteLine ("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeExtension);");
} else {
sw.WriteLine ("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeApp);");
}
sw.WriteLine ("\t[pool drain];");
sw.WriteLine ("\treturn rv;");
sw.WriteLine ("}");
string extension_main = null;
if (app.Platform == ApplePlatform.WatchOS && app.IsWatchExtension) {
// We're building a watch extension, and we have multiple scenarios, depending on the watchOS version we're executing on:
//
// * watchOS 2.0 -> 5.*: we must call a `main` function provided in the WatchKit framework.
// * watchOS 6.0 -> * : we must call a `WKExtensionMain` function provided in the WatchKit framework.
// * watchOS 7.0 -> * : The `WKExtensionMain` function uses dlsym to find any `main` functions in the
// main executable, and calls that function (otherwise WKExtensionMain will call
// UIApplicationMain and normal startup occurs)
//
// * We can't call our entry point "main", because we call WKExtensionMain, and then we run into an
// infinite loop on watchOS 7.0. So we call it xamarin_watch_extension_main.
// * The watchOS 6+ SDK helpfully provides a static library (WKExtensionMainLegacy) that has a
// WKExtensionMain function, which we use when the deployment target is earlier than watchOS 6.0.
// This means that calling WKExtensionMain works everywhere (as long as we're using the
// watchOS 6+ SDK to build; otherwise we just call "main" directly and don't link with the
// WKExtensionMainLegacy library)
if (app.SdkVersion.Major >= 6) {
extension_main = "WKExtensionMain";
} else {
extension_main = "main";
}
}
if (!string.IsNullOrEmpty (extension_main)) {
sw.WriteLine ($"extern \"C\" {{ int {extension_main} (int argc, char* argv[]); }}");
sw.WriteLine ();
}
sw.WriteLine ();
sw.WriteLine ("void xamarin_initialize_callbacks () __attribute__ ((constructor));");
sw.WriteLine ("void xamarin_initialize_callbacks ()");
sw.WriteLine ("{");
sw.WriteLine ("\txamarin_setup = xamarin_setup_impl;");
sw.WriteLine ("\txamarin_register_assemblies = xamarin_register_assemblies_impl;");
sw.WriteLine ("\txamarin_register_modules = xamarin_register_modules_impl;");
if (!string.IsNullOrEmpty (extension_main))
sw.WriteLine ($"\txamarin_extension_main = {extension_main};");
sw.WriteLine ("}");
}
WriteIfDifferent (main_source, sb.ToString (), true);
} catch (ProductException) {
throw;
} catch (Exception e) {
throw new ProductException (4001, true, e, Errors.MT4001, main_source);
}
return main_source;
}
public static void CopyAssembly (string source, string target, string target_dir = null)
{
if (File.Exists (target))
@ -1175,20 +926,5 @@ namespace Xamarin.Bundler
}
}
}
static bool IsBoundAssembly (Assembly s)
{
if (s.IsFrameworkAssembly == true)
return false;
AssemblyDefinition ad = s.AssemblyDefinition;
foreach (ModuleDefinition md in ad.Modules)
foreach (TypeDefinition td in md.Types)
if (td.IsNSObject (s.Target.LinkContext))
return true;
return false;
}
}
}

Просмотреть файл

@ -472,6 +472,9 @@
<Compile Include="..\common\Driver.execution.cs">
<Link>tools\common\Driver.execution.cs</Link>
</Compile>
<Compile Include="..\common\BitCodeMode.cs">
<Link>tools\common\BitCodeMode.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Core" />