Using The Linker In Xamarin Projects

Xamarin Linker is used in iOS and Android projects, to remove unused code from compiled assemblies. This helps reduce the final size of the apk or ipa. However, it is often too aggressive, and starts stripping away methods and fields you are using. This is common, if methods are only referenced by reflection.

Linker Options

First, the linker has a few options that we can choose from. None/Don’t Link, means the linker won’t do anything, and everything will be included in the resulting package. Sdk Assemblies Only/Link Framework SDKs Only is limited to base class libraries. What they exactly include is listed in Available Assemblies. Sdk and User Assemblies/Link All is everything, including your code.

You can set the Linker options by going to Properties in Android

In Properties in iOS you will see this.

File Size

If you don’t use the Linker, and you select many different types of architectures to support, you will soon find out your resulting package, will be very large. Using the Linker, and linking all assemblies, can result in the resulting package being between 20-30% of the non-linked package size.

It is best to get linking all assemblies working, to ensure your package size, is the smallest result possible, hence the fastest download speed for your users.

Configuration

Sometimes the linker can’t find everything that you are using. This is certainly the case when using Reflection. When you try to run your app, when the linker removes more than it should, you will come across errors such as, MissingMethodException. Here are the ways you can tell the linker to stop removing certain assemblies, and/or methods.

Create A Reference Class

This is a trick picked up by a few developers, that is the simplest way to resolve the issue. Create a class in your Android or iOS project, called LinkerPleaseInclude. Then reference the class and methods you want to use, inside functions, as shown.

public class LinkerPleaseInclude
{
    public void Include(MyType arg)
    {
        arg.MethodIDontWantRemoved();
    }
}

Don’t call this class from anywhere, but just having it there, the Linker will assume they are all called, and stop removing them from the resulting binary.

Assemblies

If it is removing entire assemblies, and you want everything in that assembly kept, you can tell the linker to not link certain assemblies.

In iOS, you place these in the mtouch arguments box.

--linkskip=AssemblyOne --linkskip=AssemblyTwo

In Android, place this in the Skip Linking Assemblies box, under Android Options in your projects Properties.

assemblyOne; assemblyTwo

Preserve Attribute

There is a preserve attribute in the Android and iOS sdk’s that you can use to tag methods or whole classes, to not link. If you want to do this in a class library, then you can create an attribute called Preserve. It works on the name of the attribute, not a reference to the actual class. You can do this at the assembly level.

[assembly: Preserve (typeof (MyType), AllMembers = true)]

Or place it on top of a class or method.

[Preserve (AllMembers = true)]

XML Config

First a note, that I have not actually got this working correctly before, but it is listed in Xamarin’s Custom Linker Configuration documentation. You can create an XML file, and place it in the root of your iOS or Android project. Then set the Build Action to LinkDescription.

From here you can write an XML file, with assembly and methods names, that you do not want to be linked.

<linker>
    <assembly fullname="AssemblyOne">
        <type fullname="Namespace.Class">
            <field name="fieldName" />
            <method name="get_Property" />
        </type>
    </assembly>
</linker>

Look at the official Xamarin documentation, to discover more ways to reference methods.

Learn More

If you want to delve into the exact differences of resulting binaries, from the linker, you can use a tool such as BitDiffer. You can find the Xamarin documentation on linking at Linking on iOS and Linking on Android.

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,000+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Related Posts

3 Comments

  1. Gabriel Barreto

    Have you already configure the full linker with Prism + Unity?
    I’ve spent a lot of time on that and was not able to make it work.
    I’m getting this error:

    The type initializer for ‘Microsoft.Practices.Unity.ArrayResolutionStrategy’ threw an exception. —> System.InvalidOperationException: Sequence contains no matching element

    If you could give me some help, i will be very gratetful.
    Thanks in advance.

    1. Adam Pedley

      Just to confirm, does this work, if the Linker is set to None?

      That error is saying that it was trying to initialize ArrayResolutionStrategy, but nothing in the list was found. I am guessing that it is trying to inject a certain type in here, but it’s not finding it. See what it’s constructor parameters are, then use the LinkerPleaseInclude method above to create a reference to that type.

      1. Gabriel Barreto

        Hi, thank you for the fast reply.

        Yes, my app is working with link set to none and set do Link only sdk assemblies.
        Ok, I will try, if I can make it work, i will let you know.

        Thank you very much!

Leave A Comment?