dotnet7 aot編譯實戰

原文地址:https://www.cnblogs.com/kewei/p/16722674.html

0 起因

這段日子看到dotnet7-rc1發布,我對NativeAot功能比較感興趣,如果aot成功,這意味了我們的dotnet程序在防破解的上直接指數級提高。我隨手使用asp.netcore-7.0模板創建了一個默認的web程序,發現aot發布出來,web服務完全使用,這是之前那些preview版本做不到的。想到fastgithub本質上也是基于asp.netcore-6.0框架的項目,于是走上fastgithub的aot改造之路。

1 改造步驟

1.1 升級框架

將所有項目的TargetFramework值改為7.0,fastgithub使用Directory.Build.props,所以我只需要在Directory.Build.props文件修改一個地方,所有項目生效了。

1.2 升級nuget包

所有項目的nuget包進行升級,像有些是6.0.x版本的,如果有7.0.x-rc.x.x的更新包,就升級到最新rc版本。

1.3 json序列化

如果您的使用JsonSerializer序列化了內部未公開的類型,則需要改為JsonSerializerContext(源代碼生成)方式,比如我在想序列化下面的EndPointItem類型的實例,需要如下改進:

private record EndPointItem(string Host, int Port);[JsonSerializable(typeof(EndPointItem[]))]
[JsonSourceGenerationOptions(WriteIndented = true,PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
private partial class EndPointItemsContext : JsonSerializerContext
{
}
var utf8Json = JsonSerializer.SerializeToUtf8Bytes(endPointItems, EndPointItemsContext.Default.EndPointItemArray);

2 aot發布

我發布在vs上進行發布時有問題,我們需要在使用cli來發布,cli發布還能為我們提供更多的編譯信息輸出。

2.1 單文件的發布命令

set output=./publish
if exist "%output%" rd /S /Q "%output%"
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained -r win-x64 -o "%output%/fastgithub_win-x64" ./FastGithub/FastGithub.csproj

aot編譯之后也是單個文件,所以如果您的程序使用PublishSingleFile模式發布不能正常運行的話,就不用試著aot發布了。

2.2 aot發布的命令

set output=./publish
if exist "%output%" rd /S /Q "%output%"
dotnet publish -c Release /p:PublishAot=true /p:PublishTrimmed=true --self-contained -r win-x64 -o "%output%/fastgithub_win-x64" ./FastGithub/FastGithub.csproj

我們只需要把之前的PublishSingleFile改為PublishAot,他們兩個不能同時設置為true。經過幾分鐘的滿屏黃色警告之后,我們終于得到aot版本的40MB左右的fastgtihub.exe,迫不及待地運行了fastgithub.exe,不幸的是程序運行異常:

Unhandled Exception: System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.---> System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.---> System.NotSupportedException: 'Org.BouncyCastle.Security.DigestUtilities+DigestAlgorithm[]' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibilityat System.Reflection.Runtime.General.TypeUnifier.WithVerifiedTypeHandle(RuntimeArrayTypeInfo, RuntimeTypeInfo) + 0x5bat System.Array.InternalCreate(RuntimeType, Int32, Int32*, Int32*) + 0x5cat System.Array.CreateInstance(Type, Int32) + 0x46at System.RuntimeType.GetEnumValues() + 0x86at Org.BouncyCastle.Utilities.Enums.GetArbitraryValue(Type enumType) + 0xaat Org.BouncyCastle.Security.DigestUtilities..cctor() + 0x86

2.3 嘗試解決BouncyCastle

BouncyCastle是用于生成ca證書和服務器證書的第三方庫,在dotnet6時或以前,我們沒有其它庫可以完成這個功能。以上的異常大概是提示了DigestUtilities這個類型的某個內部私有類型被裁剪了,所以無法創建這個已裁剪掉類型的數組類型。我想到可以給項目的ItemGroup加上<TrimmerRootAssembly Include="BouncyCastle.Crypto" />,讓這個程序集不要裁剪,然后再進行新一輪aot編譯,不幸的是這次是編譯時異常:

CVTRES : fatal error CVT1103: 無法讀取文件 [D:\github\FastGithub\FastGithub\FastGithub.csproj]
LINK : fatal error LNK1123: 轉換到 COFF 期間失敗: 文件無效或損壞 [D:\github\FastGithub\FastGithub\FastGithub.csproj]
C:\Program Files\dotnet\sdk\7.0.100-rc.1.22431.12\Sdks\Microsoft.DotNet.ILCompiler\build\Microsoft.NETCore.Native.targe
ts(349,5): error MSB3073: 命令“"C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.34.31721\bin\Hostx
64\x64\link.exe" @"obj\Release\net7.0\win-x64\native\link.rsp"”已退出,代碼為 1123。 [D:\github\FastGithub\FastGithub\FastGithu
b.csproj]

2.4 移除BouncyCastle

迫于無奈,我們必須移除對BouncyCastle的依賴,轉為使用基礎庫來實現證書生成,這方面幾乎沒有任何可以查到有幫助的資料,我花了整整一天來改造,感興趣證書生成的同學,可以參考CertGenerator.cs。去掉BouncyCastle之后再aot發布,程序可以運行起來了,沒有任何異常,但是發現程序沒有攔截任何流量。

2.5 查找程序不干活的原因

由于沒有任何的異常輸出,咱也不知道是啥情況,現在使用debug模式繼續aot發布,然后運行fastgithub.exe,在vs附加到fastgithub進程,下斷點分析。經過一路跟蹤,我發現如下一個分支,總是進入return邏輯:

var domain = question.Name;
if (this.fastGithubConfig.IsMatch(question.Name.ToString()) == false)
{return;
}

我想看看fastGithubConfig現在是什么值,為什么總是不匹配,但是經過aot之后,無法發現fastGithubConfig這個局部變量,而函數內的變量,也不再是crl類型,而是一種為調試而存在的代理類型一樣,可看的信息也很少。
于是我加入大量的log,通過log看看fastGithubConfig是什么值,最后發現是配置綁定到Options的字典類型屬性時,綁定不成功(但也沒有任何異常或日志)。

2.6 解決配置綁定到字典的問題

這個問題咱實在不知道怎么解決,那就github上發起問題吧:services.Configure(configuration) failure at PublishAot,果然回復很積極,告訴咱們目前可以在任意調用的函數加上[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Dictionary<string, DomainConfig>))]。經過這么修改之后,配置綁定到Options生效了。

