如何说服mkbundle包含MonoPosixHelper
本文关键字:包含 MonoPosixHelper mkbundle | 更新日期: 2023-09-27 18:29:24
我正在使用mkbundle,并试图创建一个使用Isis2的小程序IdaTester的嵌入式版本。该系统反过来使用Mono的功能,这些功能依赖于MonoPoxHelper
我的问题是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库的平台,但如果在尚未安装libMonoPoxHelper的平台上运行,则在运行时尝试动态加载该库时会失败。。。
需要将libMonoPosixHelper.so与应用程序一起分发,并更改dll映射以使其工作。
问题背景-库在运行时加载
libMonoPosixHelper不是静态链接的,而是作为p/Invoke调用搜索和加载的,例如下面的示例:
[DllImport ("MonoPosixHelper")]
static extern int zipClose (ZipHandle handle, string globalComment);
也就是说,它只在运行时请求,而不是在编译时请求,因此不能提前链接。
修复它-分发libMonoPoxHelper.so
需要四个步骤。
- 将libMonoPosixHelper复制到将要分发程序的目录中
- 更新DllMap配置文件以避免硬编码的位置
- 使用mkbundle嵌入配置文件
- 将带有libMonoPosixHelper.so的路径添加到安装计算机上的LD_LIBRARY_path中
执行每个:
1.将libMonoPosixHelper复制到将要分发程序的目录中
libMonoPosixHelper通常位于lib文件夹中,只需将其复制到要制作tarball的文件夹中即可。
cp $MONO_ROOT/lib/libMonoPosixHelper.so ~/MY_PROGRAM/
2.更新DllMap配置文件以避免硬编码位置
这是避免硬编码路径问题的关键比特。我们需要使用mkbundle嵌入一个不指定路径的配置文件。要做到这一点,首先找到mono-config文件,然后将其复制到本地目录
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环境变量
据我所知,对我来说,最好的选择是构建一个非共享的Mono库,其中包含与当前在MonoPoxHelper.so中找到的方法相同的方法,或者提供MonoPoxhelper.so的副本作为组件安装在与我的服务器相同的文件夹中。两者似乎都不理想:前者迫使我"接触"Mono发行版,这会产生长期维护问题,而后者则迫使我进入更复杂的发行和安装模式。但似乎一旦生成了一个共享库,就无法静态链接到该版本的库;Linux加载程序只是没有像处理更多标准库那样将这样的东西视为库。
相比之下,如果我确实从相同的.o文件生成了一个标准库,加载程序会很乐意静态链接到它,因为mxbundle最终运行cc,因此使用了标准ld,所以这个选项对我来说是有效的。所以我想这就是我问题的答案。