我有一个由api、core和third-party组成的多模块SBT构建.其结构大致如下:
api
|- core
|- third-partythird-party的代码实现了api,是从其他地方逐字复制的,所以我真的不想碰它。
由于third-party的实现方式(大量使用单例),我不能只让core依赖于third-party。具体来说,我只需要通过api使用它,但是我需要在运行时拥有多个独立的third-party副本。(这允许我同时拥有多个“单身汉”。)
如果我在SBT构建之外运行,我只需要这样做:
def createInstance(): foo.bar.API = {
val loader = new java.net.URLClassLoader("path/to/third-party.jar", parent)
loader.loadClass("foo.bar.Impl").asSubclass(classOf[foo.bar.API]).newInstance()
}但问题是,如果我是通过URLClassLoader运行的,那么我不知道如何在运行时为sbt core/run提供一个参数。
发布于 2015-04-11 16:12:27
这应该是可行的,虽然我并没有用你的设置来测试它。
基本思想是让sbt将类路径写入一个您可以在运行时使用的文件中。sbt-buildinfo已经为此提供了一个很好的基础,所以我将在这里使用它,但是您可能只提取相关的部分,而不使用这个插件。
将此添加到项目定义中:
lazy val core = project enablePlugins BuildInfoPlugin settings (
buildInfoKeys := Seq(BuildInfoKey.map(exportedProducts in (`third-party`, Runtime)) {
case (_, classFiles) ⇒ ("thirdParty", classFiles.map(_.data.toURI.toURL))
})
...在运行时,请使用以下命令:
def createInstance(): foo.bar.API = {
val loader = new java.net.URLClassLoader(buildinfo.BuildInfo.thirdParty.toArray, parent)
loader.loadClass("foo.bar.Impl").asSubclass(classOf[foo.bar.API]).newInstance()
}exportedProducts只包含项目的编译类(例如.../target/scala-2.10/classes/)。根据您的设置,您可能希望使用fullClasspath (它还包含libraryDependencies和依赖项目)或任何其他与类路径相关的键。
https://stackoverflow.com/questions/29578808
复制相似问题