Switch to a different documentation area.

Xamarin - Documentation

iOS

change platform

  1. Xamarin
  2. iOS
  3. Advanced Topics
  4. Linker

Linker

When building your application, MonoDevelop calls a tool called mtouch that includes a linker for managed code. It is used to remove from the class libraries the features that the application is not using. The goal is to reduce the size of the application, which will ship with only the necessary bits.

The linker uses static analysis to determine the different code paths that your application is susceptible to follow. It's a bit heavy as it has to go through every detail of each assembly, to make sure that nothing discoverable is removed. As such it is not enabled, by defaut, on the simulator builds. But since it produce smaller applications it can speed up AOT compilation and uploading to the device so, by default, all devices builds are using the linker.

As the linker is a static tool, it can not mark for inclusion types and methods that are called through reflection, or dynamically instantiated. Several options exists to workaround this limitation.

Linker Behavior

The linking process can be customized in different ways. The primary mechanism for controlling the linker is the Linker Behavior drop-down within MonoDevelop's Project Options dialog box. Three main options are offered:

Don't Link

Disabling linking will make sure that no assemblies are modified. For performance reasons this is the default setting when MonoDevelop targets for the iOS simulator. For devices builds this should only be used as a workaround whenever the linker contains a bug that prevents your application to run. If your application only works with -nolink, please submit a bug report.

This correspond to the -nolink option when using the command-line tool mtouch.

Link SDK assemblies only

In this mode, the linker will leave your assemblies untouched, and will reduce the size of the SDK assemblies (i.e. what's shipped with MonoTouch) by removing everything that your application doesn't use. This is the default setting when MonoDevelop targets iOS devices.

This is the most simple option, as it does not require any change in your code. The difference with linking everything is that the linker can not perform a few optimizations in this mode, so it's a trade-off between the work needed to link everything and the final application size.

This correspond to the -linksdk option when using the command-line tool mtouch.

Link all assemblies

When linking everything, the linker can use the whole set of its optimizations to make the application as small as possible. It will modify user code, which may break whenever the code uses features in a way that the linker's static analysis cannot detect. In such cases, e.g. webservices, reflection, or serialization, some adjustements might be required in your application to link everything.

This correspond to the -linkall option when using the command-line tool mtouch.

Controlling the Linker

When you use the linker it will sometimes will remove code that you might have called dynamically, even indirectly. To cover those cases the linker provides a few features and options to allow you greater control on it's actions.

Preserving Code

When you use the linker it can sometimes remove code that you might have called dynamically either using System.Reflection.MemberInfo.Invoke, or by exporting your methods to Objective-C using the [Export] attribute and then invoking the selector manually.

In those cases, you can instruct the linker to consider either entire classes to be used or individual members to be preserved by applying the [MonoTouch.Foundation.Preserve] attribute either at the class-level or the member-level. Every member that is not statically linked by the application is subject to be removed. This attribute is hence used to mark members that are not statically referenced, but that are still needed by your application.

For instance, if you instantiate types dynamically, you may want to preserve the default constructor of your types. If you use XML serialization, you may want to preserve the properties of your types.

You can apply this attribute on every member of a type, or on the type itself. If you want to preserve the whole type, you can use the syntax [Preserve (AllMembers = true)] on the type.

Sometimes you want to preserve certain members, but only if the containing type was preserved.   In those cases, use [Preserve (Conditional=true)]

Skipping Assemblies

It is possible to specify assemblies that should not be excluded from the linker process, while allowing other assemblies to be linked normally. This is helpful if using [Preserve] on some assemblies is impossible (e.g. 3rd party code) or as a temporary workaround for a bug.

This correspond to the -linkskip option when using the command-line tool mtouch.

There is no user interface to use this option but it can be provided in the MonoDevelop Project Options dialog within "Additional mtouch arguments" text field. E.g. "--linkskip=mscorlib" would not link mscorlib.dll but would link other assemblies in the solution.

Disabling "Link Away"

The linker will remove code that is very unlikely to be used on devices, e.g. unsupported or disallowed. In rare occasion it is possible that an application or library depends on this (working or not) code. Since MonoTouch 5.0.1 the linker can be instructed to skip this optimization.

This correspond to the -nolinkaway option when using the command-line tool mtouch.

There is no user interface to use this option but it can be provided in the MonoDevelop Project Options dialog within "Additional mtouch arguments" text field. E.g. "--nolinkaway" would not remove the extra code (about 100kb).