将.NET程序集编译为指定目标平台二进制文件

4
我已经寻找了一段时间,想找到一种编译指定目标平台的.NET程序集的方法。目标是将IL和整个程序集编译成独立于.NET运行时的可独立执行文件。
我阅读了很多关于为什么不能这样做的文章和评论,但我很好奇 - 有人能想出一些想法吗?
更新:微软宣布发布“.NET Native”预览版。请参见此处。 根据FAQ
引用: Q:链接是如何工作的?框架代码是否编译到应用程序中? A:是的,框架代码将被编译到应用程序中。
现在听起来很令人兴奋。不过,我对BuildDefinitions和自定义优化(目前使用VC++ opt.)还有点疑惑。

你的目标平台是什么?它是 mono 不支持的平台吗? - Bauhaus
@Bauhaus 好的,我们来说所有的吧 :) 包括 BuildDefinitions 和非 Windows 设备。 - Boyan
2
类似MonoTouch这样的一些Mono衍生产品是能够做到这一点的。你所需要的大部分代码已经在Mono AOT中了。 - SK-logic
1
我只使用过MonoTouch,从未在开源的Mono上做过同样的事情。您可以开始阅读http://www.mono-project.com/AOT(参见“Full AOT”),或尝试在此处召唤http://stackoverflow.com/users/16929/miguel-de-icaza。 - SK-logic
5个回答

3
如果你的.NET程序集能运行在Mono上,那么就可以使用Mono来生成一个可执行文件,而不需要最终用户安装.NET Framework或者Mono。实际上,有几个开发人员(包括我自己)正在这样做(主要针对*nix目标平台,但也可以在Windows上实现)。
首先需要注意的是,自Windows XP以来,.NET Framework 2.0已经作为Windows安装的一部分包含在内。如果您能够针对该框架进行开发,很少有Windows用户需要安装.NET Framework才能运行您的应用程序。如果可能的话,我会推荐您选择这种选项。
如果无法使用该框架,则可以使用Mono的mkbundle工具。mkbundle在所运行的平台上生成本地可执行文件。不幸的是,我没有关于在Windows上运行它的确切步骤;我只在Linux和Mac上使用过它。

我的意图是将其作为服务提供,运行在Linux上,这听起来对我来说很不错。不过我得试一下,因为我以前从未使用过mkbundle。 - Boyan
1
Windows 8 默认不启用 .NET 2.0、3.0 和 3.5。 - hyru

2

我不能发布评论(我的声望不足50点),但我是CodeRefractor的创建者,所以我想澄清一下这个项目:

  • 我认为与CodeRefractor相比,Mono和--full-aot标志是一个更好的目标,因为Mono在商业上得到支持,资源更多(即:开发人员在运行时的所有组件上工作)而且历史更悠久

  • CR是一个自由/业余项目,并且它将保持这样,因为我看不到很多除我之外的贡献者(实际上没有,除了评论:请添加这个,或者CR是否处理那个)。仅仅出于这个原因,我主要关注如何优化CIL操作码,而不是成为一个坚实的.Net实现。此外,我将把项目设计用作论文

  • 如果你需要处理非常数学密集型的代码并且想要分析C/C++生成的代码,则CodeRefractor可以帮助你,但实际的运行库非常有限。您可能需要编写自己的PInvoke库来流入和流出数据。说实话,这有点困难!

  • CR具有一些良好的性能默认值:如果代码遵循一些简单的规则,则性能很可能处于Java的服务器编译器或手动优化的C++范围内。其中的一个原因也是因为CR不检查循环的范围并且没有异常。所以,如果你运气好,效果会非常好!

  • CodeRefractor具有一些有趣的优化,至少在理论上是这样的。这意味着如果你真正尝试了解执行哪些优化,你可以获得非常好的性能。它与GCC编译器中的LTO非常相似,并且是多层次的优化,特别适用于使用常量的情况,包括死代码,都将被优化掉!

  • CodeRefractor的目标是通过提供(某种程度上)可读的C++代码来消除对.Net的依赖,该代码可以至少复制/粘贴到您的C++代码或根据需要进行调整。这也意味着始终会有一些边缘情况,即C++无法正确映射CIL代码的情况,例如在多线程领域(使用volatile)

所以最后的答案是:看看Mono和--full-aot标志。如果CodeRefractor对你有用那太棒了,但如果现在还不能使用我会感到非常惊讶!也许在3-4年后,如果人们支持它(或公司,谁知道呢),否则就像大多数人一样阅读博客。

如果您对CR的设计感兴趣,则可以从文档文件夹中阅读:

https://github.com/ciplogic/CodeRefractor/blob/master/Documentation/BarchelorPaper2014.docx

0

我一直在使用可移植类库(PCL),它们非常好用。基本上,它是 .Net 的一个子集,可以在多个设备上运行(它专门为此目的设计)。

您可以使用 Linq、async/await、lambdas 等,因此您可以使用 C# 的所有语法功能。

唯一的注意事项是许多 .Net 库不可用(例如加密),解决方法通常是在 Nuget 上找到 PCL 移植版本的库,或者自己复制一些 .Net 功能。 - 实际上,Microsoft 鼓励这种限制,因为他们声称您的 PCL 应该从其他库中使用依赖注入以启用缺失的功能。例如,您的 XBox 项目可能实现了在 PCL 中缺失的加密库,您的 PCL 项目应该被注入以在运行时使用 XBox 的类(通过接口等);稍后,您可以为 Android 做类似的事情,您的 Android 库将把加密库注入到 PCL 中,但 PCL 逻辑本身不需要更改,并且对于 XBox 和 Android 项目来说都是相同的。

这是关于它的更多信息http://msdn.microsoft.com/en-us/library/vstudio/gg597391(v=vs.110).aspx

-1

不错,但是参考程序集怎么办?你只能获取其中编译后的IL代码... - Boyan
这取决于你。作者指出,你需要为默认引用的 .net 程序集编写自定义包装器。 - Alecu
并不是我深入研究过,但我认为 Mono 的 mkbundle(正如 Smith 先生所建议的)是一个更好的想法。这种方法涉及太多额外的工作,包括一些反编译等。 - Boyan

-1

这是一个.NET应用程序,它将依赖于.NET运行时。它提供了以下几个方面:

  1. 大量的程序集在GAC中,每个.NET应用程序都会使用(例如System命名空间等)
  2. JIT编译器将IL转换为可执行代码。
  3. 注册表键和其他必需的系统修改。

将所有这些编译成单个应用程序并不实际、不可取或者不可能。你最好将.NET框架与你的应用程序一起打包并安装它(这是推荐的方法)。我相信你甚至需要安装mono(出于同样的原因)。

我知道你正在寻找另一种解决方案,但真正的答案是.NET不支持这种类型的编译。


是的,你所说的一切都有道理,我已经很清楚了。 这可能是个死胡同,但我希望能有一些聪明的方法来实际构建所有依赖项(希望如此)。 事实上,我将失去所有虚拟化,但我们假设这是可以接受的。 - Boyan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接