视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
.NET Core单文件发布静态编译AOT CoreRT的方法详解
2020-11-27 22:35:03 责编:小采
文档


前言

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

支持Windows, MacOS and Linux x 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 确保功能正常运行。

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

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

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

发布完成后,打开bin\x\release\netcoreapp2.0\win-x\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-x -c release 发布

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

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

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

总结

下载本文
显示全文
专题