将本机系统库与 SBT 集成 [英] Integrating native system libraries with SBT

查看:34
本文介绍了将本机系统库与 SBT 集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将各种 SBT 任务与本机库(例如,来自 JOGLLWGLJCuda? 具体来说,

What is a good way to integrate various SBT tasks with native libraries (for example, those from JOGL, LWGL, or JCuda? Specifically,

  1. 是否有推荐的方法在 run 任务中包含本机库?SBT 邮件列表上的讨论表明了这些可能性:

  1. Is there a recommended way to include a native library in the run task? A discussion on the SBT mailing list suggests these possibilities:

  • Modify JavaOptions to include -Djava.library.path=<path to native libraries>, and then modify the run task to fork the JVM. (See this plugin for an example.)
  • Use the SBT initialize setting to run code that calls System.setProperty(...) to configure java.library.path. Again, run must fork.
  • Put the native libraries on the classpath before launching SBT.

最后一个优点是run不需要fork,缺点是配置必须在SBT之外.

The last one has the advantage that run need not fork, but the disadvantage that the configuration must be done outside SBT.

我能否在由 sbteclipse 插件生成的 Eclipse 项目中自动包含本机库?可以重写.project文件在后处理步骤中. 有示例代码吗?有没有更好的方法?

Can I automatically include native libraries in the Eclipse project generated by the sbteclipse plugin? It's possible to rewrite the .project file in a post-processing step. Is there example code? Is there a better way?

本地库是否可以包含在由插件生成的可运行 Jar 中,例如 sbt-程序集sbt-onejarsbt-proguard?

Can native libraries be included in the runnable Jar that is generated by a plugin such as sbt-assembly, sbt-onejar or sbt-proguard?

我假设本机库没有直接的 SBT 设置.如果存在这样的事情,上述任务是否可以透明地处理本机库?

I assume there is no direct SBT setting for native libraries. If something like that existed, could the above tasks handle native libraries transparently?

推荐答案

从我过去的研究来看,只有两种方法可以加载原生库:修改 java.library.pathcode> 并使用 System.loadLibrary(我觉得大多数人都这样做),或者使用带有绝对路径的 System.load.

From the research I've done in the past, there are only two ways to get native libraries loaded: modifying java.library.path and using System.loadLibrary (I feel like most people do this), or using System.load with an absolute path.

正如您所提到的,在配置 SBT 和 Eclipse 方面,使用 java.library.path 可能会很烦人,而且我认为不可能为可执行 jar 自动执行此操作.

As you've alluded to, messing with java.library.path can be annoying in terms of configuring SBT and Eclipse, and I do not think it's possible to do automatically for an executable jar.

这样就剩下System.load.在编写自己的原生库方面,您可以做的是:

So that leaves System.load. In terms of writing your own native libraries, what you can do is:

  • 创建一个 SBT 任务来编译您的本机源代码(使用 javahgcc),获取生成的 .so 文件和它依赖的任何 .so 文件,将它们放入在目标目录的 jar(作为资源)中,并将 jar 的路径添加到 unmanagedJars in Compile.
  • 创建一个 Scala 方法来加载库.它不会调用 System.loadLibrary,而是使用 Class.getResourceAsStream 读取库,File.createTempFile 将其写入文件系统的某个位置,和 System.load 将其加载到 JVM 中.
  • 现在不再像以前那样调用 System.loadLibrary,而是调用 MyClasspathJniLoader.loadLibrary.
  • Create an SBT task that compiles your native sources (with javah and gcc), takes the resulting .so files and any .so files it depends on, puts them in a jar (as resources) in the target directory, and adds the path to the jar to unmanagedJars in Compile.
  • Create a Scala method to load a library. Instead of calling System.loadLibrary, it will use Class.getResourceAsStream to read the library, File.createTempFile to write it somewhere on the filesystem, and System.load to load it into the JVM.
  • Now instead of calling System.loadLibrary as you would before, call MyClasspathJniLoader.loadLibrary.

这将适用于 SBT 运行、Eclipse 和可执行 jar,无需任何额外配置(虽然我不知道 proguard 如何知道要包含哪些资源).

That will work with SBT run, Eclipse, and executable jars without any extra configuration (although I don't know how proguard knows which resources to include).

现在对于已经编写好的第三方本机库,其中一些像 jblas 已经使用了这种fat jar"方法.如果他们希望您设置 java.library.path,然后在他们愿意时调用 System.loadLibrary,那么您需要做一些魔术来做到这一点工作.

Now as to third party native libraries that have already been written, some of them like jblas already use this "fat jar" approach. If they expect you to set up java.library.path and then they call System.loadLibrary when they feel like it, you'll need to do some magic to make that work.

我没有试过这个,但这个解决方案可能有效:

I haven't tried this, but this solution might work:

  • 使用类似的 SBT 任务将其本机路径上的所有库作为资源放入 jar 中,并将该 jar 放入 clsaspath.
  • 创建一个 Scala 方法,它接受一个函数和一个库名列表,创建一个临时目录,将这些库从 jar 的资源中读取到临时目录中的文件中,将临时目录添加到 java.library.path,调用传入的函数,最后将java.library.path恢复到原来的样子.
  • 第一次调用本机库时(当它可能会静态初始化并进行 System.loadLibrary 调用时),将该特定调用包装在您的方法中,并包含它将加载的库列表.这样,当它调用 System.loadLibrary 时,它的所有库都将在 java.library.path 上并成功加载.
  • Use a similar SBT task to put all of the libraries on their native path into a jar as resources, and put that jar on the clsaspath.
  • Create a Scala method that takes a function and a list of library names, creates a temp directory, reads those libraries from the jar's resources into files in the temp directory, adds the temp directory to java.library.path, calls the passed in function, and finally reverts the java.library.path back to what it was before.
  • The first time you call into the native library (when it presumably will statically initialize and make the System.loadLibrary call), wrap that particular call in your method with the list of libraries it will load. That way, when it calls System.loadLibrary, all of its libraries will be on java.library.path and will be loaded successfully.

显然这很烦人,因为您必须在使用之前手动初始化第三方库,但包装所有初始化点(您的主要功能和测试初始化​​)似乎比获取所有工具更可行正确设置 java.library.path.如果您已经在第三方库之上拥有自己的抽象层,那么这可能会更容易,因此您实际上只需要包装一个初始化点.

Obviously this is annoying since you have to manually initialize the third party library before using it, but it seems more feasible to wrap all of the initialization points (your main functions and test initializations) than it does to get all of your tools to set java.library.path correctly. And it may be even easier than that if you already have your own layer of abstraction above the third party library, so there's really only one initialization point you have to wrap.

如果这看起来是一个现实的解决方案,如果您感到困惑,我可以添加有关 SBT 任务或 Scala 包装方法的更多详细信息.

If that seems like a realistic solution, I can add more details about the SBT task or Scala wrapper methods if you're confused.

这篇关于将本机系统库与 SBT 集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