一、前言
NativeAOT是.NET7的新特性,可以将.NET代码编译成操作系统原生的应用程序或者类库运行,不依赖.NET运行环境。自从它面世以来在.NET圈子内一直颇受关注,跃跃欲试的人当中自然也包括了区区在下。观望了一年多,今天我终于出手,浅尝了一下传说中的.NET NativeAOT。
二、开发环境
开头必是搭建开发环境,准确来说应该是编译环境才算比较准确。因为NativeAOT有个臭脾气——不能跨平台编译。编译windows应用必须在windows环境下;编译linux应用必须在linux环境下;编译osx应用必须在mac环境下。否则,立马会给你脸色看:Cross-OS native compilation is not supported.
但,这难不倒在下,以上的操作系统俺都有!
1、MacOS
Mac是我的主力开发系统,Visual Studio For Mac早就是最新的Stable版本。因此,上手非常顺利。随便创建一个输出“Hello World”的.NET7控制台项目,然后,修改*.csproj文件,加上<PublishAot>true</PublishAot>
就完事了。编译也相当顺利,跑完一下脚本命令。
dotnet publish DemoAot.csproj -o $PWD/pub -c Release -r osx-x64
10秒钟后,一个大小8M的AOT应用程序就出炉了。测运行了一下,还真能跑出“Hello World”。
2、Linux
我的编译环境是Debian11的虚拟机,安装好.NET7 SDK后。同样跑了一下上面的脚本:
dotnet publish DemoAot.csproj -o $PWD/pub -c Release -r linux-x64
出现了报错,提示缺少了clang编译库。那么按照官方指示安装上
apt-get install clang zlib1g-dev
再跑发布脚本,出来了一个10M左右的执行文件。按照网上的办法给工程文件(*.csproj),加上`<StripSymbols>true</StripSymbols>可以裁剪发布文件的大小,对Linux比较有效。果然加上之后文件大小变成了3.77M。
3、Windows
windows环境下的编译发布,似乎比上述两个都要麻烦一些。首先,即使已经安装了Visual Studio 2022还不够,还要安装C++做面开发环境(对于大多数只写C#的开发者,一般这都不会装这个的)。
为了体验NativeAOT,我也只能重新打开VS的installer跑了4-5个小时,终于把这东西下载安装好了。然后,马不停蹄跑了一下发布脚本。很快,一个for windows的exe执行文件就被生成出来了,大小只有2.5M左右。比前面两个系统发布的文件都要小一些。
dotnet publish DemoAot.csproj -o pub\ -c Release -r win-x64
三、应用实战
上面用“Hello World”应用跑通了NativeAOT的编译环境,那么接下来,就要挑战一下复杂一些的应用,看看NativeAOT是否能够经得住实战的考验,可以成为技术开发的首选方案。
1、控制台应用
我们还是从控制台应用开始,当然接下来的肯定不是简单的输出“Hello World”这样的应用了,而是有使用功能的。
比如,这个StockMonitor,是很久之前用.NET Core3.1开发的一个小应用。主要功能是HttpClient抓取每日股票数据,整理发送到LeanCloud的对象存储服务中,然后从LeanCloud读取一段时间的数据进行分析,给出买入卖出建议。项目主要用到的库有这个几个:
- LeanCloud SDK(Common、Storage、Standard)
- Newtonsoft.Json
- System.Net
- System.Text.Encoding.CodePages
照例,我们把工程文件改造一番:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>latest</LangVersion>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<RuntimeIdentifiers>linux-x64</RuntimeIdentifiers>
<_IsPortable>true</_IsPortable>
<PublishAot>true</PublishAot>
<StripSymbols>true</StripSymbols>
</PropertyGroup>
然后脚本编译发布
dotnet publish StockMonitor.csproj -o $PWD/pub -c Release -r osx-x64
居然非常的顺利,应用发布成功了!没有改任何代码。那么,试一下能否执行吧。
./StockMonitor fetch sh000001
./StockMonitor fetch sh000001 Start StockMonitor... Run fetch-sh000001... 上 证 指 数 时 间 : 7/4/2023 12:05:00 PM
昨 收 : 3243.98 今 开 : 3241.23 当 前 : 3246.13 涨 幅 : 0.07%
太好了,也成功了!不过执行文件的Size涨到了67M,先不管它,肯定还是有办法做裁剪的。听说换成.NET8就可以将NativeAOT编译文件减半。
2、WebAPI
一系列的成功,让我对NativeAOT的信心瞬间膨胀了起来。下面开始挑战WebAPI应用,整个ASP.NET的Web框架都引入过来,会有奇迹发生吗?
- 创建一个简单的WebAPI项目,使用最简单的MiniAPI,做了一个API方法“weatherforecast”。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateTime.Now.AddDays(index),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
- 编译发布,也是成功的,exe执行文件大小25M。
- 双击打开运行,表面看起来是跑起来了。但是,打开浏览器访问API接口,报错便随之而来了。看起来是System.Text.Json序列化出了问题,试验宣告失败!
- 当然,还有改进的可能,譬如将Json库换成Newtonsoft.Json说不定能够迈过这个坑呢?等下次有机会再试一试吧。
四、总结
- NativeAOT是初衷非常好的,让C#语言可适用的疆界做了一次扩展以及重定义,虽然目前看来还有很多不成熟的地方。相信在将来.NET8、.NET9可能得到很好的解决,最终可以跟C++、Go、Rust这些原生应用领域的编译语言一较高下。
- 鉴于目前的NativeAOT使用的限制还是比较多的,因此能够开发的应用类型还是比较少的,因此开发一些小工具小应用能够胜任,但是并不建议企业商用项目使用,否者将会是个无底深坑。
- 让NativeAOT再飞一会吧!
参考资料
https://learn.microsoft.com/zh-cn/dotnet/core/deploying/native-aot/?tabs=net7
https://www.netnr.com/home/list/185