.NET Core单文件发布静态编译AOT CoreRT的方法详解

前言

本文主要介绍的是关于.NET Core单文件发布静态编译AOT CoreRT,将.NET Core应用打包成一个可执行文件并包含运行时。

支持Windows, MacOS and Linux x64 w/ RyuJIT codegen。

示例项目:

https://github.com/dotnet/corert/tree/master/samples/WebApi

下面来实际体验。

首先确保安装C++编译环境,以及.NET Core 2.0 以上版本SDK。

新建WebAPI应用

打开命令提示符,输入如下:

dotnet new webapi -o zeroapi

cd zeroapi

新建WebAPI应用。

添加CoreRT到项目

目前CoreRT还是alpha版,在myget上有包。

首先添加一个nuget.config

dotnet new nuget

然后在 <packageSources> 节点添加如下:

<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />

接着添加Microsoft.DotNet.ILCompiler包引用:

dotnet add package Microsoft.DotNet.ILCompiler -v 1.0.0-alpha-*

替换默认services并处理反射

打开Startup.cs ,将 services.AddMvc(); 替换成 services.AddMvcCore().AddJsonFormatters();

接着创建一个rd.xml 配置文件,用于反射处理运行时,确保反射程序集编译到程序中。

rd.xml配置文件如下:

<Directives>
 <Application>
 <Assembly Name="zeroapi" Dynamic="Required All" />
 <Assembly Name="Microsoft.AspNetCore.Server.Kestrel.Core">
  <Type Name="Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Server.Kestrel.Core.Internal.KestrelServerOptionsSetup" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Server.Kestrel" Dynamic="Required All"/>
 <Assembly Name="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv">
  <Type Name="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.LibuvTransportFactory" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.LibuvTransportOptions" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.DependencyInjection" Dynamic="Required All">
  <Type Name="Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteExpressionBuilder" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Options">
  <Type Name="Microsoft.Extensions.Options.OptionsManager`1[[Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions,Microsoft.AspNetCore.Server.Kestrel.Core]]" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.Options.OptionsFactory`1[[Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions,Microsoft.AspNetCore.Server.Kestrel.Core]]" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.Options.OptionsMonitor`1[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions,Microsoft.Extensions.Logging.Console]]" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Mvc.Core" Dynamic="Required All" />
 <Assembly Name="Microsoft.AspNetCore.Routing">
  <Type Name="Microsoft.AspNetCore.Routing.Internal.RoutingMarkerService" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Builder.RouterMiddleware" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Routing.DefaultInlineConstraintResolver" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Routing.RouteOptions" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Mvc.Formatters.Json">
  <Type Name="Microsoft.AspNetCore.Mvc.Formatters.Json.Internal.MvcJsonMvcOptionsSetup" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Mvc.MvcJsonOptions" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Authorization">
  <Type Name="Microsoft.AspNetCore.Authorization.DefaultAuthorizationPolicyProvider" Dynamic="Required All" />
  <Type Name="Microsoft.AspNetCore.Authorization.AuthorizationOptions" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Http">
  <Type Name="Microsoft.AspNetCore.Http.HttpContextFactory" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.AspNetCore.Hosting" Dynamic="Required All">
  <Type Name="Microsoft.AspNetCore.Hosting.Internal.ApplicationLifetime" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Logging.Abstractions">
  <Type Name="Microsoft.Extensions.Logging.Logger`1[[Microsoft.AspNetCore.Hosting.Internal.WebHost,Microsoft.AspNetCore.Hosting]]" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Logging">
  <Type Name="Microsoft.Extensions.Logging.LoggerFactory" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Logging.Console">
  <Type Name="Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Logging.Debug">
  <Type Name="Microsoft.Extensions.Logging.Debug.DebugLogger" Dynamic="Required All" />
  <Type Name="Microsoft.Extensions.Logging.Debug.DebugLoggerProvider" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="System.Linq.Expressions">
  <Type Name="System.Linq.Expressions.ExpressionCreator`1[[Newtonsoft.Json.Serialization.ObjectConstructor`1[[System.Object,System.Private.CoreLib]],Newtonsoft.Json]]" Dynamic="Required All" />
  <Type Name="System.Linq.Expressions.ExpressionCreator`1[[System.Func`2[[System.Object,System.Private.CoreLib],[System.Object,System.Private.CoreLib]],System.Private.CoreLib]]" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.ObjectPool">
  <Type Name="Microsoft.Extensions.ObjectPool.DefaultObjectPoolProvider" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Newtonsoft.Json">
  <Type Name="Newtonsoft.Json.Serialization.ObjectConstructor`1[[System.Object,System.Private.CoreLib]]" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="System.ComponentModel.TypeConverter">
  <Type Name="System.ComponentModel.TypeConverter" Dynamic="Required All" />
  <Type Name="System.ComponentModel.StringConverter" Dynamic="Required All" />
  <Type Name="System.ComponentModel.Int32Converter" Dynamic="Required All" />
 </Assembly>
 <Assembly Name="Microsoft.Extensions.Configuration.Json">
  <Type Name="Microsoft.Extensions.Configuration.Json.JsonConfigurationSource" Dynamic="Required All" />
 </Assembly>
 </Application>
