使用本机库的clojure库的“最佳实践”?

时间:2014-01-29 16:22:44

标签: clojure leiningen

虽然这可能看似主观,但有一个具体的例子,我希望帮助解决。这与Overtone Clojure库https://github.com/overtone/overtone/issues/274的问题有关,似乎应该有一个" Best Practice"对于Leiningen并适用于比Overtone更多的库。

Overtone是一个clojure库,可以在其他项目中使用。 Overtone需要本机库才能工作,因此它在project.clj https://github.com/overtone/overtone/blob/master/project.clj#L69中使用:native-path "native",以便为使用的本地scsynth库[overtone/scsynth "3.5.7.0"]获取正确的路径。

但是,我认为这会重置依赖于Overtone库的项目的传入路径。请参阅问题以了解某些背景知识,但基本上依赖于项目中的[overtone "0.9.1"]。{1}}仅返回当前本机路径,而使用Overtone的项目无法传递到任何本地库的路径。

所以,问题是 - 依赖项目如何将本地本地库与Overtone混合? Overtone或依赖项目是否应调整其project.clj设置?怎么样?

3 个答案:

答案 0 :(得分:3)

我不知道" best",但这是一个现在至少在四个项目中成功运作的实践,其中三个是"真实" ,商业的。虽然我只开源a specific case for ZeroMQ,但我相信这些原则是通用的,适用于任何本地库。大多数代码也可以轻松地重用,并且它在Eclipse下获得许可,因此如果您愿意,可以随意使用它。我还没有对包含本机的库的更通用版本的需求,但我相信它很容易被提取出来。

我对标准解决方案(lein' s:native-path,JVM args等)的问题是,我想要一个便携式解决方案,用于uberjar发布,不需要用户安装任何东西其他,所以请说明如下"下载uberjar,从你的软件包管理器安装libzmq-dev,然后启动uberjar"不可能。

原理非常简单:我将所有支持的平台中的本机库捆绑在库jar中。那样:

  • 我作为图书馆作者,具体控制使用哪些版本。没有惊喜。
  • 包含来自其他项目的库可以在不知道库依赖于本机库的情况下完成。
  • 同样,uberjar的分发,无论是来自leiningen还是maven,都可以无缝地工作。

我也不依赖于任何操作系统链接策略,因为我发现很难让它们可靠地工作。所以我做的是我包含了所有必需的本机库,这些库不能保证在jar中运行的系统上,然后在运行时,库中包含:

  • 动态找出它正在运行的平台;
  • 将本机库从其自己的存档中提取到系统特定的临时目录(如果它尚不存在)(基于SHA;这是必要的,以避免在不能正确清理其临时目录的平台上累积 - 这是,Windows);
  • "手动"以正确的顺序加载本机依赖项,​​因此动态链接不会尝试解析主机OS路径上的库。

这种方法当然有缺点:

  • 由于单个工件的构建过程涉及三种不同的操作系统(我支持Linux,Windows和OSX)和2种体系结构(i386和x86_64),因此构建过程难以自动化并需要访问相关的机器; < / LI>
  • 由于捆绑了本机库的特定版本,因此库用户无法更新它们;在安全敏感的环境中,这可能是不可接受的;
  • 作为这个库的用户,你必须相信我捆绑的本机库确实是我所声称的,并且确实是通过我在源代码中描述的过程构建的,而不再篡改;
  • 由于我对链接动态库几乎一无所知,这种方法可能还有其他问题,尽管它们还没有让我感到困惑。

答案 1 :(得分:2)

我通过Clojars发布了clj-nativedep,可以帮助解决这个问题。该库提供了快速识别当前系统体系结构的规范化名称的功能,并且可以将任何选定的资源(在jar或类路径中)加载到运行时环境中。

请参阅:https://github.com/rritoch/clj-nativedep

这个系统专门用于我的WarpCTL项目,该项目利用swig生成的大量本机代码。由于处理Clojure类加载的方式,需要通过静态类构造函数加载本机依赖项,​​您可以在https://github.com/rritoch/WarpCTL/blob/master/extra/JADL-SDK/build/java/src/com/vnetpublishing/swig/adl/jadl_sdk.java#L13看到一个示例。对于该项目,我将java代码构建到JAR中,并添加clj-nativedep和jar作为依赖项。应该可以从纯clojure应用程序加载资源,但为了获得最佳性能,需要从静态类构造函数加载。

答案 2 :(得分:0)

我曾经遇到过这个问题,所以我创建了一个非正统的lein插件,只需一次性解决这个问题就可以添加几行project.cljhttps://bitbucket.org/noncom/nativot

警告:Clojure方式非常不受欢迎,因为它打破了所有可重复性和内容的概念,允许您将任意jar,资源和其他文件打包到生成的jar中,并使其正常工作。