summaryrefslogtreecommitdiff
path: root/project/Osgi.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2015-11-24 15:46:19 +0100
committerLukas Rytz <lukas.rytz@typesafe.com>2015-11-24 15:46:19 +0100
commit2890f0b767948dd9a0953b1e669e85dbd45ec0a7 (patch)
treeb714f4b4db41f6c52cb3bfcb9c8e22662a4bdd90 /project/Osgi.scala
parent8eb1d4c29d85aef7828eeb35169e80c085cea93e (diff)
parent2803d0ad50e94a3a88d98d709b7a38a5bbb6a383 (diff)
downloadscala-2890f0b767948dd9a0953b1e669e85dbd45ec0a7.tar.gz
scala-2890f0b767948dd9a0953b1e669e85dbd45ec0a7.tar.bz2
scala-2890f0b767948dd9a0953b1e669e85dbd45ec0a7.zip
Merge pull request #4855 from szeiger/wip/sbt-osgi
Create a full Scala distribution from sbt
Diffstat (limited to 'project/Osgi.scala')
-rw-r--r--project/Osgi.scala68
1 files changed, 68 insertions, 0 deletions
diff --git a/project/Osgi.scala b/project/Osgi.scala
new file mode 100644
index 0000000000..6c0ef74ef5
--- /dev/null
+++ b/project/Osgi.scala
@@ -0,0 +1,68 @@
+import aQute.lib.osgi.Builder
+import aQute.lib.osgi.Constants._
+import java.util.Properties
+import sbt._
+import sbt.Keys._
+import scala.collection.JavaConversions._
+import VersionUtil.versionProperties
+
+/** OSGi packaging for the Scala build, distilled from sbt-osgi. We do not use sbt-osgi because it
+ * depends on a newer version of BND which gives slightly different output (probably OK to upgrade
+ * in the future but for now it would make comparing the sbt and ant build output harder) and does
+ * not allow a crucial bit of configuration that we need: Setting the classpath for BND. In sbt-osgi
+ * this is always `fullClasspath in Compile` whereas we want `products in Compile in packageBin`. */
+object Osgi {
+ val bundle = TaskKey[File]("osgiBundle", "Create an OSGi bundle.")
+ val bundleName = SettingKey[String]("osgiBundleName", "The Bundle-Name for the manifest.")
+ val bundleSymbolicName = SettingKey[String]("osgiBundleSymbolicName", "The Bundle-SymbolicName for the manifest.")
+ val headers = SettingKey[Seq[(String, String)]]("osgiHeaders", "Headers and processing instructions for BND.")
+
+ def settings: Seq[Setting[_]] = Seq(
+ bundleName := description.value,
+ bundleSymbolicName := organization.value + "." + name.value,
+ headers := {
+ val v = VersionUtil.versionProperties.value.osgiVersion
+ Seq(
+ "Bundle-Name" -> bundleName.value,
+ "Bundle-SymbolicName" -> bundleSymbolicName.value,
+ "ver" -> v,
+ "Export-Package" -> ("*;version=${ver}"),
+ "Import-Package" -> ("scala.*;version=\"${range;[==,=+);${ver}}\",*"),
+ "Bundle-Version" -> v,
+ "Bundle-RequiredExecutionEnvironment" -> "JavaSE-1.6, JavaSE-1.7",
+ "-eclipse" -> "false"
+ )
+ },
+ bundle <<= Def.task {
+ bundleTask(headers.value.toMap, (products in Compile in packageBin).value,
+ (artifactPath in (Compile, packageBin)).value, Nil, streams.value)
+ },
+ packagedArtifact in (Compile, packageBin) <<= (artifact in (Compile, packageBin), bundle).identityMap,
+ // Also create OSGi source bundles:
+ artifact in (Compile, packageBin) ~= (_.copy(`type` = "bundle")),
+ packageOptions in (Compile, packageSrc) += Package.ManifestAttributes(
+ "Bundle-Name" -> (description.value + " Sources"),
+ "Bundle-SymbolicName" -> (bundleSymbolicName.value + ".source"),
+ "Bundle-Version" -> versionProperties.value.osgiVersion,
+ "Eclipse-SourceBundle" -> (bundleSymbolicName.value + ";version=\"" + versionProperties.value.osgiVersion + "\";roots:=\".\"")
+ )
+ )
+
+ def bundleTask(headers: Map[String, String], fullClasspath: Seq[File], artifactPath: File,
+ resourceDirectories: Seq[File], streams: TaskStreams): File = {
+ val log = streams.log
+ val builder = new Builder
+ builder.setClasspath(fullClasspath.toArray)
+ headers foreach { case (k, v) => builder.setProperty(k, v) }
+ val includeRes = resourceDirectories.filter(_.exists).map(_.getAbsolutePath).mkString(",")
+ if(!includeRes.isEmpty) builder.setProperty(INCLUDERESOURCE, includeRes)
+ builder.getProperties.foreach { case (k, v) => log.debug(s"bnd: $k: $v") }
+ // builder.build is not thread-safe because it uses a static SimpleDateFormat. This ensures
+ // that all calls to builder.build are serialized.
+ val jar = synchronized { builder.build }
+ builder.getWarnings.foreach(s => log.warn(s"bnd: $s"))
+ builder.getErrors.foreach(s => log.error(s"bnd: $s"))
+ jar.write(artifactPath)
+ artifactPath
+ }
+}