Failed to archive project Xamarin.forms

2

Next, I'm finishing my project and as last step I'm trying to "archive" my android project, but when trying to file it 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 Studio17\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets   1748    

After much searching I noticed that this error is related to an option marked in Android.Manifest called Linker, in it you have the option to "compact" your application in a way that does not get too big. Without this option marked my project generates the apk, but it gets very big (70mb). So in short, does anyone know how to make this linking option work or do you have some other way to make the generated apk get smaller? Thanks in advance to anyone who can respond.

    
asked by anonymous 25.06.2018 / 14:28

1 answer

2

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

The point is that for this, the 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 (such as methods invoked via reflection, by example).

In a free translation, microsoft documentation says that

  

Xamarin.Android applications use linker to reduce the size of the application. The linker applies a static analysis of your application to determine what libraries, types, and members are actually being used. It behaves like a garbage collector , searching recursively for libraries, types, and member that are referenced until determining the scope of library usage. From there, everything from that scope is discarded .

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

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

How to apply the linker in the project

You can start by understanding the Linker behavior , using the "SDK Libraries" option initially and going to make the settings of the elements that are used in runtime after identifying them one by one .

The configuration for this boils down to three options:

1. The LinkerPleaseInclude strategy or FalseFlag

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

An example of the Microsoft documentation itself:

[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 reference force for 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 Preserve attribute:

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 is an example of the same source file:

<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 a deeper study of the expected file format, syntax, wildcard characters, and so on.

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

That's the hard part. When the project is already developed this step should consume considerable time. To execute it, you can activate the linker in debug mode, and go putting breakpoints in the application's execution chain and treat each other on a case-by-case basis. You can also use BitDiffer , comparing a one-to-one compilation with the linker. This way 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 do not believe it would be content on here in SOpt. Again I recommend the contents of Module 8 of the Marathon Xamarin Advanced that deals with this subject.

Finally ...

You can not help your case, as you can imagine, because when it comes to Linker, every case is a case. Your solution needs to be evaluated along with the linker or runtime error message to fix.

I hope this helps.

    
25.06.2018 / 19:56