mill-osgi - Build OSGi Bundles with mill


// default imports
import mill._, mill.scalalib._
// This import the mill-osgi plugin
import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.1.2`
import de.tobiasroeser.mill.osgi._

object project extends ScalaModule with OsgiBundleModule {

  def bundleSymbolicName = "com.example.project"

  def osgiHeaders = T{ super.osgiHeaders().copy(
    `Export-Package`   = Seq("com.example.api"),
    `Bundle-Activator` = Some("com.example.internal.Activator")

  // other settings ...


Use mill 0.5.7 or newer, to build the OSGi bundle.

$ mill project.osgiBundle
[27/38] project.compile
[info] Compiling 1 Scala source to /tmp/project/out/project/compile/dest/classes ...
[info] Done compiling.
[38/38] project.osgiBundle

Please note, that the default jar target is also overriden, so that it depends on osgiBundle and in fact it returns the exact same bundle.

$ mill show project.jar
[1/1] show
[39/39] project.jar


To produce OSGi bundles, your module has to implement de.tobiasroeser.mill.osgi.OsgiBundleModule.

Configuration options
  • def bundleVersion: T[String] - The bundle version. If the module is a PublishModule, it defaults to PublishModule.publishVersion.

  • def bundleSymbolicName: T[String] - The bundle symbolic name. If the module is a PublishModule, it derives a default from from PublishModule.artifactMetadata.

  • def reproducibleBundle: T[Boolean] - Create a reproducible bundle file. To achieve that, some properties of the resulting JAR will be adjusted, e.g. sorted manifest and JAR entries, unified file create time, etc. Defaults to true.

  • def embeddedJars: T[Seq[PathRef]] - Embed these JAR files and also add them to the bundle classpath.

  • def explodedJars: T[Seq[PathRef]] - Embed the content of the given JAR files into the bundle.

  • def exportContents: T[Seq[String]] - Exports the given packages but does not try to include them from the class path. The packages should be loaded with alternative means.

  • def osgiHeaders: T[OsgiHeaders] - Various OSGi headers defining the OSGi bundle. You should always use OsgiHeaders.copy to customize some headers to not loose useful defaults.

  • def includeSources: T[Boolean] - Iff true include sources in the final bundle under OSGI-OPT/src. Defaults to false.

  • def includeResource: T[Seq[String]] - Resources to include into the final bundle. Defaults to include resources defined with JavaModule.resources.

  • def additionalHeaders: T[Map[String, String]] - Additional headers to add to the bundle manifest. All headers added here will be applied after osgiHeaders and thus override previously defined values. Be careful to not add standard OSGi headers here, but via osgiHeaders.

  • def osgiBundle: T[PathRef] - Build the OSGi Bundle.


By default mill-osgi tries to provide some sensible default values based on the current build setup.

Export-Package and Private-Package

By default, all output packages of the compile task will be added to the Private-Package header. No packages will be exported via Export-Package.


If the module does not extends PublishModule, the bundle symbolic name will be initializes with JavaModule.artifactId.

If the module extends PublishModule, the Bundle-SymbolicName is computed using from PublishModule.pomSettings.organization and JavaModule.artifactId. If the organization or the last segment of the organization is a prefix of the artifactName, than that redundant part is omitted.


Apache License, version 2

Version Compatibility Matrix

Mill is still in active development, and has no stable API yet. Hence, not all mill-osgi versions work with every mill version.

The following table shows a matrix of compatible mill and mill-osgi versions.

Table 1. Version Compatibility Matrix
mill-osgi mill


0.5.7 - 0.5.9


0.5.7 - 0.5.9


0.3.6 - 0.5.3


0.3.6 - 0.5.3












mill-osgi 0.1.2 - 2020-01-19

  • Use the artifactId as base for the default Bundle-SymbolicName

  • Added exportContents target

See list of commits since 0.1.1.

mill-osgi 0.1.1 - 2020-01-08

  • Version bump mill API to 0.5.7

  • Version bump to bndlib-4.3.1

  • Version bump to scala 2.12.10

See list of commits since 0.1.0.

mill-osgi 0.1.0 - 2019-09-13

  • Version bump to bndlib-4.2.0

  • Fixed handling of empty compile result

  • osgiBundle now produces a proper named jar (symbolic name and version)

  • Some internal improvements

  • Improved documentation

mill-osgi 0.0.6 - 2019-02-15

  • Version bump to mill-0.3.6 and use of new mill-api

  • Improved integration test setup

  • Added runtime detection of possibly incompatible mill runtime version

mill-osgi 0.0.5 - 2018-12-14

  • Reworked integration test setup

  • Version bump to mill-0.3.5 and use of os-lib

mill-osgi 0.0.4 - 2018-11-20

  • Added explicit scala-library dependency to released pom.xml

mill-osgi 0.0.3 - 2018-11-02

  • Changed packaging / pom dependency information so that loading into mill excludes mill dependencies

mill-osgi 0.0.2 - 2018-10-18

  • Improved default bundle symbolic name algorithm

  • Added support for -includeresource

  • Improved source docs

  • Don’t add non-existing resources to avoid bnd warnings/errors

  • Add more default headers when project is a PublishModule

mill-osgi 0.0.1 - 2018-10-10

  • Initial early release to gain user feedback