有条件地使用 sbt 和通用插件包含提供的范围依赖项

Posted

技术标签:

【中文标题】有条件地使用 sbt 和通用插件包含提供的范围依赖项【英文标题】:Conditionally include provided scope dependencies with sbt and the universal plugin 【发布时间】:2016-08-19 04:33:57 【问题描述】:

我有一个项目是 scala & scalatra API。我有两个使用 sbt-native-packager 构建的可分发文件 -

    RPM 和 DEB 安装用于本地安装 用于云安装的 heroku 安装

我目前正在使用 provided 范围依赖项来处理我需要使用 RPM/DEB 方法手动管理的项目 - 由于许可证限制,我无法捆绑和分发的数据库库。

"mysql" % "mysql-connector-java" % "5.1.30" % "provided",
"com.microsoft" % "sqlserver.jdbc" % "4.1" % "provided",
..etc..

这一直很好。我使用通用插件和dist 任务,稍加处理,然后连接一些包构建脚本。

现在我正在构建 heroku 安装,但我不知道如何重新添加那些提供的依赖项。我正在使用通用插件并运行stage 任务。但是,提供的依赖项正在被过滤掉,我希望在运行 stage 时将它们包含在内,因为我在 heroku 中不再有许可证限制。

我认为我有的选择...

    添加 mapping 以在 stage 任务期间添加回提供的范围依赖项,但在 dist 任务期间不添加 在dist 期间完全删除提供的范围并手动从打包过程中排除这些依赖项

我已经有一些这样的映射,

//add webapp dir to zip
mappings in Universal ++= directory("src/main/webapp")

//add db dir to zip, but move it into /lib/db instead of /db
mappings in Universal ++= (directory("src/main/resources/db").mapt => 
    (t._1, "lib/"+t._2)
  
)

所以我觉得如果我真的尝试过,我可能会弄清楚如何添加/排除,但我在查找这些东西的任何文档时遇到了问题。 here 的例子并没有太大帮助,或者我理解的不够。

提前致谢!

【问题讨论】:

【参考方案1】:

这是一个有趣的问题。前段时间,我们在构建类路径中添加了add arbitrary artifacts 的可能性。 (也见scaladocs)

选项 1 可能如下所示。请注意,这并不像我预期的那样工作,因为本机打包程序并未完全拾取某些映射:

// `show universal::stage:mappings` works properly
mappings in (Universal, stage) ++= 
  // calculate provided dependencies.
  val compileDep = (managedClasspath in Compile).value.toSet
  val runtimeDep = (managedClasspath in Runtime).value.toSet
  val provided = compileDep -- runtimeDep

  // create mappings
  fromClasspath(provided.toSeq, "jar", artifact => true)

我通过提供build environment 并决定要添加哪些映射来建议选项 1 的变体。

mappings in Universal ++= 
  // a build environment
  val env = buildEnv.value

  // calculate provided dependencies.
  val compileDep = (managedClasspath in Compile).value.toSet
  val runtimeDep = (managedClasspath in Runtime).value.toSet
  val provided = compileDep -- runtimeDep

  // create mappings, depending on build environment
  fromClasspath(provided.toSeq, "jar", _ => env == BuildEnv.Stage)


// add the dependencies to the start script as well
scriptClasspath ++=  /* similar code as above */

我想做的事

我希望能够做到这样的事情

libraryDependencies += "com.google.guava" % "guava" % "19.0" % "provided"

mappings in (Universal, stage) ++= fromClasspath(
   (managedClasspath in Compile).value,
   "jar",
    artifact => artifact.scope == "provided"
)

这是不可能的,因为sbt Artifact 无法访问常春藤范围(或者我没有找到它)。

然后我尝试这样做

libraryDependencies += "com.google.guava" % "guava" % "19.0" % "provided" extra("heroku" -> "true")

mappings in (Universal, stage) ++= fromClasspath(
   (managedClasspath in Compile).value,
   "jar",
    artifact => artifact.extra.find(_ == "heroku")
      .map(_.toBoolean)
      .getOrElse(false)
)

这也不起作用,因为 SBT 似乎没有将 ModuleID 中的 extra 属性传递给 Artifact 模型。这给我留下了上述解决方案。

【讨论】:

似乎成功了,非常感谢您的帮助。我能够添加一些过滤来调整结果,然后我们就可以开始运行了。对 sbt Artifact 感到难过 - 你会认为应该能够在带内访问此类信息,而不是制作另一个配置项! 实际上这并不太成功 - 它添加了映射文件,但没有设法将它们添加到运行脚本的类路径条目中。现在正在尝试解决这个问题 使用 scriptClasspath ++= ..same stuff.. 添加了它们 真棒@卢卡斯!对不起,我没有想到:(

以上是关于有条件地使用 sbt 和通用插件包含提供的范围依赖项的主要内容,如果未能解决你的问题,请参考以下文章

sbt 插件和使用插件本身的多项目构建中的项目之间的相互依赖关系

是否有一个sbt插件来获取像Gemfile中的依赖项?

sbt共享项目之间的依赖关系

如何在 sbt 项目中使用 sbt 插件作为库依赖项?

SBT Native Packager 的条件 JavaAgent 命令

sbt 中库和插件依赖项的不同导入处理策略