From 509b721d12c909d9298127637a9391bfef6e91b4 Mon Sep 17 00:00:00 2001 From: Josh Rosen Date: Mon, 30 Jul 2012 18:05:13 -0700 Subject: Fix Akka configuration in assembly jar. This resolves an issue where running Spark from the assembly jar would cause a "No configuration setting found for key 'akka.version'" exception. This solution is from the Akka Team Blog: http://letitcrash.com/post/21025950392/ --- project/SparkBuild.scala | 57 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'project') diff --git a/project/SparkBuild.scala b/project/SparkBuild.scala index 726d490738..3603d42a23 100644 --- a/project/SparkBuild.scala +++ b/project/SparkBuild.scala @@ -1,5 +1,7 @@ import sbt._ import Keys._ +import classpath.ClasspathUtilities.isArchive +import java.io.FileOutputStream import sbtassembly.Plugin._ import AssemblyKeys._ @@ -69,12 +71,12 @@ object SparkBuild extends Build { "cc.spray" % "spray-can" % "1.0-M2.1", "cc.spray" % "spray-server" % "1.0-M2.1" ) - ) ++ assemblySettings ++ extraAssemblySettings + ) ++ assemblySettings ++ extraAssemblySettings ++ mergeSettings def replSettings = sharedSettings ++ Seq( name := "spark-repl", libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _) - ) ++ assemblySettings ++ extraAssemblySettings + ) ++ assemblySettings ++ extraAssemblySettings ++ mergeSettings def examplesSettings = sharedSettings ++ Seq( name := "spark-examples" @@ -82,6 +84,57 @@ object SparkBuild extends Build { def bagelSettings = sharedSettings ++ Seq(name := "spark-bagel") + // Fix for "No configuration setting found for key 'akka.version'" exception + // when running Spark from the jar generated by the "assembly" task; see + // http://letitcrash.com/post/21025950392/howto-sbt-assembly-vs-reference-conf + lazy val merge = TaskKey[File]("merge-reference", + "merge all reference.conf") + + lazy val mergeSettings: Seq[Project.Setting[_]] = Seq( + merge <<= (fullClasspath in assembly) map { + c => + // collect from all elements of the full classpath + val (libs, dirs) = + c map (_.data) partition (isArchive) + // goal is to simply concatenate files here + val dest = file("reference.conf") + val out = new FileOutputStream(dest) + val append = IO.transfer(_: File, out) + try { + // first collect from managed sources + (dirs * "reference.conf").get foreach append + // then from dependency jars by unzipping and + // collecting reference.conf if present + for (lib <- libs) { + IO withTemporaryDirectory { + dir => + IO.unzip(lib, dir, "reference.conf") + (dir * "reference.conf").get foreach append + } + } + // return merged file location as task result + dest + } finally { + out.close() + } + }, + + // get rid of the individual files from jars + excludedFiles in assembly <<= + (excludedFiles in assembly) { + (old) => (bases) => + old(bases) ++ (bases flatMap (base => + (base / "reference.conf").get)) + }, + + // tell sbt-assembly to include our merged file + assembledMappings in assembly <<= + (assembledMappings in assembly, merge) map { + (old, merged) => (f) => + old(f) :+(merged, "reference.conf") + } + ) + def extraAssemblySettings() = Seq(test in assembly := {}) ++ Seq( mergeStrategy in assembly := { case m if m.toLowerCase.endsWith("manifest.mf") => MergeStrategy.discard -- cgit v1.2.3