I am trying to compile my iOS application using MonoTouch in Link SDK only mode. It compiles completely fine if I turn off linking entirely but it also produces a colossal binary which is not suitable for release mode.
Unfortunately, one of the libraries that I need somehow invokes Expression.Visit and I can't figure out how to instruct the linker to not strip it out. This results in this compilation error:
Error MT2002: Failed to resolve "System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor::Visit(System.Linq.Expressions.Expression)" reference from "System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" (MT2002) (MyApp)
As per the documentation on custom linking, I have set up a linker file to try to stop this happening:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor">
<method signature="System.Linq.Expressions.Expression Visit(System.Linq.Expressions.Expression)" />
</type>
</assembly>
</linker>
Unfortunately, that doesn't have any effect - the error just happens as before.
The documentation mentions a preserve="fields"
parameter I can supply to <type>
, so I tried that:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor" preserve="methods" />
</assembly>
</linker>
That didn't work either.
I then introduced an XML syntax error into the file and the build failed saying it couldn't parse the linker file so I at least know that the file is being read.
But then I tried introducing errors into the assembly name:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="NonexistentAssembly">
</assembly>
</linker>
That caused an error, complaining that the assembly couldn't be resolved.
I then tried to mangle the type name:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="NonExistentType" preserve="methods" />
</assembly>
</linker>
Now, that just started showing the same "unable to resolve expressionvisitor::visit" error I was seeing before. It seems that type names are not checked.
Also, neither are signature names as this also presented the same compilation error.
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor">
<method signature="jg98j23890rj2390erk90fk3ew!]['##'#'[" />
</type>
</assembly>
</linker>
So it seems that so long as you specify the assembly name and have a valid XML structure, the linker file does not cause any exceptions to be thrown. The documentation for the linker file though is not especially verbose for such a complex topic and includes numerous syntax errors, i.e.:
<type fullname="Foo" preserve="fields" />
<method name=".ctor" />
</type>
Also, it doesn't give a technical description of the linker file format so it's entirely possible that my definition is totally wrong.
I have also tried just skipping the linking of System.Core entirely with --linkskip=System.Core
but this has no effect. I have tried this flag both with and without --xml
.
In the MvvmCross project, I tried specifying a new class to call the Visit method in the same style as the LinkerPleaseInclude.cs file that gets added to every iOS project by the MvvmCross NuGet package:
[Preserve]
public class PleaseIncludeVisitor : ExpressionVisitor
{
public PleaseIncludeVisitor()
{
this.Visit(null);
}
}
Unfortunately, this also had no effect.
I am currently using Mono 3.2.6 ((no/9b58377) and Xamarin.iOS v7.0.7.2.