[英]Bundle native JNI shared libraries with Clojure libraries
I am writing a library for clojure which involves native code. 我正在编写一个涉及本机代码的clojure库。 How can I bundle the shared library (aka native dependencies) when I deploy the clojure libraries to public repositories (like clojars)?
当我将clojure库部署到公共存储库(如clojars)时,如何捆绑共享库(也称为本机依赖项)?
My project structure looks roughly like: 我的项目结构大致如下:
src/
native/ - C code , C Object files and compiled shared libs
java/ - Java stuff
clojure/ - Clojure stuff
I am currently using leineingen. 我目前正在使用leineingen。 I have tried doing:
我试过做:
:jvm-opts [~(str "-Djava.library.path=src/native/:"
(System/getenv "$LD_LIBRARY_PATH"))]
It works if I am in the project. 如果我在项目中,它可以工作。 However, if I include this project as a dependency, I will get a
UnsatisfiedLink
error. 但是,如果我将此项目作为依赖项包含,我将收到
UnsatisfiedLink
错误。
The answer depends on your exact use-case. 答案取决于您的确切用例。 In the simplest situation, you need to:
在最简单的情况下,您需要:
native/
folder in :resource-paths
in your project.clj
. native/
文件夹包含在project.clj
中的:resource-paths
中。 :native-prefix
option to indicate a path inside your library jar from which native libraries should be extracted. :native-prefix
选项以指示库jar中的路径,应从中提取本机库。 For example, if your library contains a resource "mylib.so" in the root folder, you can specify it like this: [com.foo/bar "1.0.1" :native-prefix ""]
[com.foo/bar "1.0.1" :native-prefix ""]
:native-path
option in your project.clj
. project.clj
的:native-path
选项指定提取的库应该去的位置。 :native-path
you have specified to java.library.path
, using :jvm-opts
like you said. :jvm-opts
将你指定的:native-path
添加到java.library.path
。 These options are documented in the sample leiningen project.clj . 这些选项记录在示例leiningen project.clj中 。
Now the reason I said it depends on your use-case is that if you want to create an uberjar that contains native libs, things start getting more messy. 现在我说它取决于你的用例的原因是,如果你想创建一个包含本机库的uberjar,事情开始变得更加混乱。 The main reason is that you can't directly link to a lib that is zipped inside your jar.
主要原因是你无法直接链接到jar中压缩的lib。 If you're lucky, you'll be able to use the
loadLibraryFromJar
method in the NativeUtils class. 如果幸运的话,您将能够在NativeUtils类中使用
loadLibraryFromJar
方法。 However, I remember having ClassLoader
-related issues that prevented me from using System/load
. 但是,我记得有
ClassLoader
问题导致我无法使用System/load
。 Instead I had to make sure the library was present in one of the paths that the JVM looks for, so that System/loadLibrary
finds it correctly. 相反,我必须确保库存在于JVM查找的其中一个路径中,以便
System/loadLibrary
正确地找到它。 Here is what I ended up doing: 这是我最终做的事情:
(-> my-lib io/resource io/input-stream (io/copy my-temp-file))
(-> my-lib io/resource io/input-stream (io/copy my-temp-file))
java.library.path
system property at runtime to add the temporary folder to it, using System/setProperty
System/setProperty
在运行时更新java.library.path
系统属性以向其添加临时文件夹 This is painful to setup, but after that it works pretty well. 设置很痛苦,但之后效果很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.