</Directives>

其中如果你要替换成自己的程序,更改 <Assembly Name="zeroapi" Dynamic="Required All" /> 中的Name。

打开zeroapi.csproj

<PropertyGroup>节点下将 <RdXmlFile>rd.xml</RdXmlFile> 加入。

接着将 <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" /> 替换成如下:

<PackageReference Include="Microsoft.AspNetCore" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.0.1" />

接着将 ValuesController 更改一下,确保功能正常,如下:

public class ValuesController
 {
 [HttpGet("/")]
 public string Hello() => "Hello World! LineZero AOT";
 // GET api/values
 [HttpGet("/api/values")]
 public IEnumerable<string> Get()
 {
  return new string[] { "AOT", "CoreRT" };
 }
 // GET api/values/5
 [HttpGet("/api/values/{id}")]
 public string Get(int id)
 {
  return "Your value is " + id;
 }
 }

程序改造完成,接着最重要的发布。

还原并发布

发布之前,使用dotnet run 确保功能正常运行。

发布请打开 x64 Native Tools Command Prompt for VS 2017 ,注意一定在此命令行发布。在开始菜单找到 Visual Studio 2017,打开就能找到。

发布命令还是  dotnet publish -r <RID> -c <Configuration>

这里发布Windows 64位 dotnet publish -r win-x64 -c release,初次的话会默认还原对应的包,需要一些时间。

发布完成后,打开bin\x64\release\netcoreapp2.0\win-x64\publish 文件夹,里面zeroapi.exe即为最终文件,执行即可。

可以看到最终大小为21m左右。然后访问http://localhost:5000/ 如图:

控制台Demo

新建一个控制台应用,使用AOT发布。

单纯控制台,没有反射的内容,无需要rd.xml 文件。

代码如下:

class Program
 {
 static void Main(string[] args)
 {
  Console.WriteLine("Hello World!");
  Console.WriteLine("LineZero AOT Demo!");
  Console.ReadKey();
 }
 }

最终 dotnet publish -r win-x64 -c release 发布

最终单个文件大小不到4m!

目前该技术还是早期版本,期待微软最终带到正式版。

