5

我正在使用 mkbundle 并尝试创建一个使用 Isis2 的小程序 IdaTester 的嵌入式版本。该系统反过来使用依赖于 MonoPosixHelper 的 Mono 功能

我的问题是 mkbundle 无法识别依赖关系,我最终得到了一个仍然需要动态链接到 ~/bin/lib/libMonoPosixHelper.so 的可执行文件,当我将此可执行文件移动到我没有的系统时会导致问题安装了 Mono。实际上,bundle 缺少它应该静态链接的东西之一。

我的可执行文件确实有效,但前提是我确保仅在“正确位置”具有动态库的机器上运行它。这违背了嵌入式可执行文件的目的......我希望能够将这个程序作为一种服务器提供给人们,他们可以放在任何地方并作为二进制文件启动,显然如果他们需要安装库以使其工作,服务器并不完全独立!

我看到了如何强制 mkbundle 包含程序所依赖的任何 dll 文件,但 MonoPosixHelper 不作为 dll 存在;这是一个仅限 Linux 的库,仅作为共享库存在。有谁知道“强制”捆绑包静态嵌入它的方法?

如果这有帮助,我的小编译脚本如下:

mcs -debug+ IdaTester.cs Isis.cs -r:System.dll -r:Microsoft.CSharp.dll -r:Mono.Posix.dll
mkbundle --static -o IdaTester IdaTester.exe --deps

然后我运行 IdaTester;这适用于可以找到 libMonoPosixHelper 库的平台,但如果在未安装 libMonoPosixHelper 的平台上运行,则尝试动态加载该库时将在运行时失败...

4

2 回答 2

3

需要将 libMonoPosixHelper.so 与应用程序一起分发并更改 dll 映射以使其工作。

问题的背景 - 库在运行时加载

libMonoPosixHelper 不是静态链接的,而是作为 P/Invoke 调用搜索和加载的,如下例所示:

    [DllImport ("MonoPosixHelper")]
    static extern int zipClose (ZipHandle handle, string globalComment);

也就是说,它只在运行时请求,而不是编译时请求,因此无法提前链接。

修复它 - 分发 libMonoPosixHelper.so

需要四个步骤。

  1. 将 libMonoPosixHelper 复制到您将用于分发程序的目录。
  2. 更新 DllMap 配置文件以避免硬编码位置。
  3. 使用 mkbundle 嵌入配置文件
  4. 将带有 libMonoPosixHelper.so 的路径添加到安装机器上的 LD_LIBRARY_PATH。

要执行每个:

1. 将 libMonoPosixHelper 复制到您将用于分发程序的目录中。

libMonoPosixHelper 通常位于 lib 文件夹中,只需将其复制到您将制作 tarball 的文件夹中即可。

cp $MONO_ROOT/lib/libMonoPosixHelper.so ~/MY_PROGRAM/

2. 更新 DllMap 配置文件以避免硬编码位置。

这是避免硬编码路径问题的关键位。我们需要使用未指定路径的 mkbundle 嵌入一个配置文件。为此,首先找到单声道配置文件,并将其复制到本地目录

cp $MONO_ROOT/etc/mono/config ~/MY_PROGRAM/config

现在我们需要更改此文件以删除 dll 的特定路径,使用您喜欢的编辑器打开它并更改路径以避免特定前缀:

<dllmap dll="MonoPosixHelper" target="MACHINE_SPECIFIC/lib/libMonoPosixHelper.dylib" os="!windows" />

<dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.dylib" os="!windows" />

3. 使用 mkbundle 嵌入配置文件

将以下选项添加到您的 mkbundle 命令以嵌入新编辑的配置文件:

   --config MY_PROGRAM/config

4. 将带有 libMonoPosixHelper.so 的路径添加到安装机器上的 LD_LIBRARY_PATH。

现在您可以压缩您的 mkbundled 可执行文件、libMonoPosixHelper.so 和任何其他文件以进行分发。当解压并在机器上运行时,dlopen 现在将像任何其他 dll 一样查找 libMonoPosixHelper.so。因此,只需将包含您的分布式版本的 libMonoPosixHelper 的任何目录添加到他们的 LD_LIBRARY_PATH 环境变量中

于 2015-10-08T18:54:18.030 回答
1

据我所知,对我来说最好的选择是构建一个非共享的 Mono 库,其中包含与当前在 MonoPosixHelper.so 中找到的方法相同的方法,或者提供 MonoPosixHelper.so 的副本作为组件安装在与我的服务器相同的文件夹中。两者似乎都不理想:前者迫使我“接触” Mono 发行版,这会产生长期维护问题,而后者迫使我进入更复杂的发行和安装模式。但是似乎一旦生成了共享库,您就根本无法静态链接到该库的版本;Linux 加载器只是在处理更多标准库的方式上没有将这样的东西视为库。

相反,如果我确实从相同的 .o 文件生成标准库,加载器将很乐意静态链接它,并且因为 mxbundle 最终运行 cc 并因此使用标准 ld,该选项对我有用。所以我想这就是我的问题的答案。

于 2013-08-29T13:29:39.993 回答