Failed to archive Xamarin.Forms project

Asked

Viewed 847 times

2

Next, I am finishing my project and as last step I am trying to "archive" my android project, however while trying to archive it generates the following error:

    Erro        Falha inesperada da tarefa "LinkAssemblies".
Mono.Linker.MarkException: Error processing method: 'System.Void Xamarin.Forms.Pages.BaseDataSource/<Initialize>d__22::MoveNext()' in assembly: 'Xamarin.Forms.Pages.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve System.Void Xamarin.Forms.Log::Warning(System.String,System.String)
   em Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference)
   em Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)
   em Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction)
   em Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
   em Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
   em Mono.Linker.Steps.MarkStep.ProcessQueue()
   --- Fim do rastreamento de pilha de exceções internas ---
   em Mono.Linker.Steps.MarkStep.ProcessQueue()
   em Mono.Linker.Steps.MarkStep.ProcessEntireQueue()
   em Mono.Linker.Steps.MarkStep.Process()
   em Mono.Linker.Steps.MarkStep.Process(LinkContext context)
   em Mono.Linker.Pipeline.Process(LinkContext context)
   em MonoDroid.Tuner.Linker.Process(LinkerOptions options, ILogger logger, LinkContext& context)
   em Xamarin.Android.Tasks.LinkAssemblies.Execute(DirectoryAssemblyResolver res)
   em Xamarin.Android.Tasks.LinkAssemblies.Execute()
   em Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   em Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() AppRDVAUX.Android   C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets   1748    

After a lot of searching I noticed that this error is related to an option marked in Android.Manifest called Linker(linking), in Voce you have the option to "compress" your application so that it doesn’t get too big. Without this option checked my project generates apk, however it gets very large(70mb). So to sum up, does anyone know how to make this binding option work or has any other way to make the generated apk get smaller? Thanks in advance to those who can answer.

1 answer

2

The mechanism of Linker is not based on a compaction, but in removing unused features (basically methods and classes) in your app. This is how it reduces the size of the app - "capping" referenced libraries to keep only what is used.

The point is that, for this, Linker identifies what is or is not being used through a static analysis, and sometimes it can remove methods that are being used at runtime (as method invoked via reflection, for example).

In a free translation, the microsoft documentation says that

Applications Xamarin.Android use the Linker to reduce the size of the app. Linker applies a static analysis of your application to determine which libraries, types and members are actually being used. He behaves like a Garbage Collector, recursively searching for libraries, types and members that are referenced until determining the scope of use of the library. From then on, everything within that scope is discarded.

I confess that using Full Linker is not a trivial task when you already have a project built: it is a slow process to identify and correct improper removals. This subject is even being taught as an advanced topic in the Xamarin Marathon ongoing.

In general, the staff indicates to use the intermediate option (pass the Linker in the SDK libraries only) and from the beginning of the project, so it is easier to identify if something should not have been removed. This already gives a good reduced app size.

How to apply Linker to the project

You can start by understanding the linker’s behavior, using the option "SDK Libraries" initially and go making the settings of the elements that are used in running time after identifying them one by one.

The setting for this comes down to three options:

1. The strategy shall LinkerPleaseInclude or Falseflag

It consists of making a reference to the members and/or classes that have been discarded.

An example of microsoft’s own documentation:

[Activity (Label="Linker Example", MainLauncher=true)]
class MyActivity 
{   
    static bool falseflag = false;
    static MyActivity ()
    {
        if (falseflag)
            var ignore = new Example ();
    }
    // ...
}

In practice this code will never be executed, but as a force for reference to the type Example, this constructor will not be removed by Linker.

2. Attribute Preserve

Another way to do the same as shown above would be to use the attribute Preserve:

public class Example
{
    [Android.Runtime.Preserve]
    public Example ()
    {
        // ...
    }
}

3. Custom configuration file

The other alternative would be to use an xml file with the configuration. This file needs to have its build action set to LinkDescription.

Here’s an example of the file from the same source:

<linker>
        <assembly fullname="mscorlib">
                <type fullname="System.Environment">
                        <field name="mono_corlib_version" />
                        <method name="get_StackTrace" />
                </type>
        </assembly>
        <assembly fullname="My.Own.Assembly">
                <type fullname="Foo" preserve="fields">
                        <method name=".ctor" />
                </type>
                <type fullname="Bar">
                        <method signature="System.Void .ctor(System.String)" />
                        <field signature="System.String _blah" />
                </type>
                <namespace fullname="My.Own.Namespace" />
                <type fullname="My.Other*" />
        </assembly>
</linker>

The latter, however, requires further study of the expected file format, syntax, wildcard characters and so on.

And to identify the members, types and classes that have been removed?

That’s the hard part. When the project is already developed this step should take considerable time. To run, you can activate Linker in debug mode, and go putting breakpoints in the application’s execution chain and treating case by case. You also have the possibility to use the BitDiffer, comparing a compilation without and one with Linker. So you will be able to identify all members, types and libraries that have been removed and deal directly with the cases.

Details on this procedure would be more of a tutorial and I don’t believe it would be content on here at Sopt. Again recommend the contents of Module 8 from Advanced Xamarin Marathon that deals with that subject.

Finally...

You can’t help your specific case, as you might imagine, because when it comes to Linker, each case is a case. Your solution needs to be evaluated along with the error message of the Linker or execution process to be corrected.

I hope this helps.

  • 1

    Hello Diego, thank you for answering, I removed some libraries from my project that I believe were responsible for not archiving my project (in my case they were Xamarin.Theme.Base, Xamarin.Theme.Ligth, Xamarin.Theme.Dark ), I adjusted the project and selected the option to link "SDK Assemblies Only" it managed to archive, generated the apk and to my surprise the size was not reduced at all, still a file of giant size for an apk. Anyway, this already problem for another topic and I am researching more on the subject. I thank you again for your help.

  • @Q.Wesley if Linker hasn’t made a difference in apk size, we have two options: either some library you’re using is too large or virtually all of the app’s content is being preserved and Linker is having no effect. A project hello world simple would already have a reduction of 70 to 87% apk size. Check Bitdiffer

  • 1

    Hi Diego, thanks for the help, I managed to generate an apk with 15mb (it was already a tremendous difference), I got this by redoing the whole project, started a new project updated everything, all libraries, files, imported the classes of my project enabled the options and worked, I don’t know exactly what was wrong, but it worked. I will not stop looking at the Bitdiffer you indicated, is a tool that will definitely help me a lot. Thanks again.

  • Ball show. 15 Mb already makes things easier. =)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.