xamarin-macios/tools/common/Target.cs

870 строки
31 KiB
C#
Исходник Обычный вид История

2016-04-21 15:57:02 +03:00
// Copyright 2013--2014 Xamarin Inc. All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Mono.Cecil;
using Mono.Tuner;
using Mono.Linker;
using Xamarin.Linker;
using Xamarin.Utils;
using Registrar;
using ObjCRuntime;
2016-04-21 15:57:02 +03:00
#if MONOTOUCH
using MonoTouch;
using MonoTouch.Tuner;
using PlatformResolver = MonoTouch.Tuner.MonoTouchResolver;
using PlatformLinkContext = MonoTouch.Tuner.MonoTouchLinkContext;
#elif MMP
2016-04-21 15:57:02 +03:00
using MonoMac.Tuner;
using PlatformResolver = Xamarin.Bundler.MonoMacResolver;
using PlatformLinkContext = MonoMac.Tuner.MonoMacLinkContext;
#elif NET
using LinkerOptions = Xamarin.Linker.LinkerConfiguration;
using PlatformLinkContext = Xamarin.Tuner.DerivedLinkContext;
using PlatformResolver = Xamarin.Linker.DotNetResolver;
#else
#error Invalid defines
2016-04-21 15:57:02 +03:00
#endif
namespace Xamarin.Bundler {
public partial class Target {
public Application App;
public AssemblyCollection Assemblies = new AssemblyCollection (); // The root assembly is not in this list.
2016-04-21 15:57:02 +03:00
public PlatformLinkContext LinkContext;
public LinkerOptions LinkerOptions;
2016-04-21 15:57:02 +03:00
public PlatformResolver Resolver = new PlatformResolver ();
public HashSet<string> Frameworks = new HashSet<string> ();
public HashSet<string> WeakFrameworks = new HashSet<string> ();
internal StaticRegistrar StaticRegistrar { get; set; }
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
// If we didn't link because the existing (cached) assemblyes are up-to-date.
bool cached_link = false;
Symbols dynamic_symbols;
// Note that each 'Target' can have multiple abis: armv7+armv7s for instance.
public List<Abi> Abis;
// If we're targetting a 32 bit arch for this target.
bool? is32bits;
public bool Is32Build {
get {
if (!is32bits.HasValue)
is32bits = Application.IsArchEnabled (Abis, Abi.Arch32Mask);
return is32bits.Value;
}
}
// If we're targetting a 64 bit arch for this target.
bool? is64bits;
public bool Is64Build {
get {
if (!is64bits.HasValue)
is64bits = Application.IsArchEnabled (Abis, Abi.Arch64Mask);
return is64bits.Value;
}
}
2016-04-21 15:57:02 +03:00
public Target (Application app)
{
this.App = app;
this.StaticRegistrar = new StaticRegistrar (this);
2016-04-21 15:57:02 +03:00
}
// If this is an app extension, this returns the equivalent (32/64bit) target for the container app.
// This may be null (it's possible to build an extension for 32+64bit, and the main app only for 64-bit, for instance.
public Target ContainerTarget {
get {
return App.ContainerApp.Targets.FirstOrDefault ((v) => v.Is32Build == Is32Build);
}
}
public Assembly AddAssembly (AssemblyDefinition assembly)
{
var asm = new Assembly (this, assembly);
Assemblies.Add (asm);
return asm;
}
// This will find the link context, possibly looking in container targets.
public PlatformLinkContext GetLinkContext ()
{
if (LinkContext != null)
return LinkContext;
if (App.IsExtension && App.IsCodeShared)
return ContainerTarget.GetLinkContext ();
return null;
}
[mtouch/mmp] Fix tracking of whether the static registrar should run again or not. Fixes #641. (#3534) (#3536) * [tests] Improve debug spew for the RebuildTest_WithExtensions test. * [mtouch/mmp] Store/load if the dynamic registrar is removed or not into the cached link results. Store/load if the dynamic registrar is removed or not into the cached link results, so that we generate the correct main.m even if cached linker results are used. * [mtouch/mmp] The static registrar must not execute if we're loading cached results from the linker. The static registrar must not execute if we're loading cached results from the linker, because the static registrar needs information from the linker that's not restored from the cache. * [mtouch/mmp] Share Touch code. * [mtouch/mmp] Make it possible to touch inexistent files (to create them). * [mtouch/mmp] Fix tracking of whether the static registrar should run again or not. The recent changes to support optimizing away the dynamic registrar caused the Xamarin.MTouch.RebuildTest_WithExtensions test to regress. The problem ----------- * The linker now collects and stores information the static registrar needs. * This information is not restored from disk when the linker realizes that it can reload previously linked assemblies instead of executing again. * The static registrar runs again (for another reason). * The information the static registrar needs isn't available, and incorrect output follows. So fix 1: show an error if the static registrar runs when the linker loaded cached results. The exact scenario the test ran into is this: * 1st build: everything is new and everything is built. * 2nd build: contents of .exe changes, the linker runs again, the static registrar runs again, but sees that the generated output didn't change, so it doesn't write the new content to disk (this is an optimization to avoid compiling the registrar.m file again unless needed). * 3rd build: only the .exe timestamp changes, the linker sees nothing changes in the contents of the .exe and loads the previously linked assemblies from disk, the static registrar sees that the .exe's timestamp is newer than registrar.m's timestamp and run again, but doesn't produce the right result because it doesn't have the information it needs. Considered solutions -------------------- 1. Only track timestamps, not file contents. This is not ideal, since it will result in more work done: in particular for the case above, it would add a registrar.m compilation in build #2, and linker rerun + static registrar rerun + registrar.m compilation + final native link in build #3. 2. Always write the output of the static registrar, even if it hasn't changed. This is not ideal either, since it will also result in more work done: for the case above, it would add a registrar.m compilation + final native link in build #3. 3. Always write the output of the static registrar, but track if it changed or not, and if it didn't, just touch registrar.o instead of recompiling it. This only means the final native link in build #3 is added (see #5 for why this is worse than it sounds). 4. Always write the output of the static registrar, but track it it changed or not, and if it didn't, just touch registrar.o instead of recompiling it, and track that too, so that the final native link in build #3 isn't needed anymore. Unfortunately this may result in incorrect behavior, because now the msbuild tasks will detect that the executable has changed, and may run dsymutil + strip again. The executable didn't actually change, which means it would be the previously stripped executable, and thus we'd end up with an empty .dSYM because we ran dsymtil on an already stripped executable. 5. Idea #4, but write the output of the final link into a temporary directory instead of the .app, so that we could track whether we should update the executable in the .app or not. This is not optimal either, because executables can be *big* (I've seen multi-GB tvOS bitcode executables), and extra copies of such files should not be taken lightly. 6. Idea #4, but tell the MSBuild tasks that dsymutil/strip doesn't need to be rerun even if the timestamp of the executable changed. This might actually work, but now the solution's become quite complex. Implemented solution -------------------- Use stamp files to detect whether a file is up-to-date or not. In particular: * When we don't write to a file because the new contents are identical to the old contents, we now touch a .stamp file. This stamp file means "the accompanying file was determined to be up-to-date when the stamp was touched." * When checking whether a file is up-to-date, also check for the presence of a .stamp file, and if it exists, use the highest timestamp between the stamp file and the actual file. Now the test scenario becomes: * 1st build: everything is new and everything is built. * 2nd build: contents of .exe changes, the linker runs again, the static registrar runs again, but sees that the generated output didn't change, so it doesn't write the new content to disk, but it creates a registrar.m.stamp file to indicate the point in time when registrar.m was considered up-to- date. * 3rd build: only the .exe timestamp changes, the linker sees nothing changes in the contents of the .exe and loads the previously linked assemblies from disk, the static registrar sees that the .exe's timestamp is *older* than registrar.m.stamp's timestamp and doesn't run again. We only use the stamp file for source code (registrar.[m|h], main.[m|h], pinvokes.[m|h]), since using it every time has too much potential for running into other problems (for instance we should never create .stamp files inside the .app). Fixes these test failures: 1) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("single","",False,System.String[]) single Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory371/testApp.app/testApp is modified, timestamp: 2/15/2018 3:04:11 PM > 2/15/2018 3:04:09 PM" > 2) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("dual","armv7,arm64",False,System.String[]) dual Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory375/testApp.app/testApp is modified, timestamp: 2/15/2018 3:06:03 PM > 2/15/2018 3:06:00 PM" > 3) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("llvm","armv7+llvm",False,System.String[]) llvm Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory379/testApp.app/testApp is modified, timestamp: 2/15/2018 3:07:14 PM > 2/15/2018 3:07:12 PM" > 4) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("debug","",True,System.String[]) debug Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory383/testApp.app/testApp is modified, timestamp: 2/15/2018 3:08:16 PM > 2/15/2018 3:08:13 PM" > 5) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("single-framework","",False,System.String[]) single-framework Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory387/testApp.app/testApp is modified, timestamp: 2/15/2018 3:09:18 PM > 2/15/2018 3:09:16 PM" > Fixes https://github.com/xamarin/maccore/issues/641
2018-02-20 13:43:23 +03:00
public bool CachedLink {
get {
return cached_link;
}
}
2016-04-21 15:57:02 +03:00
public void ExtractNativeLinkInfo (List<Exception> exceptions)
{
foreach (var a in Assemblies) {
try {
a.ExtractNativeLinkInfo ();
} catch (Exception e) {
exceptions.Add (e);
}
}
#if MTOUCH
if (!App.OnlyStaticLibraries && Assemblies.Count ((v) => v.HasLinkWithAttributes) > 1) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (127, Errors.MT0127);
App.ClearAssemblyBuildTargets (); // the default is to compile to static libraries, so just revert to the default.
}
#endif
2016-04-21 15:57:02 +03:00
}
[DllImport (Constants.libSystemLibrary, SetLastError = true)]
static extern string realpath (string path, IntPtr zero);
public static string GetRealPath (string path)
{
[xcode11.4] Add xcode 11.4 b1 initial support (#7805) * [xcode11.4] Add xcode 11.4 b1 initial support * [xtro] re-enable PDFKit * Disable watchOS and fix xtro Unfortunately watchOS simulator hangs when we try to deploy to it and it keeps our tests timing out. Disabling for now until we can investigate more. Disables PDFKit on xtro in macOS * [jenkins] Switch to use the catalina bot group (#7819) * Bump maccore to get fix for launching the simulator for watch apps. New commits in xamarin/maccore: * xamarin/maccore@546270c8f9 [Xamarin.Hosting] Fix the name of the notification we get when the simulator has launched. (#2145) Diff: https://github.com/xamarin/maccore/compare/55957e908d7ef6de87d78100fa782023371af280..546270c8f9d72cfa73a9b6a49c4cce1f4fe868a3 * [tests] Diable watch due to time out, enable 10,15,4 in intro, fix min version * Bump macios-binaries to get updated binary mlaunch as well. New commits in xamarin/macios-binaries: * xamarin/macios-binaries@f8c6e63 Bump mlaunch to xamarin/maccore@546270c8f9 Diff: https://github.com/xamarin/macios-binaries/compare/eb6980e8b6ee7bcd6edfd514e606b664bd93f33d..f8c6e6322822e817643613ff0c62f6da45739f7a * [msbuild] Reflect ibtool changes in our tests Looks like Apple reverted some changes introduces in Xcode 11 in ibtool, for more context see xamarin/xamarin-macios#6970 * [mtouch] Workaround strange behavior of realpath. Co-authored-by: Sebastien Pouliot <sebastien.pouliot@gmail.com> Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
2020-02-12 04:25:43 +03:00
// For some reason realpath doesn't always like filenames only, and will randomly fail.
// Prepend the current directory if there's no directory specified.
if (string.IsNullOrEmpty (Path.GetDirectoryName (path)))
path = Path.Combine (Environment.CurrentDirectory, path);
2016-04-21 15:57:02 +03:00
var rv = realpath (path, IntPtr.Zero);
if (rv != null)
return rv;
var errno = Marshal.GetLastWin32Error ();
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (54, Errors.MT0054, path, FileCopier.strerror (errno), errno);
2016-04-21 15:57:02 +03:00
return path;
}
public void ValidateAssembliesBeforeLink ()
{
if (App.LinkMode != LinkMode.None) {
foreach (Assembly assembly in Assemblies) {
if ((assembly.AssemblyDefinition.MainModule.Attributes & ModuleAttributes.ILOnly) == 0)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (2014, Errors.MT2014, assembly.AssemblyDefinition.MainModule.FileName);
}
}
}
public void ComputeLinkerFlags ()
{
foreach (var a in Assemblies)
a.ComputeLinkerFlags ();
}
public void GatherFrameworks ()
{
Assembly asm = null;
foreach (var assembly in Assemblies) {
if (assembly.AssemblyDefinition.Name.Name == Driver.GetProductAssembly (App)) {
asm = assembly;
break;
}
}
[mtouch] Show MT0123 if the executable assembly does not reference the product assembly. Fixes #59798. (#2801) It does not make sense to create Xamarin.iOS projects that don't reference Xamarin.iOS.dll, so make this an explicit error. This fixes a NullReferenceException which could (when building for device, or when not using simlauncher) occur, and instead shows the MT0123 error. > MTOUCH : error MT0000: Unexpected error - Please file a bug report at http://bugzilla.xamarin.com > System.NullReferenceException: Object reference not set to an instance of an object > at Xamarin.Bundler.Target.GatherFrameworks () [0x00065] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/common/Target.cs:122 > at Xamarin.Bundler.Target.ProcessAssemblies () [0x000c2] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Target.cs:802 > at Xamarin.Bundler.Application.ProcessAssemblies () [0x0002f] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:1407 > at Xamarin.Bundler.Application.BuildManaged () [0x00001] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:831 > at Xamarin.Bundler.Application+<>c.<BuildAll>b__134_1 (Xamarin.Bundler.Application v) [0x00000] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:779 > at System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) [0x00024] in <48b95f3df5804531818f80e28ec60191>:0 > at Xamarin.Bundler.Application.BuildAll () [0x00050] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:779 > at Xamarin.Bundler.Driver.Main2 (System.String[] args) [0x00481] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/mtouch.cs:1420 > at Xamarin.Bundler.Driver.Main (System.String[] args) [0x0000f] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/mtouch.cs:945 https://bugzilla.xamarin.com/show_bug.cgi?id=59798
2017-09-28 18:31:55 +03:00
if (asm == null)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"could not find the product assembly {Driver.GetProductAssembly(App)} in the list of assemblies referenced by the executable");
[mtouch] Show MT0123 if the executable assembly does not reference the product assembly. Fixes #59798. (#2801) It does not make sense to create Xamarin.iOS projects that don't reference Xamarin.iOS.dll, so make this an explicit error. This fixes a NullReferenceException which could (when building for device, or when not using simlauncher) occur, and instead shows the MT0123 error. > MTOUCH : error MT0000: Unexpected error - Please file a bug report at http://bugzilla.xamarin.com > System.NullReferenceException: Object reference not set to an instance of an object > at Xamarin.Bundler.Target.GatherFrameworks () [0x00065] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/common/Target.cs:122 > at Xamarin.Bundler.Target.ProcessAssemblies () [0x000c2] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Target.cs:802 > at Xamarin.Bundler.Application.ProcessAssemblies () [0x0002f] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:1407 > at Xamarin.Bundler.Application.BuildManaged () [0x00001] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:831 > at Xamarin.Bundler.Application+<>c.<BuildAll>b__134_1 (Xamarin.Bundler.Application v) [0x00000] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:779 > at System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) [0x00024] in <48b95f3df5804531818f80e28ec60191>:0 > at Xamarin.Bundler.Application.BuildAll () [0x00050] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/Application.cs:779 > at Xamarin.Bundler.Driver.Main2 (System.String[] args) [0x00481] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/mtouch.cs:1420 > at Xamarin.Bundler.Driver.Main (System.String[] args) [0x0000f] in /Users/builder/data/lanes/5024/152b654a/source/xamarin-macios/tools/mtouch/mtouch.cs:945 https://bugzilla.xamarin.com/show_bug.cgi?id=59798
2017-09-28 18:31:55 +03:00
AssemblyDefinition productAssembly = asm.AssemblyDefinition;
// *** make sure any change in the above lists (or new list) are also reflected in
// *** Makefile so simlauncher-sgen does not miss any framework
HashSet<string> processed = new HashSet<string> ();
#if !MONOMAC
Version v80 = new Version (8, 0);
#endif
foreach (ModuleDefinition md in productAssembly.Modules) {
foreach (TypeDefinition td in md.Types) {
// process only once each namespace (as we keep adding logic below)
string nspace = td.Namespace;
if (processed.Contains (nspace))
continue;
processed.Add (nspace);
Framework framework;
if (Driver.GetFrameworks (App).TryGetValue (nspace, out framework)) {
// framework specific processing
switch (framework.Name) {
#if MONOMAC
case "QTKit":
// we already warn in Frameworks.cs Gather method
if (!Driver.LinkProhibitedFrameworks)
continue;
break;
#else
case "CoreAudioKit":
// CoreAudioKit seems to be functional in the iOS 9 simulator.
if (App.IsSimulatorBuild && App.SdkVersion.Major < 9)
continue;
break;
case "Metal":
case "MetalKit":
case "MetalPerformanceShaders":
// some frameworks do not exists on simulators and will result in linker errors if we include them
if (App.IsSimulatorBuild)
continue;
break;
case "DeviceCheck":
if (App.IsSimulatorBuild && App.SdkVersion.Major < 13)
continue;
break;
case "PushKit":
// in Xcode 6 beta 7 this became an (ld) error - it was a warning earlier :(
// ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/PushKit.framework/PushKit) for architecture armv7
// this was fixed in Xcode 6.2 (6.1 was still buggy) see #29786
if ((App.DeploymentTarget < v80) && (Driver.XcodeVersion < new Version (6, 2))) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (49, Errors.MT0049, framework.Name);
continue;
}
break;
case "WatchKit":
// Xcode 11 doesn't ship WatchKit for iOS
if (Driver.XcodeVersion.Major == 11 && App.Platform == ApplePlatform.iOS) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (5219, Errors.MT5219);
continue;
}
break;
default:
if (App.IsSimulatorBuild && !App.IsFrameworkAvailableInSimulator (framework.Name)) {
if (App.LinkMode != LinkMode.None) {
ErrorHelper.Warning (5223, Errors.MX5223, framework.Name, App.PlatformName);
} else {
Driver.Log (3, Errors.MX5223, framework.Name, App.PlatformName);
}
continue;
}
break;
#endif
}
if (framework.Unavailable) {
ErrorHelper.Warning (181, Errors.MX0181 /* Not linking with the framework {0} (used by the type {1}) because it's not available on the current platform ({2}). */, framework.Name, td.FullName, App.PlatformName);
continue;
}
if (App.SdkVersion >= framework.Version) {
var add_to = framework.AlwaysWeakLinked || App.DeploymentTarget < framework.Version ? asm.WeakFrameworks : asm.Frameworks;
add_to.Add (framework.Name);
continue;
} else {
Driver.Log (3, "Not linking with the framework {0} (used by the type {1}) because it was introduced in {2} {3}, and we're using the {2} {4} SDK.", framework.Name, td.FullName, App.PlatformName, framework.Version, App.SdkVersion);
}
}
}
}
// Make sure there are no duplicates between frameworks and weak frameworks.
// Keep the weak ones.
asm.Frameworks.ExceptWith (asm.WeakFrameworks);
}
[mtouch/mmp] Print assembly references in verbose mode. (#2139) * [mtouch/mmp] Print assembly references in verbose mode. Sample output: Loaded assembly 'unifiedtestapp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' from /Users/rolf/Projects/TestApp/bin/iPhoneSimulator/Debug/unifiedtestapp.exe References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 Loaded assembly 'mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/mscorlib.dll Loaded assembly 'Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/../../64bits/Xamarin.iOS.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756 References: System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756 References: System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/Mono.Security.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.Xml.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.Core.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e I believe this will make it easier to diagnose cases where something references a desktop assembly. * [mtouch/mmp] Share more code between mmp and mtouch.
2017-05-29 17:15:22 +03:00
internal static void PrintAssemblyReferences (AssemblyDefinition assembly)
{
if (Driver.Verbosity < 2)
return;
var main = assembly.MainModule;
Driver.Log ($"Loaded assembly '{assembly.FullName}' from {StringUtils.Quote (assembly.MainModule.FileName)}");
[mtouch/mmp] Print assembly references in verbose mode. (#2139) * [mtouch/mmp] Print assembly references in verbose mode. Sample output: Loaded assembly 'unifiedtestapp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' from /Users/rolf/Projects/TestApp/bin/iPhoneSimulator/Debug/unifiedtestapp.exe References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 Loaded assembly 'mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/mscorlib.dll Loaded assembly 'Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/../../64bits/Xamarin.iOS.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756 References: System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756 References: System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/Mono.Security.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.Xml.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e Loaded assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' from /work/maccore/master/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/lib/mono/Xamarin.iOS/System.Core.dll References: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e References: System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e I believe this will make it easier to diagnose cases where something references a desktop assembly. * [mtouch/mmp] Share more code between mmp and mtouch.
2017-05-29 17:15:22 +03:00
foreach (var ar in main.AssemblyReferences)
Driver.Log ($" References: '{ar.FullName}'");
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
public Symbols GetAllSymbols ()
{
CollectAllSymbols ();
return dynamic_symbols;
}
public void CollectAllSymbols ()
{
if (dynamic_symbols != null)
return;
var cache_location = Path.Combine (App.Cache.Location, "entry-points.txt");
if (cached_link) {
dynamic_symbols = new Symbols ();
dynamic_symbols.Load (cache_location, this);
} else {
if (LinkContext == null) {
// This happens when using the simlauncher and the msbuild tasks asked for a list
// of symbols (--symbollist). In that case just produce an empty list, since the
// binary shouldn't end up stripped anyway.
dynamic_symbols = new Symbols ();
} else {
dynamic_symbols = LinkContext.RequiredSymbols;
}
// keep the debugging helper in debugging binaries only
var has_mono_pmip = App.EnableDebug;
#if MMP
has_mono_pmip &= !Driver.IsUnifiedFullSystemFramework;
#endif
if (has_mono_pmip)
dynamic_symbols.AddFunction ("mono_pmip");
bool has_dyn_msgSend;
if (App.Platform == ApplePlatform.MacOSX) {
has_dyn_msgSend = App.MarshalObjectiveCExceptions != MarshalObjectiveCExceptionMode.Disable && !App.RequiresPInvokeWrappers && Is64Build;
} else {
has_dyn_msgSend = App.IsSimulatorBuild;
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
if (has_dyn_msgSend) {
dynamic_symbols.AddFunction ("xamarin_dyn_objc_msgSend");
dynamic_symbols.AddFunction ("xamarin_dyn_objc_msgSendSuper");
dynamic_symbols.AddFunction ("xamarin_dyn_objc_msgSend_stret");
dynamic_symbols.AddFunction ("xamarin_dyn_objc_msgSendSuper_stret");
}
#if MONOTOUCH
if (App.EnableProfiling && App.LibProfilerLinkMode == AssemblyBuildTarget.StaticObject)
[runtime] integrate mono 2017-10 (#2905) * Update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now. * [builds] Pass --with-cross-offsets= to crosstv's configure. * Bump mono to 2017-08. * Bump mono to 2017-08. * Force disable 'futimens' and 'utimensat' so that we build with Xcode 9. This is also needed to build with Xcode 8.3 on High Sierra. * Remove old AppleTls implementation. * Bump mono. * Bump mono to 2017-08. * Bump mono to 2017-08 * Reenable link-keep-resources-2 test - This reverts commit 76b759ef22c06cda3ba30aba1ac0d45634e4fbf4. - 2017-08 has linker fix * Bump mono to 2017-10 * Revert "Bump mono to 2017-10" This reverts commit bb7832724e18f8578449e46426382a537f3f4823. * Bump system mono to 2017-10 * Bump embedded mono to 2017-10 * [runtime] reflect eglib move https://github.com/mono/mono/commit/9be68f8952ea0e1aad582bfe2f47bad71aee2cc7 * bump mono * [btouch] remove Security.Tls usage from test * [mtouch tests] update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now. see https://github.com/mono/mono/commit/ea4e4a9ef6fc42570a23026adbe826cf7248290e fixes: ``` 1) Failed : Xamarin.MTouch.Profiling(tvOS) _mono_profiler_startup_log Expected: collection containing "_mono_profiler_startup_log" But was: < "_mono_profiler_init_log" > at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0 2) Failed : Xamarin.MTouch.Profiling(watchOS) _mono_profiler_startup_log Expected: collection containing "_mono_profiler_startup_log" But was: < "_xamarin_get_block_descriptor", "_mono_profiler_init_log" > at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0 ``` * [mmptest] update log profiler options. https://github.com/mono/mono/commit/826558a4af624bc0acaea98ec39784e65d278091 deprecated the dash prefix for the mlpd path. `noallocs` or `nocalls` are not needed, neither of them are default anymore. * [mmptest] fix link-keep-resources-2 test to cope with more corlib resources. another corlib resource (mscorlib.xml) was added: https://github.com/mono/mono/commit/11e95169e787#diff-2d1c64decd91d9a6e8842ab0f0e9438d * Revert "[mmptest] fix link-keep-resources-2 test to cope with more corlib resources." This reverts commit 350eb3c174288bbffcc3b7acb15cadb913af25b7. * [XHarness] Add the Mono.Data.Tds tests. * Address comments from rolf in the review. * [mmp regresssion tests] bump mono linker, so mscorlib.xml gets stripped the test was failing in that way: > Executing link-keep-resources-2... > [FAIL] i18n 4/2 data files present: charinfo.nlp, collation.core.bin, collation.tailoring.bin, mscorlib.xml also update the output, because it's actually expected at least three elements. fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=59277 * bump mono fixes crash in tvOS: https://github.com/mono/mono/pull/5812 * bump mono for updated BCL tests see https://github.com/mono/mono/pull/5820 * [mono] set 2017-10 branch in .gitmodules * [macos] Fix guiunit error on clean builds by depending on correct copy (#2912) * [macos] Fix guiunit error on clean builds by depending on correct copy - From a clean build making a BCL test would error due to the non-mobile guiunit not being built - This was because the Makefile-mac.inc target was incorrect - This was because xharness assumed that non variation based targets were always Modern - However, BCL tests are Full, not Modern * Code review change * Swap to var to reduce diff * Revert changes in the paths for GuiUnit. * [XHarness] Add the System.IO.Compression bcl tests. (#2918) * [XHarness] Add the System.IO.Compression bcl tests. * [XHarness] Add bcl tests for System.IO.Compression.FileSystem. (#2924) * [XHarness] Add the System.IO.Compression bcl tests. * Ensure that resources are correctly copied in the bundles. * [XHarness] Add bcl tests for System.IO.Compression.FileSystem. * As per review, make the Mac test app name match the tests that are ran. * [XHarness] Add Mono.CSharp tests on ios. (#2927) * [XHarness] Add Mono.CSharp tests on ios. * Bump mono to bring changes in the mono.csharp tests. * [xtro-sharpie] fix TypeDefinition access due to Cecil change * Bump mono * bump mono fixes - https://bugzilla.xamarin.com/show_bug.cgi?id=60480 - https://bugzilla.xamarin.com/show_bug.cgi?id=60482 * bump mono more fixes around conflicting paths when tests are run in parallel. * Bump for mono/mono@2017-10
2017-11-14 23:30:08 +03:00
dynamic_symbols.AddFunction ("mono_profiler_init_log");
#endif
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
dynamic_symbols.Save (cache_location);
}
foreach (var name in App.IgnoredSymbols) {
var symbol = dynamic_symbols.Find (name);
if (symbol == null) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (5218, Errors.MT5218, StringUtils.Quote (name));
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
} else {
symbol.Ignore = true;
}
}
}
bool IsRequiredSymbol (Symbol symbol, Assembly single_assembly = null)
{
if (symbol.Ignore)
return false;
// Check if this symbol is used in the assembly we're filtering to
if (single_assembly != null && !symbol.Members.Any ((v) => v.Module.Assembly == single_assembly.AssemblyDefinition))
return false; // nope, this symbol is not used in the assembly we're using as filter.
// If we're code-sharing, the managed linker might have found symbols
// that are not in any of the assemblies in the current app.
// This occurs because the managed linker processes all the
// assemblies for all the apps together, but when linking natively
// we're only linking with the assemblies that actually go into the app.
if (App.Platform != ApplePlatform.MacOSX && App.IsCodeShared && symbol.Assemblies.Count > 0) {
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
// So if this is a symbol related to any assembly, make sure
// at least one of those assemblies are in the current app.
if (!symbol.Assemblies.Any ((v) => Assemblies.Contains (v)))
return false;
}
switch (symbol.Type) {
case SymbolType.Field:
return true;
case SymbolType.Function:
#if MTOUCH
// functions are not required if they're used in an assembly which isn't using dlsym, and we're AOT-compiling.
if (App.IsSimulatorBuild)
return true;
if (App.Platform == ApplePlatform.MacCatalyst)
return true;
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
if (single_assembly != null)
return App.UseDlsym (single_assembly.FileName);
if (symbol.Members?.Any () == true) {
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
foreach (var member in symbol.Members) {
if (App.UseDlsym (member.Module.FileName)) {
// If any assembly uses dlsym to reference this symbol, it's a required symbol that must be preserved,
// because otherwise stripping the binary will cause the symbol (but not the function itself) to be removed,
// preventing any assembly using dlsym to find it.
return true;
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
// None of the members use dlsym (and we have at least one member), then we don't need to preserve the symbol.
return false;
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
#endif
return true;
case SymbolType.ObjectiveCClass:
// Objective-C classes are not required when we're using the static registrar and we're not compiling to shared libraries,
// (because the registrar code is linked into the main app, but not each shared library,
// so the registrar code won't keep symbols in the shared libraries).
if (single_assembly != null)
return true;
return App.Registrar != RegistrarMode.Static;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
}
public Symbols GetRequiredSymbols (Assembly assembly = null)
{
CollectAllSymbols ();
Symbols filtered = new Symbols ();
foreach (var ep in dynamic_symbols) {
if (IsRequiredSymbol (ep, assembly)) {
filtered.Add (ep);
}
}
return filtered ?? dynamic_symbols;
}
#if MTOUCH
IEnumerable<CompileTask> GenerateReferencingSource (string reference_m, IEnumerable<Symbol> symbols)
#else
internal string GenerateReferencingSource (string reference_m, IEnumerable<Symbol> symbols)
#endif
{
if (!symbols.Any ()) {
if (File.Exists (reference_m))
File.Delete (reference_m);
#if MTOUCH
yield break;
#else
return null;
#endif
}
var sb = new StringBuilder ();
sb.AppendLine ("#import <Foundation/Foundation.h>");
foreach (var symbol in symbols) {
switch (symbol.Type) {
case SymbolType.Function:
case SymbolType.Field:
sb.Append ("extern void * ").Append (symbol.Name).AppendLine (";");
break;
case SymbolType.ObjectiveCClass:
sb.AppendLine ($"@interface {symbol.ObjectiveCName} : NSObject @end");
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
}
sb.AppendLine ("static void __xamarin_symbol_referencer () __attribute__ ((used)) __attribute__ ((optnone));");
sb.AppendLine ("void __xamarin_symbol_referencer ()");
sb.AppendLine ("{");
sb.AppendLine ("\tvoid *value;");
foreach (var symbol in symbols) {
switch (symbol.Type) {
case SymbolType.Function:
case SymbolType.Field:
sb.AppendLine ($"\tvalue = {symbol.Name};");
break;
case SymbolType.ObjectiveCClass:
sb.AppendLine ($"\tvalue = [{symbol.ObjectiveCName} class];");
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
}
sb.AppendLine ("}");
sb.AppendLine ();
[mtouch/mmp] Fix tracking of whether the static registrar should run again or not. Fixes #641. (#3534) (#3536) * [tests] Improve debug spew for the RebuildTest_WithExtensions test. * [mtouch/mmp] Store/load if the dynamic registrar is removed or not into the cached link results. Store/load if the dynamic registrar is removed or not into the cached link results, so that we generate the correct main.m even if cached linker results are used. * [mtouch/mmp] The static registrar must not execute if we're loading cached results from the linker. The static registrar must not execute if we're loading cached results from the linker, because the static registrar needs information from the linker that's not restored from the cache. * [mtouch/mmp] Share Touch code. * [mtouch/mmp] Make it possible to touch inexistent files (to create them). * [mtouch/mmp] Fix tracking of whether the static registrar should run again or not. The recent changes to support optimizing away the dynamic registrar caused the Xamarin.MTouch.RebuildTest_WithExtensions test to regress. The problem ----------- * The linker now collects and stores information the static registrar needs. * This information is not restored from disk when the linker realizes that it can reload previously linked assemblies instead of executing again. * The static registrar runs again (for another reason). * The information the static registrar needs isn't available, and incorrect output follows. So fix 1: show an error if the static registrar runs when the linker loaded cached results. The exact scenario the test ran into is this: * 1st build: everything is new and everything is built. * 2nd build: contents of .exe changes, the linker runs again, the static registrar runs again, but sees that the generated output didn't change, so it doesn't write the new content to disk (this is an optimization to avoid compiling the registrar.m file again unless needed). * 3rd build: only the .exe timestamp changes, the linker sees nothing changes in the contents of the .exe and loads the previously linked assemblies from disk, the static registrar sees that the .exe's timestamp is newer than registrar.m's timestamp and run again, but doesn't produce the right result because it doesn't have the information it needs. Considered solutions -------------------- 1. Only track timestamps, not file contents. This is not ideal, since it will result in more work done: in particular for the case above, it would add a registrar.m compilation in build #2, and linker rerun + static registrar rerun + registrar.m compilation + final native link in build #3. 2. Always write the output of the static registrar, even if it hasn't changed. This is not ideal either, since it will also result in more work done: for the case above, it would add a registrar.m compilation + final native link in build #3. 3. Always write the output of the static registrar, but track if it changed or not, and if it didn't, just touch registrar.o instead of recompiling it. This only means the final native link in build #3 is added (see #5 for why this is worse than it sounds). 4. Always write the output of the static registrar, but track it it changed or not, and if it didn't, just touch registrar.o instead of recompiling it, and track that too, so that the final native link in build #3 isn't needed anymore. Unfortunately this may result in incorrect behavior, because now the msbuild tasks will detect that the executable has changed, and may run dsymutil + strip again. The executable didn't actually change, which means it would be the previously stripped executable, and thus we'd end up with an empty .dSYM because we ran dsymtil on an already stripped executable. 5. Idea #4, but write the output of the final link into a temporary directory instead of the .app, so that we could track whether we should update the executable in the .app or not. This is not optimal either, because executables can be *big* (I've seen multi-GB tvOS bitcode executables), and extra copies of such files should not be taken lightly. 6. Idea #4, but tell the MSBuild tasks that dsymutil/strip doesn't need to be rerun even if the timestamp of the executable changed. This might actually work, but now the solution's become quite complex. Implemented solution -------------------- Use stamp files to detect whether a file is up-to-date or not. In particular: * When we don't write to a file because the new contents are identical to the old contents, we now touch a .stamp file. This stamp file means "the accompanying file was determined to be up-to-date when the stamp was touched." * When checking whether a file is up-to-date, also check for the presence of a .stamp file, and if it exists, use the highest timestamp between the stamp file and the actual file. Now the test scenario becomes: * 1st build: everything is new and everything is built. * 2nd build: contents of .exe changes, the linker runs again, the static registrar runs again, but sees that the generated output didn't change, so it doesn't write the new content to disk, but it creates a registrar.m.stamp file to indicate the point in time when registrar.m was considered up-to- date. * 3rd build: only the .exe timestamp changes, the linker sees nothing changes in the contents of the .exe and loads the previously linked assemblies from disk, the static registrar sees that the .exe's timestamp is *older* than registrar.m.stamp's timestamp and doesn't run again. We only use the stamp file for source code (registrar.[m|h], main.[m|h], pinvokes.[m|h]), since using it every time has too much potential for running into other problems (for instance we should never create .stamp files inside the .app). Fixes these test failures: 1) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("single","",False,System.String[]) single Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory371/testApp.app/testApp is modified, timestamp: 2/15/2018 3:04:11 PM > 2/15/2018 3:04:09 PM" > 2) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("dual","armv7,arm64",False,System.String[]) dual Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory375/testApp.app/testApp is modified, timestamp: 2/15/2018 3:06:03 PM > 2/15/2018 3:06:00 PM" > 3) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("llvm","armv7+llvm",False,System.String[]) llvm Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory379/testApp.app/testApp is modified, timestamp: 2/15/2018 3:07:14 PM > 2/15/2018 3:07:12 PM" > 4) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("debug","",True,System.String[]) debug Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory383/testApp.app/testApp is modified, timestamp: 2/15/2018 3:08:16 PM > 2/15/2018 3:08:13 PM" > 5) Failed : Xamarin.MTouch.RebuildTest_WithExtensions("single-framework","",False,System.String[]) single-framework Expected: <empty> But was: < "/Users/builder/data/lanes/5746/4123bf7e/source/xamarin-macios/tests/mtouch/bin/Debug/tmp-test-dir/Xamarin.Tests.BundlerTool.CreateTemporaryDirectory387/testApp.app/testApp is modified, timestamp: 2/15/2018 3:09:18 PM > 2/15/2018 3:09:16 PM" > Fixes https://github.com/xamarin/maccore/issues/641
2018-02-20 13:43:23 +03:00
Driver.WriteIfDifferent (reference_m, sb.ToString (), true);
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
#if MTOUCH
foreach (var abi in GetArchitectures (AssemblyBuildTarget.StaticObject)) {
var arch = abi.AsArchString ();
var reference_o = Path.Combine (Path.GetDirectoryName (reference_m), arch, Path.GetFileNameWithoutExtension (reference_m) + ".o");
var compile_task = new CompileTask {
Target = this,
Abi = abi,
InputFile = reference_m,
OutputFile = reference_o,
SharedLibrary = false,
Language = "objective-c",
};
yield return compile_task;
}
#else
return reference_m;
#endif
}
// This is to load the symbols for all assemblies, so that we can give better error messages
// (with file name / line number information).
public void LoadSymbols ()
{
foreach (var a in Assemblies)
a.LoadSymbols ();
}
public void GenerateMain (ApplePlatform platform, Abi abi, string main_source, IList<string> registration_methods)
{
var sb = new StringBuilder ();
GenerateMain (sb, platform, abi, main_source, registration_methods);
}
public void GenerateMain (StringBuilder sb, ApplePlatform platform, Abi abi, string main_source, IList<string> registration_methods)
{
try {
using (var sw = new StringWriter (sb)) {
if (registration_methods != null) {
foreach (var method in registration_methods) {
sw.Write ("extern \"C\" void ");
sw.Write (method);
sw.WriteLine ("();");
}
sw.WriteLine ();
}
sw.WriteLine ("static void xamarin_invoke_registration_methods ()");
sw.WriteLine ("{");
if (registration_methods != null) {
for (int i = 0; i < registration_methods.Count; i++) {
sw.Write ("\t");
sw.Write (registration_methods [i]);
sw.WriteLine ("();");
}
}
sw.WriteLine ("}");
sw.WriteLine ();
switch (platform) {
case ApplePlatform.iOS:
case ApplePlatform.TVOS:
case ApplePlatform.WatchOS:
case ApplePlatform.MacCatalyst:
GenerateIOSMain (sw, abi);
break;
case ApplePlatform.MacOSX:
GenerateMacMain (sw);
break;
default:
throw ErrorHelper.CreateError (71, Errors.MX0071, platform, App.ProductName);
}
}
Driver.WriteIfDifferent (main_source, sb.ToString (), true);
} catch (ProductException) {
throw;
} catch (Exception e) {
throw new ProductException (4001, true, e, Errors.MT4001, main_source);
}
}
void GenerateMacMain (StringWriter sw)
{
sw.WriteLine ("#define MONOMAC 1");
sw.WriteLine ("#include <xamarin/xamarin.h>");
#if !NET
if (App.Registrar == RegistrarMode.PartialStatic)
sw.WriteLine ("extern \"C\" void xamarin_create_classes_Xamarin_Mac ();");
#endif
sw.WriteLine ();
sw.WriteLine ();
sw.WriteLine ();
sw.WriteLine ("extern \"C\" int xammac_setup ()");
sw.WriteLine ("{");
if (App.CustomBundleName != null) {
sw.WriteLine ("\textern NSString* xamarin_custom_bundle_name;");
sw.WriteLine ("\txamarin_custom_bundle_name = @\"" + App.CustomBundleName + "\";");
}
sw.WriteLine ("\txamarin_executable_name = \"{0}\";", App.AssemblyName);
if (!App.IsDefaultMarshalManagedExceptionMode)
sw.WriteLine ("\txamarin_marshal_managed_exception_mode = MarshalManagedExceptionMode{0};", App.MarshalManagedExceptions);
#if NET
// We require support for dllmap, which isn't in .NET/macOS yet (https://github.com/dotnet/runtime/issues/43204), so disable
sw.WriteLine ("\txamarin_marshal_objectivec_exception_mode = MarshalObjectiveCExceptionModeDisable;");
#else
sw.WriteLine ("\txamarin_marshal_objectivec_exception_mode = MarshalObjectiveCExceptionMode{0};", App.MarshalObjectiveCExceptions);
#endif
if (App.DisableLldbAttach.HasValue ? App.DisableLldbAttach.Value : !App.EnableDebug)
sw.WriteLine ("\txamarin_disable_lldb_attach = true;");
if (App.DisableOmitFramePointer ?? App.EnableDebug)
sw.WriteLine ("\txamarin_disable_omit_fp = true;");
sw.WriteLine ();
#if !NET
if (App.Registrar == RegistrarMode.Static)
sw.WriteLine ("\txamarin_create_classes ();");
else if (App.Registrar == RegistrarMode.PartialStatic)
sw.WriteLine ("\txamarin_create_classes_Xamarin_Mac ();");
#endif
if (App.EnableDebug)
sw.WriteLine ("\txamarin_debug_mode = TRUE;");
sw.WriteLine ($"\tsetenv (\"MONO_GC_PARAMS\", \"{App.MonoGCParams}\", 1);");
sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", App.DynamicRegistrationSupported ? "TRUE" : "FALSE");
#if MMP
// AOT for .NET/macOS needs some design to verify it's staying the same way as current Xamarin.Mac
// for instance: we might decide to select which assemblies to AOT in a different way.
if (App.AOTOptions != null && App.AOTOptions.IsHybridAOT)
sw.WriteLine ("\txamarin_mac_hybrid_aot = TRUE;");
#endif
if (Driver.IsUnifiedMobile)
sw.WriteLine ("\txamarin_mac_modern = TRUE;");
sw.WriteLine ("\txamarin_invoke_registration_methods ();");
sw.WriteLine ("\treturn 0;");
sw.WriteLine ("}");
sw.WriteLine ();
}
// note: this is executed under Parallel.ForEach
void GenerateIOSMain (StringWriter sw, Abi abi)
{
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++;
}
}
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 ();
// 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);");
sw.WriteLine ("\txamarin_invoke_registration_methods ();");
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 ("}");
}
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;
}
2016-04-21 15:57:02 +03:00
}
}