Liaison d’applications Xamarin.iOSLinking Xamarin.iOS Apps

Lorsque vous générez votre application, Visual Studio pour Mac ou Visual Studio appelle un outil nommé mtouch qui inclut un éditeur de liens pour le code managé.When building your application, Visual Studio for Mac or Visual Studio calls a tool called mtouch that includes a linker for managed code. Il est utilisé pour supprimer des bibliothèques de classes les fonctionnalités que l’application n’utilise pas.It is used to remove from the class libraries the features that the application is not using. L’objectif est de réduire la taille de l’application, livrée avec uniquement les bits nécessaires.The goal is to reduce the size of the application, which will ship with only the necessary bits.

L’éditeur de liens utilise l’analyse statique pour déterminer les différents chemins d’accès au code que votre application est susceptible de suivre.The linker uses static analysis to determine the different code paths that your application is susceptible to follow. Celle-ci est un peu lourde car elle doit passer par tous les détails de chaque assembly, pour vous assurer que rien de détectable n’est supprimé.It's a bit heavy as it has to go through every detail of each assembly, to make sure that nothing discoverable is removed. Elle n’est pas désactivée par défaut sur les builds du simulateur pour accélérer la durée du build pendant le débogage.It is not enabled by default on the simulator builds to speed up the build time while debugging. Toutefois, puisqu’elle génère des applications de plus petite taille pouvant accélérer la compilation AOT et le téléchargement sur l’appareil, tous les builds (version) d’appareils utilisent l’éditeur de liens par défaut.However since it produces smaller applications it can speed up AOT compilation and uploading to the device, all devices (Release) builds are using the linker by default.

Étant donné que l’éditeur de liens est un outil statique, il ne peut pas marquer les types et les méthodes d’inclusion appelés par la réflexion ou instanciés de manière dynamique.As the linker is a static tool, it can not mark for inclusion types and methods that are called through reflection, or dynamically instantiated. Il existe plusieurs options pour contourner cette limitation.Several options exists to workaround this limitation.

Comportement de l'éditeur de liensLinker Behavior

Le processus de liaison peut être personnalisé via le menu déroulant du comportement de l’éditeur de liens dans Options du projet.The linking process can be customized via the linker behavior dropdown in Project Options. Pour accéder à ce processus, double-cliquez sur le projet iOS et accédez à Build iOS > Options de l’éditeur de liens, comme illustré ci-dessous :To access this double-click on the iOS project and browse to iOS Build > Linker Options, as illustrated below:

Les trois options principales proposées sont décrites ci-dessous :The three main options are offered are described below:

La désactivation de la liaison permet de garantir qu’aucun assembly n’est modifié.Disabling linking will make sure that no assemblies are modified. Pour des raisons de performances, il s’agit du paramètre par défaut lorsque votre IDE cible le simulateur iOS.For performance reasons this is the default setting when your IDE targets for the iOS simulator. Pour les builds d’appareils cela doit uniquement être utilisé comme solution de contournement chaque fois que l’éditeur de liens contient un bogue qui empêche l’exécution de votre application.For devices builds this should only be used as a workaround whenever the linker contains a bug that prevents your application to run. Si votre application ne fonctionne qu’avec -nolink, veuillez soumettre un rapport de bogue.If your application only works with -nolink, please submit a bug report.

Cela correspond à l’option -nolink durant l’utilisation de l’outil en ligne de commande mtouch.This corresponds to the -nolink option when using the command-line tool mtouch.

Dans ce mode, l’éditeur de liens conservera vos assemblys intactes et réduira la taille des assemblys du Kit de développement logiciel (par exemple, ce qui est livré avec Xamarin.iOS) en supprimant tout ce qui votre application n’utilise pas.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 Xamarin.iOS) by removing everything that your application doesn't use. Il s’agit du paramètre par défaut lorsque votre IDE cible les appareils iOS.This is the default setting when your IDE targets iOS devices.

Il s’agit de l’option la plus simple, car elle ne nécessite pas de modification de votre code.This is the most simple option, as it does not require any change in your code. La différence avec la liaison de tout est que l’éditeur de liens ne peut pas effectuer certaines optimisations dans ce mode, il s’agit donc d’un compromis entre le travail nécessaire pour lier tous les éléments et la taille de l’application finale.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.

Cela correspond à l’option -linksdk lors de l’utilisation de l’outil de ligne de commande mtouch.This correspond to the -linksdk option when using the command-line tool mtouch.

Lors de la liaison de tous les éléments, l’éditeur de liens peut utiliser l’ensemble de ses optimisations pour rendre l’application aussi petite que possible.When linking everything, the linker can use the whole set of its optimizations to make the application as small as possible. Il modifie le code utilisateur, ce qui peut s’arrêter dès que le code utilise des fonctionnalités d’une manière non détectable par l’analyse statique de l’éditeur de liens.It will modify user code, which may break whenever the code uses features in a way that the linker's static analysis cannot detect. Dans ce cas, par exemple, webservices, réflexion ou sérialisation, certains ajustements peuvent être requis dans votre application pour lier tous les éléments.In such cases, e.g. webservices, reflection, or serialization, some adjustements might be required in your application to link everything.