3 后續

經過這么一個實際項目aot之后,我對aot有了初步的了解,個人覺得aot基本可以用小型程序的發布,期待到dotnet8之后,NativeAot變成沒有坑。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282495.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282495.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282495.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

實現ModelDriver接口的功能(轉)

ModelDriver接口 來自com.opensymphony.xwork2.ModelDriven。是xwork-2.1.2-750.jar包的東西。 下面是源碼&#xff1a; package com.opensymphony.xwork2; public abstract interface ModelDriven<T> { public abstract T getModel(); } 該接口只有一個getModel()方法…

Git的使用(推薦命令行模式)

一 使用 git版本控制已經逐漸取代cvs,svn等版本控制,對于一名程序員來說,使用git同樣是一門必備的功課.1. 倉庫初始化查看文件.如果有.git文件夾,說明創建本地倉庫成功(.git是隱藏文件夾)2. 修改用戶名和郵箱本地配置:注: 在全局配置與本地配置都存在用戶名時,本地配置優先級更…

.NET MAUI 環境配置技巧

關于 .NET MAUI 國內?伙伴在配置 .NET MAUI 的時候&#xff0c;遇到不少問題。希望通過本教程&#xff0c;給到大家?些指引。01基礎組件部分.NET SDK 安裝建議安裝最新的 .NET SDK下載地址 https://dotnet.microsoft.com/download/dotnet/6.0安裝 .NET MAUI安裝 .NET MAUI 成…

Linux中一些常用的很巧妙的命令

當你想要使用上一個命令的最后一個參數&#xff0c;&#xff08;上一個命令的最后一個參數很長&#xff09;&#xff0c;可以使用 esc .      (是esc 點&#xff09; !$ 引用上一個命令的最后一個參數 對命令行的編輯快捷方式&#xff1a; Ctr…

android 8種對話框(Dialog)使用方法匯總

本文為作者原創&#xff0c;轉載請注明出處&#xff1a;http://www.cnblogs.com/gzdaijie/p/5222191.html 目錄 1.寫在前面2.代碼示例2.1 普通Dialog&#xff08;圖1與圖2&#xff09;2.2 列表Dialog&#xff08;圖3&#xff09;2.3 單選Dialog&#xff08;圖4&#xff09;2.4 …

使用layui的layer組件做彈出層

官方文檔地址: http://www.layui.com/doc/modules/layer.html 本例演示效果: 當點擊申請提現時,出現申請提現框,并根據用戶輸入進行一些判斷,給出友好提示,比如: 代碼實現: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&q…

C#之表達式樹使用

目的遇到一個場景需要接收一個表的列來進行動態排序&#xff0c;比如我想根據CreateTime進行正序排序&#xff0c;加上我使用的ORM框架是EFCore&#xff0c;那么我一下子就想到應該使用OrderBy&#xff0c;然后接收一個要排序的列query.OrderBy("CreateTime")但是這樣…

實現一個基于相等性比較的 GroupBy

實現一個基于相等性比較的 GroupByIntro在我們的系統里有些數據可能會有問題&#xff0c;數據源頭不在我們這里&#xff0c;數據不好修復&#xff0c;在做 GroupBy 的時候就會很痛苦&#xff0c;默認的 group by 會依賴于 HashCode &#xff0c;而某些場景下 HashCode 可能并不…

