Search code examples
scalasbtsbt-native-packager

Accumulate subprojects' `discoveredMainClasses`


How can I accumulate all the discoveredMainClasses of a project, along with its dependent sub projects in SBT?

For example, I have a project that looks like

├── bar
│   └── src
│       └── main
│           └── scala
│               └── BarMain.scala
├── build.sbt
├── foo
│   └── src
│       └── main
│           └── scala
│               └── FooMain.scala
├── project
│   └── build.properties
└── root

With one root project that aggregate(foo, bar), I get the following for discoveredMainClasses:

[info] foo/compile:discoveredMainClasses
[info]  List(MainFoo)
[info] bar/compile:discoveredMainClasses
[info]  List(MainBar)
[info] root/compile:discoveredMainClasses
[info]  List()

With one root that only dependsOn(foo, bar) I get

> show discoveredMainClasses
[info] *  

How can I have show root/discoveredMainClasses contain both MainFoo and MainBar?

For context, I have other tasks that depend on the output from discoveredMainClasses namely the makeBashScripts in native-packager


Solution

  • The core idea is to create a module that depends on all all the sub modules you want to include and configure all settings on this module.

    This results in a build.sbt like this

    lazy val root = project.in(file("."))
      // package the root module, but not the sub modules
      .enablePlugins(JavaAppPackaging)
      .settings(
        name := "application",
        // add the discoveredMainClasses to this project
        discoveredMainClasses in Compile ++= (discoveredMainClasses in (client, Compile)).value,
        discoveredMainClasses in Compile ++= (discoveredMainClasses in (server, Compile)).value
      )
      // include these modules in the resulting package
      .dependsOn(client, server)
    
    lazy val client = project.in(file("client"))
      .settings(
        name := "client"
      )
    
    lazy val server = project.in(file("server"))
      .settings(
        name := "server"
      )
    

    The (discoveredMainClasses in (client, Compile)).value accesses the discoveredMainClasses from the client project in the Compile scope.

    You can build and run your applications with

    $ sbt universal:stage
    $ ./target/universal/stage/bin/client-app
    $ ./target/universal/stage/bin/server-app
    

    A running example can be found here.

    cheers, Muki