Vinculación de una aplicación .NET MAUI iOS
Cuando compilas la aplicación, .NET Multi-platform App UI (.NET MAUI) puede usar un enlazador llamado ILLink para reducir el tamaño general de la aplicación. ILLink reduce el tamaño mediante el análisis del código intermedio generado por el compilador. Elimina los métodos, propiedades, campos, eventos, estructuras y clases que no se usan para crear una aplicación que solo contenga el código y las dependencias de ensamblaje necesarios para ejecutarla.
Comportamiento del enlazador
El enlazador admite tres modos para aplicaciones .NET MAUI en iOS y Mac Catalyst:
- No vincular. Deshabilitar la vinculación garantiza que los ensamblados no se modifiquen.
- Vincular solo ensamblados de SDK. En este modo, el enlazador deja intactos los ensamblados y reduce el tamaño de los ensamblados de SDK quitando los tipos y miembros que la aplicación no usa.
- Vincular todos los ensamblados. Cuando vincula todos los ensamblados, el enlazador realiza optimizaciones adicionales para que la aplicación sea lo más pequeña posible. Modifica el código intermedio del código fuente, que puede interrumpir la aplicación si usa características mediante un enfoque que el análisis estático del enlazador no puede detectar. En estos casos, es posible que debas realizar ajustes en el código fuente para que la aplicación funcione correctamente.
El comportamiento del enlazador se puede configurar para cada configuración de compilación de la aplicación.
Advertencia
Habilitar el enlazador para la configuración de depuración de la aplicación puede dificultar la experiencia de depuración, ya que puede quitar descriptores de acceso de propiedad que te permiten inspeccionar el estado de los objetos.
Para configurar el comportamiento del enlazador en Visual Studio:
En el Explorador de soluciones, haz clic con el botón derecho en el proyecto y selecciona Propiedades. Después, ve a la pestaña iOS > Compilación y establece la lista desplegable Comportamiento del enlazador en el comportamiento del enlazador deseado:
Conservar código
Cuando se usa el optimizador, a veces se quita el código al que podría haber llamado dinámicamente, incluso indirectamente. Puede indicar al recortador que conserve los miembros anotando con el DynamicDependency
atributo . Este atributo se puede usar para expresar una dependencia en un tipo y subconjunto de miembros, o en miembros específicos.
Importante
Todos los miembros del BCL que no se pueden determinar estáticamente para usar por la aplicación están sujetos a su eliminación.
El atributo DynamicDependency
se puede aplicar a constructores, campos y métodos:
[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
helper.Invoke(null, null);
}
En este ejemplo, DynamicDependency
garantiza que el método Helper
se mantenga. Sin el atributo , el recorte se quitaría Helper
de MyAssembly
o quitaría MyAssembly
completamente si no se hace referencia a él en otro lugar.
El atributo especifica los miembros que se mantienen mediante string
o mediante el atributo DynamicallyAccessedMembers
. El tipo y el ensamblado están implícitos en el contexto del atributo o se especifican explícitamente en el atributo (mediante Type
, o mediante objetos string
para el tipo y el nombre del ensamblado).
Las cadenas de tipo y miembro usan una variación del formato de cadena de identificador de comentario de documentación de C#, sin el prefijo de miembro. La cadena de miembro no debe incluir el nombre del tipo declarante y puede omitir parámetros para mantener todos los miembros del nombre especificado. En los ejemplos siguientes se muestran usos válidos:
[DynamicDependency("Method()")]
[DynamicDependency("Method(System,Boolean,System.String)")]
[DynamicDependency("MethodOnDifferentType()", typeof(ContainingType))]
[DynamicDependency("MemberName")]
[DynamicDependency("MemberOnUnreferencedAssembly", "ContainingType", "UnreferencedAssembly")]
[DynamicDependency("MemberName", "Namespace.ContainingType.NestedType", "Assembly")]
// generics
[DynamicDependency("GenericMethodName``1")]
[DynamicDependency("GenericMethod``2(``0,``1)")]
[DynamicDependency("MethodWithGenericParameterTypes(System.Collections.Generic.List{System.String})")]
[DynamicDependency("MethodOnGenericType(`0)", "GenericType`1", "UnreferencedAssembly")]
[DynamicDependency("MethodOnGenericType(`0)", typeof(GenericType<>))]
Conservar ensamblados
Es posible especificar ensamblados que se deben excluir del proceso de recorte, al tiempo que se permite recortar otros ensamblados. Este enfoque puede ser útil cuando no se puede usar fácilmente el DynamicDependency
atributo o no controlar el código que se está recortando.
Cuando recorta todos los ensamblados, puede indicar al optimizador que omita un ensamblado estableciendo un TrimmerRootAssembly
elemento de MSBuild en el archivo de proyecto:
<ItemGroup>
<TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>
Nota:
La extensión .dll
no es necesaria al establecer la propiedad de MSBuild TrimmerRootAssembly
.
Si el optimizador omite un ensamblado, se considera raíz, lo que significa que se conservan todas sus dependencias que se entienden estáticamente. Puedes omitir ensamblados adicionales agregando más propiedades de MSBuild TrimmerRootAssembly
a <ItemGroup>
.
Conservar ensamblados, tipos y miembros
Puede pasar al recortador un archivo de descripción XML que especifique qué ensamblados, tipos y miembros deben conservarse.
Para excluir un miembro del proceso de recorte al recortar todos los ensamblados, establezca el TrimmerRootDescriptor
elemento de MSBuild en el archivo de proyecto en el archivo XML que define los miembros que se van a excluir:
<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
A continuación, el archivo XML usa el formato de descriptor de optimizador para definir qué miembros excluir:
<linker>
<assembly fullname="MyAssembly">
<type fullname="MyAssembly.MyClass">
<method name="DynamicallyAccessedMethod" />
</type>
</assembly>
</linker>
En este ejemplo, el archivo XML especifica un método al que accede dinámicamente la aplicación, que se excluye del recorte.
Cuando se muestra un ensamblado, un tipo o un miembro en el XML, la acción predeterminada es conservación, lo que significa que, independientemente de si el optimizador cree que se usa o no, se conserva en la salida.
Nota:
Las etiquetas de conservación son ambiguamente inclusivas. Si no proporcionas el siguiente nivel de detalle, incluirá todos los elementos secundarios. Si se muestra un ensamblado sin ningún tipo, se conservarán todos los tipos y miembros del ensamblado.
Marcar un ensamblado como seguro de recorte
Si tiene una biblioteca en el proyecto o es desarrollador de una biblioteca reutilizable y desea que el optimizador trate el ensamblado como recortable, puede marcar el ensamblado como seguro para recortar agregando la IsTrimmable
propiedad MSBuild al archivo de proyecto para el ensamblado:
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Esto marca el ensamblado como "recortable" y habilita las advertencias de recorte para ese proyecto. Ser "recortable" significa que el ensamblado se considera compatible con el recorte y no debe tener advertencias de recorte al compilar el ensamblado. Cuando se usa en una aplicación recortada, el ensamblado tiene sus miembros sin usar recortados en la salida final.
Al usar la implementación de AOT nativa en .NET 9 y versiones posteriores, al establecer la propiedad IsAotCompatible
MSBuild en true
también se asigna un valor de true
a la propiedad IsTrimmable
y se habilitan propiedades adicionales de compilación del analizador de AOT. Para obtener más información sobre los analizadores de AOT, consulte analizadores de compatibilidad de AOT. Para obtener más información sobre la implementación de AOT nativa para .NET MAUI, consulte implementación de AOT nativa.
Al establecer la propiedad de MSBuild IsTrimmable
en true
en tu archivo del proyecto, se inserta el atributo AssemblyMetadata
en el ensamblado:
[assembly: AssemblyMetadata("IsTrimmable", "True")]
Como alternativa, puedes agregar el atributo AssemblyMetadata
al ensamblado sin haber agregado la propiedad de MSBuild IsTrimmable
al archivo del proyecto de tu ensamblado.
Nota:
Si la propiedad de MSBuild IsTrimmable
está establecida para un ensamblado, esto invalida el atributo AssemblyMetadata("IsTrimmable", "True")
. Esto te permite optar por recortar un ensamblado aunque no tenga el atributo o deshabilitar el recorte de un ensamblado que lo tenga.
Supresión de advertencias de análisis de código
Cuando el optimizador está habilitado, quita il que no es accesible estáticamente. Las aplicaciones que usan reflexión u otros patrones que crean dependencias dinámicas pueden romperse como consecuencia de ello. Para advertir sobre estos patrones, al marcar un ensamblado como seguro de recorte, los autores de bibliotecas deben establecer la SuppressTrimAnalysisWarnings
propiedad false
MSBuild en :
<PropertyGroup>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>
Si no se suprimen las advertencias de análisis de recorte, se incluirán advertencias sobre toda la aplicación, incluido el código propio, el de la biblioteca y el del SDK.
Representación de advertencias detalladas
El análisis de recorte genera como máximo una advertencia para cada ensamblado que procede de un elemento PackageReference
, lo que indica que los aspectos internos del ensamblado no son compatibles con el recorte. Como autor de la biblioteca, al marcar un ensamblado como seguro de recorte, debe habilitar advertencias individuales para todos los ensamblados estableciendo la TrimmerSingleWarn
propiedad false
MSBuild en :
<PropertyGroup>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>
Se muestran todas las advertencias detalladas, en lugar de reducirlas a una única advertencia por ensamblado.