[WIP] .NET MAUI で Linux 向けにビルドしたい!
.NET MAUI とは
.NET MAUI は C# と XAML により GUI クロスプラットフォームアプリケーションを開発できるフレームワークです。
Linux 版
しかし、登場した当時は Linux 版はコミュニティーによる開発扱いで、現在はもはや Linux の存在は公式ドキュメントから削除されています。
現在のコミュニティーによる開発は、ほとんど停滞しており、その開発の情報はほとんど存在しません。
この資料の目的
この資料は .NET MAUI を Linux でなんとか利用できないか試み、情報をある程度まとめたものです。
参考になるページ
リポジトリ
-
dotnet/maui (本家)
-
jsuarezruiz/maui-linux (MAUI Linux のすべてが集まっているフォーク)
- Iytico/maui (MAUI Linux のメインの開発者のフォーク)
- nblockchain/Mali (MAUI のフォーク)
-
jsuarezruiz/maui-linux (MAUI Linux のすべてが集まっているフォーク)
下2つは、#66などで maui-linux にマージしています。このリポジトリの保持者である jsuarezruiz さんも今はあんまり MAUI Linux の開発に関与していないようです。
コミュニティー
本家の wiki でも強い要望があるにも関わらず、MS やコミュニティーによる開発はあまり進んでいません。(というか、興味がある人は多いけど、開発資料が少なすぎて途中参入が難しいんだとおもう)
(まじで情報がない)
ビルドとかの方針
これは指針であり、まだ成功はしていません。
A 案
Windows や macOS 上でのビルドと同様に行う (多分無理)
-> Linux 上では maui-android
以外使えないので、ビルドエラーが大量に出る
B 案
CI/CD を参考にする
-> gtk
のワークロードがインストールできない
C 案
CI/CD をそのまま動かす (一番希望がある)
-> GitHub Actions をローカルで動かせる act
でできるかも (現状若干エラーが出てるけど頑張れば行けるか?)
-> B 案と同じで、gtk
のワークロードのインストールができない
D 案
自作する (無理)
-> Qt (Qt.NET (古い)) で作るとか (ライセンス的 (GPL/LGPL) に微妙な気がする)
結論
とりあえず C 案で進めます。B 案でもほぼ同じな気がしますが… (資料作るときは B 案のほうが act
とか入れなくてもいいので、簡単になりそう)
雑に URL を貼る
- ビルドエラー
- maui-gtk の example (あんまり参考にならない)
- ビルド方法?
- 一番の情報源 (開発者情報)
- Development (A 案で試したやつ) + これ
- コンパイル方法 (CI/CD のまま。CI/CD は動いているっぽいけど、ローカルでやっても動かない謎 (B 案/C 案))
- Mali の CI/CD
- act
CI/CD はバージョンがかなり古いので、すべて v4 に上げるのを推奨するよ
ぶっちゃけ、あと gtk
のワークロードさえインストールできれば動きそうな雰囲気ある
あと、多分これ (GTK ランタイム) は必要かも
sudo apt install libgtk-3-dev
sudo apt install libgtk-3-0
一応 act
の使い方をちょっと書いておく
-
gh
(GitHub CLI) をインストール
# 参考: https://github.com/cli/cli/blob/trunk/docs/install_linux.md
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
-
act
をインストール
# 参考: https://nektosact.com/installation/gh.html
gh extension install https://github.com/nektos/gh-act
- Docker をインストール (よくわからないけど apt で全部入れた (?) 多分
docker.io
があればいいのかな?) - Docker 起動
sudo systemctl start docker
- ユーザーを
docker
グループに追加 (docker はスーパーユーザーが必要)
sudo usermod -aG docker $USER
newgrp docker # 変更を適応
- リポジトリをクローンして、その中に移動する
git clone <リポジトリの URL>
cd <クローンしたディレクトリ>
- 動かす
# 場所は、リポジトリのルートで実行 (ルートじゃなくても動くかも?)
gh act push
# または gh act pull_request かな?
ビルドできたら DLL 参照で動くと思う
# 参考: https://github.com/HavenDV/Gtk
curl -sSL https://raw.githubusercontent.com/HavenDV/Gtk/main/scripts/workload-install.sh | sudo bash
これやって、0.2.0はありません的なエラーが出たから、他の方法を試した。
(インストールできてないから dotnet workload list
には入らないけど、dotnet workload search
には入る)
# 参考: https://matrix.to/#/!secXICyMCTWkttVBVC:matrix.org/$uX3kcJ_AITkkFvqne3wkFJUL4_77o_FpfpGos6RphzI?via=matrix.org
git clone https://github.com/GtkSharp/GtkSharp.git
cd GtkSharp
sudo dotnet tool restore
sudo dotnet cake --BuildTarget=InstallWorkload
これやって、
# (これは元からインストールしてたっぽいから関係ない気がするけど)
sudo apt-get install libgtk-3-0
これやった後に、もう一度 sudo dotnet workload install gtk
したら、なぜかインストールできた
$ dotnet workload list
インストール済みワークロードの ID マニフェストのバージョン インストール ソース
-------------------------------------------------------
gtk 0.2.0/8.0.400 SDK 8.0.400
maui-android 8.0.82/8.0.100 SDK 8.0.400
wasi-experimental 8.0.8/8.0.100 SDK 8.0.400
`dotnet workload search` を使用して追加ワークロードを検出し、インストールします。
(なんか gtk
が入った後も、結構苦難している)
Mali は ZXing をビルドしてるっぽい (https://github.com/nblockchain/Mali/blob/master/.github/workflows/build-gtk.yml)
maui-linux は本体のビルド?
(https://github.com/jsuarezruiz/maui-linux/blob/main/.github/workflows/build-gtk.yml)
これ: https://github.com/lytico/maui/blob/6ef7f0c066808ea0d4142812ef4d956245e6a711/.github/workflows/build-gtk.yml#L22-L31
をやった後に Maui.Controls.Sample
(https://github.com/jsuarezruiz/maui-linux/pull/66 で利用されているサンプルプログラム) をビルドすると、Gtk あたりのエラーになる。
多分、これを解決すれば GUI が起動できる気がする。
色んな方法を試しすぎてて、再現性が低くなりそう (あとでちゃんとした資料を書くつもり (これが本来の目的だし))
そもそも VSCode で動作させたことがある人が過去に1人もいないかも
(メイン開発者たちは VS 使ってる (WSL かな?))
# 参考: https://github.com/jsuarezruiz/maui-linux/issues/92#issuecomment-2311842074
dotnet cake --target=dotnet-pack --workloads=global --gtk
dotnet new install ./artifacts/*.nupkg
を試して、
# (Nuget.config)
- <!-- <add key="local" value="artifacts" /> -->
+ <add key="local" value="artifacts" />
にした。
この後にビルドをすると、Gtk あたりのエラーは解消されたっぽい。
だけど、次のエラーが発生した。
System.Text.Json 8.0.0 が致命的な脆弱性があるというエラーが発生するので、バージョンを上げる。
# $(MicrosoftNETCoreAppRefPackageVersion) は8.0.0になってる
- <SystemTextJsonPackageVersion>$(MicrosoftNETCoreAppRefPackageVersion)</SystemTextJsonPackageVersion>
+ <SystemTextJsonPackageVersion>8.0.4</SystemTextJsonPackageVersion>
ついでに、ビルドターゲットの出力形式を変更する
- <!-- <OutputType Condition="$(TargetFramework.Contains('-'))">Exe</OutputType> -->
+ <OutputType>Exe</OutputType>
規定に関しても設定しなきゃいけないらしい
{
"profiles": {
"Windows Machine": {
"commandName": "MsixPackage",
"nativeDebugging": true
+ },
+ "Linux Machne": {
+ "commandName": "Project",
+ "nativeDebugging": true
}
}
}
あと、Main()
が必要らしい (Windows とかは /Platforms/Windows/App.xaml.cs
とかを参照にしてるっぽい)
public static void Main()
{
CreateMauiApp();
}
dotnet run --project src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj --framework net8.0
まだエラーは続く…
Unhandled exception. Microsoft.Maui.ApplicationModel.NotImplementedInReferenceAssemblyException: This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.
at Microsoft.Maui.ApplicationModel.AppInfoImplementation.get_PackagingModel() in /home/lemon73/Downloads/maui-linux/src/Essentials/src/AppInfo/AppInfo.netstandard.cs:line 19
at Microsoft.Maui.ApplicationModel.AppInfo.get_PackagingModel() in /home/lemon73/Downloads/maui-linux/src/Essentials/src/AppInfo/AppInfo.shared.cs:line 106
at Maui.Controls.Sample.MauiProgram.<>c.<CreateMauiApp>b__4_3(IEssentialsBuilder essentials) in /home/lemon73/Downloads/maui-linux/src/Controls/samples/Controls.Sample/MauiProgram.cs:line 191
at Microsoft.Maui.Hosting.EssentialsExtensions.EssentialsRegistration.RegisterEssentialsOptions(IEssentialsBuilder essentials) in /home/lemon73/Downloads/maui-linux/src/Core/src/Hosting/EssentialsMauiAppBuilderExtensions.cs:line 110
at Microsoft.Maui.Hosting.EssentialsExtensions.EssentialsInitializer.Initialize(IServiceProvider services) in /home/lemon73/Downloads/maui-linux/src/Core/src/Hosting/EssentialsMauiAppBuilderExtensions.cs:line 131
at Microsoft.Maui.MauiContextExtensions.InitializeAppServices(MauiApp mauiApp) in /home/lemon73/Downloads/maui-linux/src/Core/src/MauiContextExtensions.cs:line 84
at Microsoft.Maui.Hosting.MauiAppBuilder.Build() in /home/lemon73/Downloads/maui-linux/src/Core/src/Hosting/MauiAppBuilder.cs:line 159
at Maui.Controls.Sample.MauiProgram.CreateMauiApp() in /home/lemon73/Downloads/maui-linux/src/Controls/samples/Controls.Sample/MauiProgram.cs:line 304
at Maui.Controls.Sample.MauiProgram.Main() in /home/lemon73/Downloads/maui-linux/src/Controls/samples/Controls.Sample/MauiProgram.cs:line 48
Essentials
でエラーが発生してるっぽいけど…なにこれ…
よくわからないので、一旦 Microsoft.Maui-vscode.sln
のビルドを目指すことに。
iOS でエラーになるので、.sln
から削除する。
$ dotnet run --project Microsoft.Maui-vscode.sln
# (エラー文)
/usr/share/dotnet/sdk/8.0.401/NuGet.targets(174,5): error : 無効なフレームワーク識別子 ''。 [/home/lemon73/Downloads/maui-linux/Microsoft.Maui-vscode.sln]
ビルドに失敗しました。ビルド エラーを修正して、もう一度実行してください。
global.json
に
{
"sdk": {
"version": "8.0.401"
}
}
を追加するも、特に効果はなし。
調節したら、別のエラーになった…
結局よくわからない
困難を極める
ついに動きました。詳しくは後で書きます。
おそらく、src/Controls/samples/Controls.Sample.Gtk/Controls.Sample.Gtk.csproj
は動くので、
dotnet run --project src/Controls/samples/Controls.Sample.Gtk/Controls.Sample.Gtk.csproj --framework net8.0-gtk
にします。
(画像の調整の必要あり (後で書く予定))
でも、UI が崩壊しているね… (おそらく仕様)
UI が崩壊しているのは、自分の Linux (KDE neon) 内で規定している GTK のテーマカラーが影響しているんじゃないかと思い、テーマカラーを上書きする設定にしたら、予想通り直った。
GTK_THEME=Adwaita:light dotnet run --project src/Controls/samples/Controls.Sample.Gtk/Controls.Sample.Gtk.csproj --framework net8.0-gtk
(GTK_THEME=Adwaita:light
を追加)
これで、一通り開発できるわね。既存のアプリケーションへの適応はできなさそうだけど、あとで試してみるかも。(Essential
あたりがほぼ実装されてない気がする)
実装状況はこれ: https://github.com/nblockchain/Mali/blob/master/Status.md
(更新が3年前だから、もっと実装されているかも)
xaml
での記述は無理かも?だけど、C# ではなんとか記述できるかも
とりあえず、コードの簡略化を進めますよん
現状 Mali で作業しているけど、maui-linux のほうが新しいデータが入ってていいかも
なんか、maui-linux でビルドしようとすると Graphics とか Essential でエラーが出るねぇ
あと、ios のワークロードが必要的な (Visual Studio なら動かせる?)
やっぱり Mali で動かすことにしよう。(ちょっと古いけど)
ターゲット指定できる?(試してない)
とりあえず Nuget (追記: 一時的なアップロードだし、GitHub Packages のほうがいいか) にあげてみようかな。ライセンス (MIT License) 的には大丈夫だし。
というか GitHub で現在の状況を公開したほうがいいか…?
面倒だからやってないけど
とりあえず Nuget (追記: 一時的なアップロードだし、GitHub Packages のほうがいいか) にあげてみようかな。ライセンス (MIT License) 的には大丈夫だし。
ということで、とりあえず Core
, Controls.Core
, Compatibility
の3つを以下のように編集しました。
<PropertyGroup>
...
- <IsPackable>false</IsPackable>
+ <!-- <IsPackable>false</IsPackable> -->
...
+ <PackageId>Lemon73.Microsoft.Maui.Controls</PackageId>
+ <Version>0.0.1</Version>
+ <Authors>Lemon73 and others</Authors>
+ <Company>Lemon's Resting Area and others</Company>
</PropertyGroup>
で Nuget 形式にパックする
dotnet pack src/Compatibility/Core/src/Compatibility.csproj
dotnet pack src/Core/src/Core.csproj
dotnet pack src/Controls/src/Core/Controls.Core.csproj
それを GitHub Packages で頒布
dotnet nuget push "artifacts/*.nupkg" --api-key (API キー) --source "github" --skip-duplicate
で頒布したのが以下のもの (あとで消すと思います。なので将来的にリンク切れするかも)
https://github.com/users/Lemon73-Computing/packages/nuget/package/Lemon73.Microsoft.Maui.Controlshttps://github.com/users/Lemon73-Computing/packages/nuget/package/Lemon73.Microsoft.Maui.Controls.Compatibilityhttps://github.com/users/Lemon73-Computing/packages/nuget/package/Lemon73.Microsoft.Maui
(なぜかバージョン指定がうまく行っていない気がする)
参考
あとで、実際に利用できるか試してみます。
(なぜかバージョン指定がうまく行っていない気がする)
あと、なぜか .net6 になってるので、.net8 でビルドしたい
あとで、実際に利用できるか試してみます。
依存関係的にこの3つだけでは動かないっぽい (もしかしたら全部ビルドする必要あるかも)
あと、なぜか .net6 になってるので、.net8 でビルドしたい
これは eng/Version.props
を変えれば良さそう (-dev
がついているのはよくわからない)
やっぱり、Mali は基本的に .net6 ベースだから、.net8 ベースの maui-linux を動かしたいな
とりあえず Nuget (追記: 一時的なアップロードだし、GitHub Packages のほうがいいか) にあげてみようかな。
やっぱり、Mali は基本的に .net6 ベースだから、.net8 ベースの maui-linux を動かしたいな
Related: https://github.com/jsuarezruiz/maui-linux/issues/94
この Issue の完了に目標を変更しよう
とりあえず Nuget (追記: 一時的なアップロードだし、GitHub Packages のほうがいいか) にあげてみようかな。
やっぱり、Mali は基本的に .net6 ベースだから、.net8 ベースの maui-linux を動かしたいな
Related: https://github.com/jsuarezruiz/maui-linux/issues/94
この Issue の完了に目標を変更しよう
https://github.com/jsuarezruiz/maui-linux/blob/main-linux/eng/pipelines/common/pack.yml これ (Azure Devops 向け) を GitHub Actions 用に調節すれば Pack 部分ができる。あとは、我らが Alice Console (謎の自作構文) の https://github.com/AliceNovel/AliceConsole/blob/main/.github/workflows/nuget.yml を参考にして、Nuget.org にコミットごと+タグごとにリリースさせればいい。
現状 Mali で作業しているけど、maui-linux のほうが新しいデータが入ってていいかも
というか GitHub で現在の状況を公開したほうがいいか…?
面倒だからやってないけど
とりあえず Nuget (追記: 一時的なアップロードだし、GitHub Packages のほうがいいか) にあげてみようかな。
やっぱり、Mali は基本的に .net6 ベースだから、.net8 ベースの maui-linux を動かしたいな
Related: https://github.com/jsuarezruiz/maui-linux/issues/94
この Issue の完了に目標を変更しよう
https://github.com/jsuarezruiz/maui-linux/blob/main-linux/eng/pipelines/common/pack.yml これ (Azure Devops 向け) を GitHub Actions 用に調節すれば Pack 部分ができる。あとは、我らが Alice Console (謎の自作構文) の https://github.com/AliceNovel/AliceConsole/blob/main/.github/workflows/nuget.yml を参考にして、Nuget.org にコミットごと+タグごとにリリースさせればいい。
ってことで、maui-linux (Lemon73 Fork) ですわ。
やっぱこれか?
# install dotnet 6
sudo apt-get update; \
sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-6.0
# add keys
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
# install gtksharp with dotnet 6 support
git clone https://github.com/trungnt2910/GtkSharp.git
cd GtkSharp
sudo dotnet tool restore
sudo dotnet cake --BuildTarget=InstallWorkload
# temporary hack for making the templates visible in dotnet new
sudo cp /usr/share/dotnet/template-packs/* /usr/share/dotnet/templates/6.0.5
# install gtk
sudo apt-get install libgtk-3-0
# test gtk template
cd ..
mkdir gtksharptest
cd gtksharptest
dotnet new gtk
dotnet run
これを GitHub Actions 上で試してみるか。
git clone https://github.com/trungnt2910/GtkSharp.git
dotnet cake --BuildTarget=InstallWorkload
PowerShell 上で動いているっぽいので。
これを GitHub Actions 上で試してみるか。
git clone https://github.com/trungnt2910/GtkSharp.git dotnet cake --BuildTarget=InstallWorkload
PowerShell 上で動いているっぽいので。
だめだー
GtkSharp 内で利用されている CI を参考にする?
面倒だけどこの方法を試してみるか
https://github.com/GtkSharp/GtkSharp/wiki/Installing-Gtk-on-Windows
面倒だけどこの方法を試してみるか
msys2 の挙動がよくわからないから一旦諦める。元の方法で試す
ていうか、実機で試してみるか?
実機で動かしてみた感じ
- https://github.com/jsuarezruiz/maui-linux/blob/main/.github/workflows/build-gtk.yml (Linux 向けを Windows 向けに調整して動かす) -> だめ
- https://github.com/GtkSharp/GtkSharp/blob/develop/.github/workflows/main.yml (ビルドして動かす) -> だめ
- https://www.nuget.org/packages/Gtk.Sdk (スクリプト) -> だめ
- https://github.com/GtkSharp/GtkSharp/wiki/Installing-Gtk-on-Windows (msys2 使う) -> 未検証
- (https://www.nuget.org/packages/Gtk4DotNet -> Linux 専用?)
つまり、今までやっていたことは、CI/CD だからエラーになっているというわけではなく、実機でもだめっぽい。
可能なら、GitHub Actions の Windows 上で WSL を動かしたい。それなら Linux のコマンドが使えるから、1の方法ができるはず。(とはいえ、インストールに時間がかかって、CI/CD がかなり遅くなりそうだから非推奨かな…)
可能なら、GitHub Actions の Windows 上で WSL を動かしたい。それなら Linux のコマンドが使えるから、1の方法ができるはず。(とはいえ、インストールに時間がかかって、CI/CD がかなり遅くなりそうだから非推奨かな…)
あるじゃん!!
明日試してみる。WSL でも無理そうなら素直に MSYS2 頑張るか
WSL 厳しそう。msys2 を実機でやって、ci にするか
Reddit でも聞いてみたけど、やはり WSL か Linux 系なら動かせる?そう
どうせ無理だと思うけど、gtk なしで一旦ビルドできるか試してみる?
最終目的はビルドして .nupkg
を nuget.org に上げることなので、その過程については特にこだわりはないし
何故かパスが通せない。から、逆に dotnet をコピーするか...?
でも、さすがに速度が遅くなりそう
何故かパスが通せない。
これだね
ちなみに、MAUI の開発で必須な Microsoft.Maui.Controls
と Microsoft.Maui.Controls.Compatibility
の依存関係は以下
現在の問題は、artifacts
の中に一つも *.nupkg
がないことですわね。
(ls
コマンドを使って見てみても、logs
しかない)
情報がなさすぎるわね
どうやら Windows でもすべてのターゲット向けのコンパイルは厳しいらしい
(.NET MAUI、クロスコンパイルが弱すぎる)
=> Linux でのビルドに切り替えてみる?
あと、dotnet build ./Microsoft.Maui.BuildTasks.slnf
が必要かもしれない。
あとで、実際に利用できるか試してみます。
依存関係的にこの3つだけでは動かないっぽい (もしかしたら全部ビルドする必要あるかも)
あと、なぜか .net6 になってるので、.net8 でビルドしたい
これは eng/Version.props を変えれば良さそう (-dev がついているのはよくわからない)
-dev
は Directory.Build.props
内の <PackageVersion>
で規定されているからっぽい。
(今の作業とは特に関係ないけど)
現在のエラー:
/usr/share/dotnet/sdk/8.0.200/Sdks/NuGet.Build.Tasks.Pack/buildCrossTargeting/NuGet.Build.Tasks.Pack.targets(110,5):
error MSB4018:
System.ArgumentException:
PackageVersion string specified '8.0.40-ci.net8.+sha.59194fc-azdo.' is invalid.
[/home/runner/work/maui-linux/maui-linux/src/Compatibility/Core/src/Compatibility.csproj]
8.0.40-ci.net8
に関しては GitInfo.txt
に記載がある。が、これがどこで利用されているのかがよくわからない。
現在のエラー:
/usr/share/dotnet/sdk/8.0.200/Sdks/NuGet.Build.Tasks.Pack/buildCrossTargeting/NuGet.Build.Tasks.Pack.targets(110,5): error MSB4018: System.ArgumentException: PackageVersion string specified '8.0.40-ci.net8.+sha.59194fc-azdo.' is invalid. [/home/runner/work/maui-linux/maui-linux/src/Compatibility/Core/src/Compatibility.csproj]
見つけた
$(BUILD_BUILDID)
が指定されていないため文字が挿入されず、バージョンの末尾が azdo.
のように .
で終わってエラーになっている。
これでほぼできた
リリース向けも追加
nuget.org へのデプロイは名前がかぶってるから多分できていない (API キーをいれて動かしてみたけど、403エラーなので)
あとは、maui-linux チームと連絡して調整ってかんじかな。
そういえば nuget package がちゃんと動くかわからないので、後で検証するか (github actions の artifacts にでも入れようかな?)
だめかも
わからなくなってきた
kztao 氏の CI が洗練されているので、それを upstream に merge してもらうといいかも
kztao 氏の CI が洗練されているので、それを upstream に merge してもらうといいかも
kztao さんの内容を cherry pick して、自分の変更と合流させた。(これのせいで若干 commit が分かりづらい気がする…)
とりあえず PR: https://github.com/kztao/maui-linux/pull/1
文章とかがめちゃくちゃだけど、ご愛嬌…
返答をお待ちいたしますわ。多分 kztao さんも CI/CD が正常に動いていなくて困っていると思うから、情報共有したいのです。