win7系統下載 ghost win7 Sp1 64位純凈3月版

win7系統下載 ghost win7 Sp1 64位純凈3月版 軟件名稱: Ghost Win7 Sp1 64位純凈3月版軟件語言: 簡體中文軟件大小: 5.25大小: GB發布日期: 2017-03-21文件名稱: ZJY_Ghost_win 7_X64_CJ201703.GHOM D 5: EB16DCD608A5CCFE34B58…

CrossPHP框架的常用操作

1. 在視圖控制器中使用$this->res()方法來生成資源文件的絕對路徑$this->res(css/style.css);生成的連接為http://youdomain.com/static/css/style.css2. 生成指定app名稱的連接$this->appUrl()第一個參數為基礎url, 第二個參數為app名稱, 第三個參數為 控制器:方法 第…

WPF-07 Style之觸發器

觸發器能夠在改變屬性值的時候&#xff0c;根據值變化執行操作&#xff0c;在不需要創建一個新的控件的情況下&#xff0c;可以動態的改變控件的外觀&#xff0c;當條件滿足時&#xff0c;觸發器可以改變任何屬性的值&#xff0c;觸發器通常定義在Style中&#xff0c;在窗體的根…

jdk自帶常用命令行工具使用

轉自&#xff1a;http://blog.csdn.net/winwill2012/article/details/46364923jps命令使用jps命令類似于Linux下的ps命令&#xff0c;用于列出當前正在運行的所有Java進程。基本用法直接運行不加任何參數就能列出所有java進程的pid和類的短名稱。例如&#xff1a;常用參數-q參數…

crossphp框架中,在模板中加載其他模板

這里說我自己做的項目的應用場景 要求是用layui框架的layer組件,實現彈出層效果,用原聲PHP無疑很容易做到,但是如果應用到crossphp框架流程就會非常麻煩 這里簡單講一下大致的步驟: 1. 在一個模板文件中應用layui的layer組件實現彈出框 index.tpl.php2. 從我們自己定義的路徑上…

for(auto c:s)與for(auto c:s)

在c11標準下可以執行的特殊格式的for循環語句&#xff0c;區別在于引用類型可以改變原來的值 #include<iostream> using namespace std; int main() {string s("hello world");for(auto c:s)ct;cout<<s<<endl;//結果為hello worldfor(auto &c:…

MASA Framework的MinimalAPIs應用

在以前的MVC引用程序中&#xff0c;控制器是一個功能齊全的框架&#xff0c;但它偏重&#xff0c;因此在.Net6.0官方引入了MinimalAPIs&#xff0c;即最小API&#xff0c;與MVC相比&#xff0c;它足夠的簡潔&#xff0c;適合小型服務來使用&#xff0c;下面就讓我們看看如何使用…

【轉】Java開發必須要知道的知識體系

Java Java是一門超高人氣編程語言&#xff0c;擁有跨平臺、面向對象、泛型編程等特性。在TIOBE編程語言排行榜中&#xff0c;連續奪得第一寶座&#xff0c;而且國內各大知名互聯網公司&#xff0c;后端開發首選語言&#xff1a;非Java莫屬。今天只是梳理下Java知識體系&#xf…

CrossPHP--在我們用ajax,js取不到指定數據時,我們可以換一種方式

項目中遇到的問題: 需求: 用的是layui的laypage組件,進行分頁操作,熟悉layui的朋友都知道,laypage需要從服務端給其一個總條數, 但是在進行ajax請求時出了問題, 我是這樣定義的但是調用的時候卻無法將數值直接返回回去,所以這里只能更換一種思路 在控制器中進行數據的查詢,然后…

VS 代碼行數統計

按CTRLSHIFTF (Find in files)&#xff0c;勾上支持正則表達式&#xff0c;然后輸入搜索內容&#xff1a; ^:b*[^:b#/].*$#開頭和/開頭或者空行都不計入代碼量。如果需要只統計代碼文件的代轉載于:https://www.cnblogs.com/sunlyk/p/7484728.html

MySQL設置從庫只讀模式

常見現象 運維工作中會經常維護MySQL主從服務器&#xff0c;當然Slave我們只是用于讀操作。 一般權限開通也只授權只讀賬號&#xff0c;但是有時候維護工作可能不是一個人在做&#xff0c;你不能保證其他同事都按照這個標準操作。 有同事可能會授權Slave庫MySQL賬號為all或者se…

尋找kernel32.dll的地址

為了尋找kernel32.dll的地址&#xff0c;可以直接輸出&#xff0c;也可以通過TEB,PEB等查找。 尋找TEB: dt _TEB nt!_TEB 0x000 NtTib : _NT_TIB 0x01c EnvironmentPointer : Ptr32 Void 0x020 ClientId : _CLIENT_ID 0x028 ActiveRpcHandle : Ptr32 Void 0x02c ThreadLocalSto…