我正在尝试在 Link SDK only 模式下使用 MonoTouch 编译我的 iOS 应用程序。如果我完全关闭链接,它编译完全正常,但它也会产生一个不适合 Release模式的巨大二进制文件。
不幸的是,我需要的库之一以某种方式调用 Expression.Visit,我不知道如何指示链接器不要将其删除。这导致此编译错误:
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)
根据 the documentation on custom linking ,我已经设置了一个链接器文件来尝试阻止这种情况发生:
<?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>
不幸的是,这没有任何影响 - 错误就像以前一样发生。
文档中提到了
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>
那也没有用。
然后我在文件中引入了一个 XML 语法错误,构建失败,说它无法解析链接器文件,所以我至少知道文件正在被读取。
但后来我尝试在程序集名称中引入错误:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="NonexistentAssembly">
</assembly>
</linker>
这导致了错误,提示无法解决程序集。
然后我尝试修改类型名称:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="NonExistentType" preserve="methods" />
</assembly>
</linker>
现在,它刚刚开始显示我之前看到的相同的“无法解析 expressionvisitor::visit”错误。似乎没有检查类型名称。
此外,签名名称也不是,因为这也出现了相同的编译错误。
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor">
<method signature="jg98j23890rj2390erk90fk3ew!]['##'#'[" />
</type>
</assembly>
</linker>
所以看起来只要指定程序集名称并具有有效的 XML 结构,链接器文件就不会导致抛出任何异常。不过,链接器文件的文档对于如此复杂的主题并不是特别冗长,并且包含许多语法错误,即:
<type fullname="Foo" preserve="fields" />
<method name=".ctor" />
</type>
此外,它没有给出链接器文件格式的技术描述,所以我的定义完全有可能是完全错误的。
我也尝试过完全跳过 System.Core 与
--linkskip=System.Core
的链接。但这没有效果。我在有和没有 --xml
的情况下都试过这个标志.在 MvvmCross 项目中,我尝试指定一个新类来以与 LinkerPleaseInclude.cs 文件相同的样式调用 Visit 方法,该文件由 MvvmCross NuGet 包添加到每个 iOS 项目中:
[Preserve]
public class PleaseIncludeVisitor : ExpressionVisitor
{
public PleaseIncludeVisitor()
{
this.Visit(null);
}
}
不幸的是,这也没有效果。
我目前正在使用 Mono 3.2.6 ((no/9b58377) 和 Xamarin.iOS v7.0.7.2。
最佳答案
主要问题是在 iOS 上无法在运行时生成代码。
这意味着System.Linq.Expressions
的很大一部分通常,在正常情况下是不可能提供的(就像 System.Refection.Emit
不能提供一样)。
为了解决此问题,Xamarin.iOS 提供了一种替代实现(可以解释最常见的表达式)。
但是,当前的代码不是 100% 与 .NET 框架兼容的 API(已修复但尚未发布)。例如。System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor::Visit(System.Linq.Expressions.Expression)
以上返回 void
在当前的 Xamarin.iOS (7.0.x) 版本中。这就是为什么链接器会提示(这不是错误),因为它找不到此成员引用(如果找不到,则无法重新创建较小的链接程序集)。无法保留不存在的成员(这就是您尝试使用 XML 文件或属性无济于事的原因)。
当前的解决方法是确定您的哪个程序集正在使用此 API 并重建它(从源代码)以使用现有的 System.Core.dll
随 Xamarin.iOS 一起提供。
备注
I can't figure out how to instruct the linker to not strip it out.
链接器不会尝试将其剥离,而是尝试将其保留(即它必须加载引用才能将其保存回来)。但是它在
System.Core.dll
中找不到该成员使得无法提供 有效 程序集的链接版本。<method signature="System.Linq.Expressions.Expression Visit(System.Linq.Expressions.Expression)" />
那就是要求保留一些不存在的东西。它将被忽略,即当
void
- 发现返回版本与 XML 描述不匹配。
关于xamarin.ios - Xamarin/MonoTouch : Unable to compile in "Link SDK only" mode due to missing symbols,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22066893/