如何使用OSGi片段来提供具有相同文件名的依赖于平台的本机代码?
我正在使用JNotify项目来监听文件系统事件。 这取决于每个操作系统的一个本机库:处理器架构。 例如,有一个用于Windows x86的库,一个用于x86-64等的库。
整体捆绑
最初,我有一个包含JNotify Java类和本机代码的包。 本机代码在Bundle-NativeCode中声明如下:
(我已经将这些格式化为bnd样式以获得更好的可读性……显然,实际的MANIFEST.MF文件已正确形成)。
Bundle-NativeCode: jnotify_64bit.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003;osname = WindowsVista;osname = Windows7;osname = WindowsServer2008;osname= Windows8;osname = WindowsServer2012;processor = x86-64,\ jnotify.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003;osname = WindowsVista;osname = Windows7;osname = WindowsServer2008;osname = Windows8;osname = WindowsServer2012;processor = x86,\ libjnotify.so;osname = Linux;processor = x86,\ libjnotify64.so;osname = Linux;processor = x86-64,\ libjnotify.dylib;osname = Mac OSX;processor = x86;processor = x86-64,\ *
这很好用。
转移到片段
我认为如果我将库移动到单独的片段包中会很“好”,这样我就可以为我感兴趣的体系结构贡献片段。以Linux为例,我将它们分成两个包:
Linux 32位
Include-Resource: lib/libjnotify.so Bundle-NativeCode: libjnotify.so;osname = Linux;processor = x86,\ * Fragment-Host: net.contentobjects.jnotify Bundle-Version: 0.94.0
Linux 64位
Include-Resource: lib/libjnotify.so Bundle-NativeCode: libjnotify.so;osname = Linux;processor = x86-64,\ * Fragment-Host: net.contentobjects.jnotify Bundle-Version: 0.94.0
请注意,这些捆绑包是根据不同的来源构建的。 虽然libjnotify.so文件名是相同的,但它们是不同Eclipse项目中的不同文件。 它们必须与JNotify一样。
请注意,相同的文件名将提供给主机包。 在这种情况下,文件名是libjnotify.so。
如果我在我的64位机器上运行这些,并且在 32位之前加载64位软件包,它就可以工作。
但是,如果首先加载32位包,我得到:
Couldn't initialise JNotify: java.lang.UnsatisfiedLinkError: /blah/generated/fw/bundle46/version0.0/net.contentobjects.jnotify.linux.x86-0.94.0.jar-lib/0/libjnotify.so: /blah/generated/fw/bundle46/version0.0/net.contentobjects.jnotify.linux.x86-0.94.0.jar-lib/0/libjnotify.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch) (JnotifyFileSystemObserver.java:53, thread platformExecutor)
显然正在加载32位库。 但为什么? My Bundle-NativeCode定义主机必须是32位Linux机器才能使用32位软件包的版本。 我想如果那个子句不匹配,库会被忽略吗?
东西我试过了
- 删除可选的通配符…这只是意味着捆绑包无法解析
由于您的片段占用相同的资源名称空间,因此只能访问一个.so文件。 您只能部署一个片段,或者您可以尝试将它们放在不同的目录中:
Fragment 32-bit: Include-Resource: x32/libjnotify.so=lib/libjnotify.so Fragment 64-bit: Include-Resource: x64/libjnotify.so=lib/libjnotify.so
我还认为你需要将Bundle-NativeCode标头放在主机包中并引用正确的目录,因为我认为这个标头没有在主机中合并。
检查您运行的Eclipse / OSGi容器的版本。 我怀疑你发现你正在启动的容器已经设置为32位系统。
如果您不介意限制使用Equinox ,则可以在Eclipse-PlatformFilter
使用每个片段一个片段的解决方案。 在这种情况下,只能在任何时候解析和安装一个具有本机代码的片段,从而避免命名空间冲突。