Cela correspond à l’option -linkall lors de l’utilisation de l’outil de ligne de commande mtouch.This correspond to the -linkall option when using the command-line tool mtouch.

Contrôle de l’éditeur de liensControlling the Linker

Lorsque vous utilisez l’éditeur de liens il peut parfois supprimer le code appelé dynamiquement, même indirectement.When you use the linker it will sometimes will remove code that you might have called dynamically, even indirectly. Pour couvrir ces cas, l’éditeur de liens fournit quelques fonctionnalités et options pour vous permettre un meilleur contrôle sur ses actions.To cover those cases the linker provides a few features and options to allow you greater control on its actions.

Conservation du codePreserving Code

Lorsque vous utilisez l’éditeur de liens, celui-ci peut parfois supprimer le code appelé dynamiquement à l’aide de System.Reflection.MemberInfo.Invoke ou par l’exportation de vos méthodes vers Objective-C à l’aide de l’attribut [Export] et lors de l’appel du sélecteur manuellement.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.

Dans ces cas, vous pouvez demander à l’éditeur de liens de prendre en compte les classes entières à utiliser ou les membres individuels à conservés en appliquant l’attribut [Xamarin.iOS.Foundation.Preserve] au niveau de la classe ou au niveau du membre.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 [Xamarin.iOS.Foundation.Preserve] attribute either at the class-level or the member-level. Chaque membre qui n’est pas lié de manière statique par l’application est soumis à suppression.Every member that is not statically linked by the application is subject to be removed. Cet attribut est donc utilisé pour marquer les membres qui ne sont pas statiquement référencés, mais qui sont toujours requis par votre application.This attribute is hence used to mark members that are not statically referenced, but that are still needed by your application.

Par exemple, si vous instanciez dynamiquement des types, vous souhaiterez éventuellement conserver le constructeur par défaut de vos types.For instance, if you instantiate types dynamically, you may want to preserve the default constructor of your types. Si vous utilisez la sérialisation XML, vous souhaiterez éventuellement conserver les propriétés de vos types.If you use XML serialization, you may want to preserve the properties of your types.

Vous pouvez appliquer cet attribut à chaque membre d’un type ou au type lui-même.You can apply this attribute on every member of a type, or on the type itself. Si vous souhaitez conserver l’ensemble du type, vous pouvez utiliser la syntaxe [Preserve (AllMembers = true)] sur le type.If you want to preserve the whole type, you can use the syntax [Preserve (AllMembers = true)] on the type.

Parfois, vous souhaitez conserver certains membres, mais uniquement si le type conteneur a été conservé.Sometimes you want to preserve certain members, but only if the containing type was preserved. Dans ces cas, utilisez [Preserve (Conditional=true)]In those cases, use [Preserve (Conditional=true)]

Si vous ne souhaitez pas prendre une dépendance sur les bibliothèques Xamarin, par exemple, disons que vous générez une bibliothèque de classes portables multiplateforme (PCL), vous pouvez encore utiliser cet attribut.If you do not want to take a dependency on the Xamarin libraries -for example, say that you are building a cross platform portable class library (PCL) - you can still use this attribute.

Pour ce faire, vous devez simplement déclarer une classe PreserveAttribute et l’utiliser dans votre code, comme suit :To do this, you should just declare a PreserveAttribute class, and use it in your code, like this:

public sealed class PreserveAttribute : System.Attribute {
    public bool AllMembers;
    public bool Conditional;
}

Le nom d’espace défini n’a pas beaucoup d’importance, l’éditeur de liens recherche cet attribut par nom de type.It does not really matter in which namespace this is defined, the linker looks this attribute by type name.

Ignorer des assemblysSkipping Assemblies

Il est possible de spécifier des assemblys exclus du processus de l’éditeur de liens, tout en permettant aux autres assemblys d’être liés normalement.It is possible to specify assemblies that should be excluded from the linker process, while allowing other assemblies to be linked normally. Cela est utile si l’utilisation de [Preserve] sur certains assemblys est impossible (par exemple, code tiers) ou en tant que solution de contournement temporaire d’un bogue.This is helpful if using [Preserve] on some assemblies is impossible (e.g. 3rd party code) or as a temporary workaround for a bug.

Cela correspond à l’option --linkskip lors de l’utilisation de l’outil de ligne de commande mtouch.This correspond to the --linkskip option when using the command-line tool mtouch.

Lorsque vous utilisez l’option Lier tous les assemblys, si vous souhaitez indiquer à l’éditeur de liens d’ignorer des assemblys entiers, placez les éléments suivants dans l’option Arguments mtouch supplémentaires de votre assembly de niveau supérieur :When using Link All Assemblies option, if you want to tell the linker to skip entire assemblies, put the following in the Additional mtouch arguments options of your top-level assembly:

