我正在管理的 Linux 工具链包含旧版 .Net 应用程序。这在 Ubuntu 上很好,因为可以使用官方的 Mono 运行时环境来运行 .Net 应用程序。但我想在没有官方 Mono 支持的其他 Linux 发行版(例如 RHEL/Rocky Linux)上运行我的工具链。我宁愿保持 runtime 依赖项列表尽可能小,即我既不想依赖第 3 方 Mono 构建,也不想依赖 Docker。
理论上,我的场景得到了很好的支持:Mono 的
mkbundle
能够将任何 .Net 应用程序打包到特定于平台的二进制文件中,该二进制文件不依赖于已安装的 Mono 运行时。但是,它确实引入了对 libmono-native.so
的依赖(这是动态依赖,因此它不会出现在 ldd
的输出中),而我无法实现这一点。
测试.cs
using System;
public class HelloWorld
{
public static void Main(string[] args)
{
Console.WriteLine ("Hello Mono World");
}
}
我通过
csc hello.cs
将其编译为 .Net 可执行文件到 test.exe
。这个可执行文件可以在 Mono 上正常运行,但是 - 显然 - 没有 Mono 运行时就不行。
mkbundle --cross mono-6.6.0-ubuntu-18.04-x64 -o test test.exe
这会创建一个本机
test
ELF 二进制文件(我几乎只是选择了任意 x64 交叉编译目标,因为 RHEL/Rocky Linux 和任何较新的 Ubuntu 目标都不可用)。当安装了 Mono 运行时时,此 test
在 Ubuntu 上运行(我测试了“Jammy”22.04),但在没有 Mono 运行时的系统上失败并显示 System.DllNotFoundException: /libmono-native.so
。
因此,我也尝试通过
mkbundle --cross mono-6.6.0-ubuntu-18.04-x64 --library /usr/lib/libmono-native.so -o test test.exe
嵌入该库,但这在所有经过测试的系统(Ubuntu 和 Rocky Linux)上都失败了
Error loading shared library: /tmp/mono-bundle-SSDDWc/libmono-native.so /tmp/mono-bundle-SSDDWc/libmono-native.so: cannot open shared object file: No such file or directory
mkbundle --static -L /usr/lib/mono/4.8-api -o test test.exe
这同样会创建一个
test
ELF 二进制文件,但执行它会崩溃,并且 Ubuntu 主机系统上已经存在 SEGFAULT。 gdb
输出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000055555556c314 in mono_mkbundle_init () at temp.c:147
#2 0x000055555556c652 in main (argc=1, argv=0x7fffffffddd8) at temp.c:224
我做错了什么,还是我的方法根本不可能?
.NET 框架有两代完全独立的实现:
Mono 目前几乎没有获得开发支持,并且在 Mono 中构建本机应用程序可能会出现问题并且无法修复。然而,.Net Core 本质上取代了它,并且可以在许多 Linux 发行版的官方软件包存储库中使用(例如 Ubuntu 的
dotnet-sdk-7.0
)。
使用.NET Core,可以构建主机平台的本机应用程序 通过从应用程序的源代码根文件夹(包含 Visual Studio 解决方案
1的文件夹)执行
dotnet publish --configuration=release --self-contained
。可以通过附加 -r <platform>
参数来生成不同平台的二进制文件。通过添加,本机应用程序可以打包为单个可执行文件(而不是一组库和可执行文件)
<PublishSingleFile>true</PublishSingleFile>
配置行添加到相应的
.csproj
/.vbproj
项目文件中。或者,还可以通过添加来修剪此单个可执行文件以减小其大小
<PublishTrimmed>true</PublishTrimmed>
配置行 - 但这仅适用于 .NET 语言功能的子集。