project/OSGi.scala (107 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* license agreements; and to You under the Apache License, version 2.0:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* This file is part of the Apache Pekko project, which was derived from Akka.
*/
/*
* Copyright (C) 2016-2022 Lightbend Inc. <https://www.lightbend.com>
*/
import com.github.sbt.osgi.OsgiKeys
import com.github.sbt.osgi.SbtOsgi._
import sbt._
import sbt.Keys._
import sbtassembly.AssemblyKeys.assembly
import net.bzzt.reproduciblebuilds.ReproducibleBuildsPlugin
object OSGi {
// The included osgiSettings that creates bundles also publish the jar files
// in the .../bundles directory which makes testing locally published artifacts
// a pain. Create bundles but publish them to the normal .../jars directory.
lazy val osgiSettings =
defaultOsgiSettings ++ Seq(
Compile / packageBin := {
val bundle = OsgiKeys.bundle.value
// This normally happens automatically when loading the
// sbt-reproducible-builds plugin, but because we replace
// `packageBin` wholesale here we need to invoke the post-processing
// manually. See also
// https://github.com/raboof/sbt-reproducible-builds#sbt-osgi
ReproducibleBuildsPlugin.postProcessJar(bundle)
},
// This will fail the build instead of accidentally removing classes from the resulting artifact.
// Each package contained in a project MUST be known to be private or exported, if it's undecided we MUST resolve this
OsgiKeys.failOnUndecidedPackage := true,
// By default an entry is generated from module group-id, but our modules do not adhere to such package naming
OsgiKeys.privatePackage := Seq(),
// Explicitly specify the version of JavaSE required #23795 (rather depend on
// figuring that out from the JDK it was built with)
OsgiKeys.requireCapability := "osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(version>=1.8))\"",
// Recent versions of BND create corrupted jars so use JDK jar instead, see https://github.com/sbt/sbt-osgi/pull/81
OsgiKeys.packageWithJVMJar := true)
lazy val actor = osgiSettings ++ Seq(
OsgiKeys.exportPackage := Seq("org.apache.pekko*"),
OsgiKeys.privatePackage := Seq("org.apache.pekko.osgi.impl"),
// pekko-actor packages are not imported, as contained in the CP
OsgiKeys.importPackage := (osgiOptionalImports.map(optionalResolution)) ++ Seq(
"!sun.misc",
scalaJava8CompatImport(),
scalaVersion(scalaImport).value,
configImport(),
"*"),
// dynamicImportPackage needed for loading classes defined in configuration
OsgiKeys.dynamicImportPackage := Seq("*"))
lazy val actorTyped = exports(Seq("org.apache.pekko.actor.typed.*"))
lazy val cluster = exports(Seq("org.apache.pekko.cluster.*"))
lazy val clusterTools = exports(Seq("org.apache.pekko.cluster.singleton.*", "org.apache.pekko.cluster.client.*",
"org.apache.pekko.cluster.pubsub.*"))
lazy val clusterSharding = exports(Seq("org.apache.pekko.cluster.sharding.*"))
lazy val clusterMetrics =
exports(Seq("org.apache.pekko.cluster.metrics.*"), imports = Seq(kamonImport(), sigarImport()))
lazy val distributedData = exports(Seq("org.apache.pekko.cluster.ddata.*"))
lazy val osgi = exports(Seq("org.apache.pekko.osgi.*"))
lazy val protobufV3 = osgiSettings ++ Seq(
OsgiKeys.importPackage := Seq(
"!sun.misc",
scalaJava8CompatImport(),
scalaVersion(scalaImport).value,
configImport(),
"*"),
OsgiKeys.exportPackage := Seq("org.apache.pekko.protobufv3.internal.*"),
OsgiKeys.privatePackage := Seq("google.protobuf.*"),
// Since the jar's generated by sbt-assembly are not added in dependencyClasspath
// we need to manually add it to sbt-osgi so it can pick it up. Note that since this
// is a fatjar from sbt-assembly we don't have to worry about incorrect osgi
// Import-Package header since the protobuf-V3 sbt-project has no real dependencies
// (including typical ones such as scala runtime)
OsgiKeys.explodedJars := Seq(assembly.value))
lazy val jackson = exports(Seq("org.apache.pekko.serialization.jackson.*"))
lazy val remote = exports(Seq("org.apache.pekko.remote.*"))
lazy val stream =
exports(
packages = Seq("org.apache.pekko.stream.*", "com.typesafe.sslconfig.pekko.*"),
imports = Seq(
scalaJava8CompatImport(),
scalaParsingCombinatorImport(),
sslConfigCoreImport("com.typesafe.sslconfig.ssl.*"),
sslConfigCoreImport("com.typesafe.sslconfig.util.*"),
"!com.typesafe.sslconfig.pekko.*"))
lazy val streamTestkit = exports(Seq("org.apache.pekko.stream.testkit.*"))
lazy val slf4j = exports(Seq("org.apache.pekko.event.slf4j.*"))
lazy val persistence = exports(
Seq("org.apache.pekko.persistence.*"),
imports = Seq(optionalResolution("org.fusesource.leveldbjni.*"), optionalResolution("org.iq80.leveldb.*")))
lazy val persistenceTyped = exports(Seq("org.apache.pekko.persistence.typed.*"))
lazy val persistenceQuery = exports(Seq("org.apache.pekko.persistence.query.*"))
lazy val testkit = exports(Seq("org.apache.pekko.testkit.*"))
lazy val discovery = exports(Seq("org.apache.pekko.discovery.*"))
lazy val coordination = exports(Seq("org.apache.pekko.coordination.*"))
lazy val osgiOptionalImports = Seq(
// needed because testkit is normally not used in the application bundle,
// but it should still be included as transitive dependency and used by BundleDelegatingClassLoader
// to be able to find reference.conf
"org.apache.pekko.testkit")
def exports(packages: Seq[String] = Seq(), imports: Seq[String] = Nil) =
osgiSettings ++ Seq(
OsgiKeys.importPackage := imports ++ scalaVersion(defaultImports).value,
OsgiKeys.exportPackage := packages)
def defaultImports(scalaVersion: String) =
Seq(
"!sun.misc",
pekkoImport(),
configImport(),
"!scala.compat.java8.*",
"!scala.util.parsing.*",
scalaImport(scalaVersion),
"*")
def pekkoImport(packageName: String = "org.apache.pekko.*") = versionedImport(packageName, "1.1", "1.2")
def configImport(packageName: String = "com.typesafe.config.*") = versionedImport(packageName, "1.4.0", "1.5.0")
def scalaImport(version: String) = {
val packageName = "scala.*"
val ScalaVersion = """(\d+)\.(\d+)\..*""".r
val ScalaVersion(epoch, major) = version
versionedImport(packageName, s"$epoch.$major", s"$epoch.${major.toInt + 1}")
}
def scalaJava8CompatImport(packageName: String = "scala.compat.java8.*") =
versionedImport(packageName, "1.0.2", "1.0.2")
def scalaParsingCombinatorImport(packageName: String = "scala.util.parsing.combinator.*") =
versionedImport(packageName, "1.1.0", "1.2.0")
def sslConfigCoreImport(packageName: String = "com.typesafe.sslconfig") =
versionedImport(packageName, "0.4.0", "1.0.0")
def sslConfigCoreSslImport(packageName: String = "com.typesafe.sslconfig.ssl.*") =
versionedImport(packageName, "0.4.0", "1.0.0")
def sslConfigCoreUtilImport(packageName: String = "com.typesafe.sslconfig.util.*") =
versionedImport(packageName, "0.4.0", "1.0.0")
def kamonImport(packageName: String = "kamon.sigar.*") =
optionalResolution(versionedImport(packageName, "1.6.5", "1.6.6"))
def sigarImport(packageName: String = "org.hyperic.*") =
optionalResolution(versionedImport(packageName, "1.6.5", "1.6.6"))
def optionalResolution(packageName: String) = "%s;resolution:=optional".format(packageName)
def versionedImport(packageName: String, lower: String, upper: String) = s"""$packageName;version="[$lower,$upper)""""
}