【问题标题】:dynamically changing library dependencies in sbt build file from provided etc从提供的等动态更改 sbt 构建文件中的库依赖项
【发布时间】:2016-06-29 23:28:43
【问题描述】:

我们在 Scala 应用程序中经常使用 spark。如果我在本地测试我的库依赖项是:

  libraryDependencies += "org.apache.spark" % "spark-core_2.10" % "1.6.1",
 libraryDependencies += "org.apache.spark" % "spark-sql_2.10" % "1.6.1" ,

而我正在构建一个 jar 来部署我使用:

  libraryDependencies += "org.apache.spark" % "spark-core_2.10" % "1.6.1" % "provided",
libraryDependencies += "org.apache.spark" % "spark-sql_2.10" % "1.6.1" % "provided",

由于工作的性质,我们有时可能不得不在尝试不同的事情时来回翻转几次。在某些时候我不可避免地忘记更改构建文件并最终浪费时间,这不是很多时间,但足以促使我提出这个问题。

那么,有没有人知道让构建文件根据触发器更新提供的值的方法(不包括记住“做正确的事”)?例如读取 test 或 live 的配置选项?

提前致谢。

【问题讨论】:

  • 如果您只使用第二个版本进行测试和部署怎么办?这应该工作......
  • 您好,我已经提供了答案,如果这是您所期望的,请告诉我。

标签: scala apache-spark sbt sbt-assembly


【解决方案1】:

在我的示例中,我刚刚使用两个不同的 spark 版本执行了动态构建。我需要根据具体情况使用两个不同的版本。

您可以通过两种方式做到这一点。由于您需要以一种或其他方式提供输入,因此您需要使用命令行参数。

1) 自行使用 build.sbt。

a) 你可以定义一个名为“sparkVersion”的参数

b) 在 build.sbt 中读取该参数,(您可以在 build.sbt 中编写 scala 代码,它会在构建时以任何方式编译为 scala。)

c) 执行基于条件的依赖,如下所示。

val sparkVersion = Option(System.getProperty("sparkVersion")).getOrElse("default")

if(sparkVersion == "newer"){
    println(" newer one");
    libraryDependencies += "org.apache.spark" %% "spark-core" % "1.6.0" 
}else{
    println(" default one");
    libraryDependencies += "org.apache.spark" %% "spark-core" % "1.6.0" % "provided"
}

您可以随意使用所有构建选项。

2) 使用 build.scala 文件。您可以在 /project/build.scala 中创建 build.scala 文件

您可以编写下面的代码。

import sbt._
import Keys._

object MyBuild extends Build {  
  val myOptionValue = Option(System.getProperty("scalaTestVersion")).getOrElse("defaultValue")

  val depVersion = if(myOptionValue == "newer"){
    println(" asked for newer version" );
    "2.2.6"
  }else{
    println(" asked for older/default version" );
    "2.2.0"
  }

   val dependencies = Seq(
    "org.scalatest" %% "scalatest" % depVersion % "test"
  )

   lazy val exampleProject = Project("SbtExample", file(".")).settings(
    version       := "1.2",
    scalaVersion  := "2.10.4",
    libraryDependencies ++= dependencies
  )

}

在此之后,只需运行如下构建命令。

sbt clean compile -DsparkVersion=newer -DscalaTestVersion=newer

我已经为两者提供了构建命令。您可以选择其中之一,并且只提供一个选项。 如果您需要任何帮助,请写信给我。

为了解决构建中的重复项,您可以在 build.sbt 中添加以下一项

mergeStrategy in assembly := {
  case m if m.toLowerCase.endsWith("manifest.mf")          => MergeStrategy.discard
  case m if m.toLowerCase.matches("meta-inf.*\\.sf$")      => MergeStrategy.discard
  case "log4j.properties"                                  => MergeStrategy.discard
  case "log4j-defaults.properties"                         => MergeStrategy.discard
  case m if m.toLowerCase.startsWith("meta-inf/services/") => MergeStrategy.filterDistinctLines
  case "reference.conf"                                    => MergeStrategy.concat
  case _                                                   => MergeStrategy.first
}

你会明白 sbt 是多么的好和神奇。

【讨论】:

  • 太棒了!太感谢了。我明天会玩,但看起来我要重写整个构建文件。 :D
  • 您好,Srini,我刚刚尝试实施您的解决方案,但遇到了困难。我通常运行来构建 jar 的命令是“sbt 程序集”,其中 spark 文件标记为提供。使用您的解决方案我收到一个重复数据删除错误,我尝试使用 -D 变量进行各种排列,但它要么告诉我它没有定义或错误。
  • 好的,那么你需要添加逻辑来解决重复。您可以简单地添加答案中提供的编辑。
  • 嗨,斯里尼,没有,没有。这类似于我的合并策略,但您的建议更彻底,但仍然失败。 :( 我的构建逻辑是: //live or test dependencies if (liveOrTest == "live") { println("Setting Live Values") libraryDependencies += "org.apache.spark" % "spark-core_2.10" % “1.6.1” % “提供” libraryDependencies += “org.apache.spark” % “spark-sql_2.10” % “1.6.1” % “提供” } else { libraryDependencies += “org.apache.spark” % "spark-core_2.10" % "1.6.1" libraryDependencies += "org.apache.spark" % "spark-sql_2.10" % "1.6.1" },
  • 嗨斯里尼,很抱歉回复晚了,它疯了:) 如果我运行 sbt assembly -DliveOrTest=live;错误是:[error] deduplicate: different file contents found in the following: [error] C:\Users\Steve\.ivy2\cache\org.apache.hadoop\hadoop-yarn-common\jars\hadoop-yarn- common-2.2.0.jar:org/apache/hadoop/yarn/util/package-info.class 以及许多其他重复数据删除错误。
猜你喜欢
  • 2013-11-07
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 2016-12-24
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
相关资源
最近更新 更多