Xamarin/MonoTouch:由于缺少符号,无法在"仅限链接SDK"模式下编译

Ste*_*uts 7 xamarin.ios mvvmcross xamarin

我试图在Link SDK only模式下使用MonoTouch编译我的iOS应用程序.如果我完全关闭链接它会完全编译,但它也产生一个巨大的二进制文件,不适合发布模式.

不幸的是,我需要的某个库以某种方式调用Expression.Visit,我无法弄清楚如何指示链接器不将其剥离.这会导致此编译错误:

错误MT2002:无法从"System.Core,Version = 2.0.5.0,Culture = neutral"解析"System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor :: Visit(System.Linq.Expressions.Expression)"引用,PublicKeyToken = 7cec85d7bea7798e"(MT2002)(MyApp)

根据自定义链接的文档,我设置了一个链接器文件来尝试阻止这种情况发生:

<?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>
Run Code Online (Sandbox Code Playgroud)

不幸的是,这没有任何影响 - 错误就像以前一样发生.

文档提到了preserve="fields"我可以提供的参数<type>,所以我尝试了:

<?xml version="1.0" encoding="UTF-8" ?>
<linker>
  <assembly fullname="System.Core">
    <type fullname="System.Linq.Expressions.ExpressionVisitor" preserve="methods" />
  </assembly>
</linker>
Run Code Online (Sandbox Code Playgroud)

那也行不通.

然后我在文件中引入了XML语法错误,并且构建失败,说它无法解析链接器文件,因此我至少知道正在读取该文件.

但后来我尝试在程序集名称中引入错误:

<?xml version="1.0" encoding="UTF-8" ?>
<linker>
  <assembly fullname="NonexistentAssembly">
  </assembly>
</linker>
Run Code Online (Sandbox Code Playgroud)

这引起了一个错误,抱怨组装无法解决.

然后我试图破坏类型名称:

<?xml version="1.0" encoding="UTF-8" ?>
<linker>
  <assembly fullname="System.Core">
    <type fullname="NonExistentType" preserve="methods" />
  </assembly>
</linker>
Run Code Online (Sandbox Code Playgroud)

现在,刚刚开始显示我之前看到的"无法解决表达式访问者::访问"错误.似乎没有检查类型名称.

此外,也不是签名名称,因为这也表示相同的编译错误.

<?xml version="1.0" encoding="UTF-8" ?>
<linker>
  <assembly fullname="System.Core">
    <type fullname="System.Linq.Expressions.ExpressionVisitor">
      <method signature="jg98j23890rj2390erk90fk3ew!]['##'#'[" />
    </type>
  </assembly>
</linker>
Run Code Online (Sandbox Code Playgroud)

所以看起来只要指定程序集名称并具有有效的XML结构,链接器文件就不会引发任何异常.虽然链接器文件的文档对于这样一个复杂的主题并不特别冗长,但包含许多语法错误,即:

<type fullname="Foo" preserve="fields" />
    <method name=".ctor" />
</type>
Run Code Online (Sandbox Code Playgroud)

此外,它没有提供链接器文件格式的技术说明,因此完全有可能我的定义完全错误.

我也尝试完全跳过System.Core的链接,--linkskip=System.Core但这没有效果.无论有没有,我都试过这个标志--xml.

在MvvmCross项目中,我尝试指定一个新类,以与LinkerPleaseInclude.cs文件相同的样式调用Visit方法,该文件由MvvmCross NuGet包添加到每个iOS项目中:

[Preserve]
public class PleaseIncludeVisitor : ExpressionVisitor
{
    public PleaseIncludeVisitor()
    {
        this.Visit(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这也没有效果.

我目前正在使用Mono 3.2.6((no/9b58377)和Xamarin.iOS v7.0.7.2.

pou*_*pou 6

主要问题是在iOS上运行时无法进行代码生成.

这意味着,有很大一部分System.Linq.Expressions 会,通常情况下,是不可能在正常情况下提供(就像System.Refection.Emit不能提供).

为了解决这个问题,Xamarin.iOS一直在提供一种替代实现(可以解释最常见的表达式).

但是,当前代码与.NET框架不是100%API兼容(已修复但尚未发布).例如

System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor::Visit(System.Linq.Expressions.Expression)

以上返回void当前的Xamarin.iOS(7.0.x)版本.这就是为什么链接器抱怨(它不是一个bug),因为它找不到这个成员引用(如果它找不到它就无法重新创建较小的,链接的程序集).无法保留不存在的成员(这就是您尝试使用XML文件或属性无效的原因).

在目前的解决办法是,以确认哪些组件使用这个API并重建(源文件)使用现有的System.Core.dll随机附带Xamarin.iOS.

笔记

我无法弄清楚如何指示链接器不将其剥离.

链接器不会尝试将其剥离它尝试保留它(即它必须加载引用才能将其保存回来).但是,它无法找到该成员,System.Core.dll因此无法提供有效的程序集链接版本.

<method signature="System.Linq.Expressions.Expression Visit(System.Linq.Expressions.Expression)" />
Run Code Online (Sandbox Code Playgroud)

这要求保留不存在的东西.它将被忽略,即当void发现-reurning版本时,它将与XML描述不匹配.