GitHub:https://github.com/dotnet/corert

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • ASP.NET Core静态文件使用教程(9)

    在这一章,我们将学习如何使用文件.几乎每个web应用程序都需要一个重要特性:能够从文件系统提供文件(静态文件). 静态文件像JavaScript文件.图片.CSS文件等,我们Asp.Net Core应用程序可以直接提供给客户. 静态文件通常位于web根(wwwroot)文件夹. 默认情况下,这是我们可以直接从文件系统提供文件的唯一的地方.  案例 现在让我们通过一个简单的示例来了解我们在我们的应用程序如何提供这些静态文件. 在这里,我们想要向我们的 FirstAppDemo 应用程序添加一个简单

  • 解析如何利用一个ASP.NET Core应用来发布静态文件

    虽然ASP.NET Core是一款"动态"的Web服务端框架,但是在很多情况下都需要处理针对静态文件的请求,最为常见的就是这对JavaScript脚本文件.CSS样式文件和图片文件的请求.针对不同格式的静态文件请求的处理,ASP.NET Core为我们提供了三个中间件,它们将是本系列文章论述的重点.不过在针对对它们展开介绍之前,我们照理通过一些简单的实例来体验一下如何在一个ASP.NET Core应用中发布静态文件. 目录 一.以Web的形式读取文件 二.浏览目录内容 三.显示默认页面

  • c# .Net Core静态文件服务器的新人入门教程

    概要: 本文通过示例,讲解了 NET Core2.0 静态文件目录的相关知识,并附带解析,适合新手,并附带了完整的项目代码.(项目通过 vs2017 初始化的 ASP.NET Core 应用程序,之后选择***空项目***) 示例代码 项目结构 program.cs文件 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks;

  • .NET Core单文件发布静态编译AOT CoreRT的方法详解

    前言 本文主要介绍的是关于.NET Core单文件发布静态编译AOT CoreRT,将.NET Core应用打包成一个可执行文件并包含运行时. 支持Windows, MacOS and Linux x64 w/ RyuJIT codegen. 示例项目: https://github.com/dotnet/corert/tree/master/samples/WebApi 下面来实际体验. 首先确保安装C++编译环境,以及.NET Core 2.0 以上版本SDK. 新建WebAPI应用 打开命

  • Golang实现文件夹的创建与删除的方法详解

    目录 创建文件夹 删除文件和文件夹 小结 学习笔记,写到哪是哪. 接着上一篇对纯文本文件读写操作,主要去实现一些文件夹操作. 创建文件夹 创建文件夹的时候往往要先判断文件夹是否存在. 样例代码如下 package main import ( "bufio" "fmt" "io" "os" ) //判断文件夹是否存在 func HasDir(path string) (bool, error) { _, _err := os.S

  • 解决.net framework 4.0环境下遇到版本不同编译不通过的方法详解

    本文内容:1.问题引出2.问题解决3.原因分析 最近部门的开发环境都更新到了WIN7+.NET framework4+VS2010上,在体验新技术和新环境带给我们提高效率的方式方法的同时也带来了一些兼容性的问题:这几天项目闲暇时在研究SQLite,在做实验的时候碰到个问题,代码编译通过执行时反复异常中断,查到后面原来是SQLite.dll是在framework2.0环境下编译的而现在的运行环境是framework4.0,所以就出现了运行异常,如图: 由于以后的开发过程中,可能会引用一些第三方的组

  • ASP.NET Core中调整HTTP请求大小的几种方法详解

    一.前言 之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET Core应用的很多特性,比如路由.认证.会话.缓存等,也同时定制消息处理管道来实现的.我们甚至可以通过管道定制在ASP.NET Core平台上创建我们自己的Web框架,实际上MVC和SingalR这两个重要的Web框架也是采用这样的方式创建的. HTTP协议自身的特性决定了任何一个Web应用的工作方式都是监听.接收

  • ASP.NET Core单文件和多文件上传并保存到服务端的方法

    前言: 在我们日常开发中,关于图片,视频,音频,文档等相关文件上传并保存到服务端中是非常常见的一个功能,今天主要是把自己在开发中常用的两种方式记录下来方便一下直接使用,并且希望能够帮助到有需要的同学! 一.配置ASP.NET Core中的静态文件: 简单概述: 在ASP.NET Core应用中静态资源文件需要进行相应的配置才能够提供给客户端直接使用. 详情描述请参考官方文档: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/st

  • Linux静态库与动态库实例详解

    Linux静态库与动态库实例详解 1. Linux 下静态链接库编译与使用 首先编写如下代码: // main.c #include "test.h" int main(){ test(); return 0; } // test.h #include<iostream> using namespace std; void test(); // test.c #include "test.h" void test(){ cout<< &quo

  • 基于Java class对象说明、Java 静态变量声明和赋值说明(详解)

    先看下JDK中的说明: java.lang.Object java.lang.Class<T> Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class tha

  • c++中的单例类模板的实现方法详解

     1.什么是单例模式 在架构设计时,某些类在整个系统生命周期中最多只能有一个对象存在 ( Single Instance ).如超市收银系统,其外观主要由显示器(1个).扫描枪(1个).收款箱(1个)组成,在系统正常运行期间这三部分都是唯一存在的:也就是说,显示器.扫描枪.收款箱这三部分都应该有各自的类,并且每个类只能唯一地实例化一个对象,基于这种模式的程序设计,称为单例模式. !!!单例模式只能创建一个对象,且该对象的生命周期伴随系统的整个运行期间. 2.怎么实现单例模式 思考:如何定义一个类

  • JSP静态导入与动态导入使用详解

    JSP静态导入(JSP指令标记include) JSP页面第一次被请求时,会被JSP引擎转译成Servlet的Java文件,然后再被编译成字节码文件执行.JSP指令标记为JSP页面转译提供整个页面的相关信息. include指令用于在JSP页面静态插入一个文件,被插入的文件可以是JSP页面.HTML页面.文本文件或一段Java代码.使用了include指令的JSP页面在转换成Java文件时,将被插入的文件在当前JSP页面出来该指令的位置做整体的插入,合并成一个新的JSP页面,然后JSP引擎再将这

随机推荐