--linkskip=NameOfAssemblyToSkipWithoutFileExtension

Si vous souhaitez que l’éditeur de liens ignore plusieurs assemblys, incluez plusieurs arguments linkskip :If you want the linker to skip multiple assemblies, you include multiple linkskip arguments:

--linkskip=NameOfFirstAssembly --linkskip=NameOfSecondAssembly

Aucune interface utilisateur n’utilise cette option, mais elle peut être fournie dans la boîte de dialogue Options de projet Visual Studio pour Mac ou le volet Propriétés de projet Visual Studio, dans le champ de texte Arguments mtouch supplémentaires.There is no user interface to use this option but it can be provided in the Visual Studio for Mac Project Options dialog or the Visual Studio project Properties pane, within the Additional mtouch arguments text field. (Par ex.(E.g. --linkskip=mscorlib ne lie pas mscorlib.dll, mais lie d’autres assemblys dans la solution).--linkskip=mscorlib would not link mscorlib.dll but would link other assemblies in the solution).

L’éditeur de liens supprimera le code qui ne sera très probablement pas utilisé sur les appareils, par exemple, non pris en charge ou non autorisé.The linker will remove code that is very unlikely to be used on devices, e.g. unsupported or disallowed. Dans de rares cas, il est possible qu’une application ou une bibliothèque dépende de ce code (de travail ou pas).In rare occasion it is possible that an application or library depends on this (working or not) code. Depuis Xamarin.iOS 5.0.1, l’éditeur de liens peut être configuré pour ignorer cette optimisation.Since Xamarin.iOS 5.0.1 the linker can be instructed to skip this optimization.

Cela correspond à l’option -nolinkaway lors de l’utilisation de l’outil de ligne de commande mtouch.This correspond to the -nolinkaway option when using the command-line tool mtouch.

Aucune interface utilisateur n’utilise cette option, mais elle peut être fournie dans la boîte de dialogue Options de projet Visual Studio pour Mac ou le volet Propriétés de projet Visual Studio, dans le champ de texte Arguments mtouch supplémentaires.There is no user interface to use this option but it can be provided in the Visual Studio for Mac Project Options dialog or the Visual Studio project Properties pane, within Additional mtouch arguments text field. (Par ex.(E.g. --nolinkaway ne supprime pas le code supplémentaire (environ 100 Ko).--nolinkaway would not remove the extra code (about 100kb)).

Marquage de votre assembly comme prêt pour l’éditeur de liensMarking your Assembly as Linker-ready

Les utilisateurs peuvent sélectionner d’uniquement lier les assemblys du Kit de développement logiciel et de ne procéder à aucune liaison vers leur code.Users can select to just link the SDK assemblies, and not do any linking to their code. Cela signifie également que toutes les bibliothèques tierces qui ne font pas partie du Kit de développement logiciel Xamarin central ne seront pas liées.This also means that any third party libraries that are not part of Xamarin's core SDK will not be linked.

Cela se produit en général car ils ne souhaitent pas ajouter manuellement des attributs [Preserve] à leur code.This happens typically, because they do not want to manually add [Preserve] attributes to their code. L’effet secondaire est que les bibliothèques tierces ne seront pas liées, il s’agit là en général d’une bonne valeur par défaut, car il n’est pas possible de savoir si une bibliothèque tierce est conviviale ou pas à l’éditeur de liens.The side effect is that third party libraries will not be linked, and this in general is a good default, as it is not possible to know whether a third party library is linker friendly or not.

Si vous avez une bibliothèque dans votre projet ou si vous êtes un développeur de bibliothèques réutilisables et souhaitez que l’éditeur de liens traite votre assembly comme pouvant être lié, il vous suffit d’ajouter l’attribut de niveau d’assemblyLinkerSafe, comme suit :If you have a library in your project, or you are a developer of reusable libraries and you want the linker to treat your assembly as linkable, all you have to do is add the assembly-level attribute LinkerSafe, like this:

[assembly:LinkerSafe]

Votre bibliothèque n’a pas réellement besoin de référencer les bibliothèques Xamarin pour cela.Your library does not actually need to reference the Xamarin libraries for this. Par exemple, si vous générez une bibliothèque de classes portables qui s’exécutera dans d’autres plateformes vous pouvez toujours utiliser un attribut LinkerSafe.For example, if you are building a Portable Class Library that will run in other platforms you can still use a LinkerSafe attribute. L’éditeur de liens Xamarin recherche l’attribut LinkerSafe par nom et non par son type réel.The Xamarin linker looks up the LinkerSafe attribute by name, not by its actual type. Cela signifie que vous pouvez écrire ce code, il fonctionne également :This means that you can write this code and it will also work:

[assembly:LinkerSafe]
// ... assembly attribute should be at top, before source
class LinkerSafeAttribute : System.Attribute {}

Configuration personnalisée de l’éditeur de liensCustom Linker Configuration

Suivez les instructions pour la création d’un fichier de configuration de l’éditeur de liens.Follow the instructions for creating a linker configuration file.