No main module initializer was specified (possibly because no or multiple main classes were found) - scala.js

Using the following project structure:
project/build.properties:
sbt.version = 1.1.4
project/plugins.sbt:
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.22")
build.sbt:
enablePlugins(ScalaJSPlugin)
name := "scalajs_example"
version := "0.1"
scalaVersion := "2.12.6"
and src/main/scala/my/Main.scala:
package my
class Main {
def main(args: Array[String]): Unit = {
println("Hello world")
}
}
I get the following error when executing sbt run:
[error] No main module initializer was specified (possibly because no
or multiple main classes were found), but
scalaJSUseMainModuleInitializer was set to true. You can explicitly
specify it either with mainClass := Some(...) or with
scalaJSMainModuleInitializer := Some(...) [error] (Compile /
scalaJSModuleInitializers) No main module initializer was specified
(possibly because no or multiple main classes were found), but
scalaJSUseMainModuleInitializer was set to true. You can explicitly
specify it either with mainClass := Some(...) or with
scalaJSMainModuleInitializer := Some(...)
Adding mainClass := Some("my.Main") to build.sbt and reloading the project did not help, same error remain when tried sbt run (scalaJSMainModuleInitializer := Some(...) - I could not figure out what to put to the ...).

The problem was with the using class Main instead of object Main. After the change, it works as expected:
[info] Running my.Main
Hello world
with or without explicitly specifying mainClass (it seems specifying an invalid main class will still find the only good one).

Related

sbt-native-packager defining multiple mainClasses in different modules

I would like to package multiple docker images, each one having its own mainClass, to ensure the app is running on startup.
lazy val `core` = project.in(file("core"))
.enablePlugins(JavaServerAppPackaging, DockerPlugin)
.settings{
mainClass in Compile := Some("path/to/Core") // Doesn't work
}
lazy val `benchmark` = project.in(file("benchmark"))
.enablePlugins(JavaServerAppPackaging, DockerPlugin)
.settings{
mainClass in Compile := Some("path/to/Benchmark") // Doesn't work
}
This does not work as the mainClasses are not found in the stage step.
When I define mainClass as a global parameter it works, but I can't build two auto-running Docker images this way.
Thanks for your help
I am not experienced with sbt-native-packager but mainClass is the classpath not the file path, so it must be defined as:
mainClass in (Compile, packageBin) := Some("com.bar.baz.Foo")

Problems finding Main class in sub-directories w/SBT assembly

I am attempting to use SBT assembly(0.14.0) to create a fat jar of my Scala project.
My project structure is as follows:
>top
> build.sbt
> api
> src
> main
> scala
> name
> Boot.scala
> other directories
I am trying to set Boot as the main method to be run in the jar.
I have tried using:
baseDirectory in (Compile,run) := file("api")
scalaSource in run := baseDirectory.value / "api"
scalaSource in Compile := baseDirectory(_ / "api")
mainClass in assembly := some("name.Boot")
The jar builds successfully but when running it I receive the error:
Error: Could not find or load main class name.Boot
Going by the snippet you posted, you could try changing
mainClass in assembly := some("name.Boot")
to
mainClass in assembly := Some("name.Boot")
The reason it does not complain is that lower case some refers to something else.
The file path of your mainClass isn't relevant, only the namespace in Scala/Java. Is your main object
package name
object Boot {
def main ...
}
?

Why my usage of `ThisBuild` is not working?

I wrote a simple SBT plugin, which defined a helloMessage, and the default value is None:
lazy val helloMessage = settingKey[Option[String]]("the message for hello")
override def projectSettings = Seq(
helloMessage in ThisBuild := None,
hello := println("Hello from my plugin: " + helloMessage.value)
)
Then in a testing project, I added this plugin, and defined in build.sbt:
helloMessage in ThisBuild := Some("hello from this build")
lazy val root = project in file(".")
lazy val core = project in file("core")
You may notice I used ThisBuild for helloMessage.
But the problem is, when I run ./sbt helloMessage in the testing project, it just outputs a None! Not the message Some("hello from this build") I defined!
But if I delete the two lines:
lazy val root = project in file(".")
lazy val core = project in file("core")
or just the core line, it will output the expected message Some("hello from this build").
Where is wrong? If I have to keep the multi projects, how to fix it?
Start by using buildSettings for in ThisBuild settings, as suggested in the docs.
A possible solution, change:
helloMessage in ThisBuild := None
to
helloMessage in Global := None
I believe the issue is with the initialization order. In your build.sbt file the line helloMessage in ThisBuild := Some("hello from this build") will be executed first. This will set the helloMessage setting in the global (build) scope.
Now, when any of your projects gets initialized it will run the new setting helloMessage in ThisBuild := None. This will overwrite the helloMessage setting in the global scope to be None.
One way to go around this is to remove the ThisBuild from inside your project settings. That is, you keep the ThisBuild scope in your main build.sbt file but keep local scope (helloMessage := None) inside the project settings in your plugin definition.

How to (automatically) inherit settings/tasks from an sbt plugin?

I have an sbt plugin defining tasks that I would like to have available in a Play project, or another sbt project in general. While it might not be best practice, I'd prefer to have these tasks automatically available in the Play project, so that all I need to do is add the sbt plugin via plugins.sbt. But before I can even get that far, I'm having trouble importing tasks at all.
If the plugin's build.sbt is as follows:
name := "sbt-task-test"
version := "1.0.0-SNAPSHOT"
scalaVersion := "2.10.3"
scalaBinaryVersion := "2.10"
organization := "com.example"
sbtPlugin := true
lazy val testTask = taskKey[Unit]("Run a test task.")
testTask := {
println("Running test task..")
}
How can I make testTask available in another sbt project's build.sbt or Build.scala? I've tried following this example to no avail.
My end goal is to use tasks defined like in this blog post, but I'd like to at least get some simpler examples working first. In this case, I'd be adding something like registerTask("testTask", "com.example.tasks.Test", "Run a test task") to build.sbt, however I have the same problem as above.
First, you should put your task definition in the source of the plugin, not the build.sbt. So try this:
build.sbt of the plugin (it defines only how to build the plugin):
name := "sbt-task-test"
version := "1.0.0-SNAPSHOT"
scalaVersion := "2.10.3"
// scalaBinaryVersion := "2.10" // better not to play with this
organization := "com.example"
sbtPlugin := true
src/main/scala/MyPlugin.scala (in the plugin project)
import sbt._
object MyPlugin extends Plugin {
lazy val testTask = taskKey[Unit]("Run a test task.")
override def settings = Seq(
testTask := { println("Running test task..") }
)
}
Overriding settings helps to add the definition of this task to the project scope.
Now you should build and publish the plugin (locally for example) using sbt publishLocal.
Then in the project, where you want to use this plugin:
project/plugins.sbt should contain:
addSbtPlugin("com.example" % "sbt-task-test" % "1.0.0-SNAPSHOT")
This will add testTask key and definition to the scope automatically, so that you can do in the project's directory:
sbt testTask
and it will print Running test task..

Cannot specify main class for both running AND packaging jar in SBT 0.12.3

For some reason I cannot simultaneously specify main class for run and packaging jar in SBT 0.12.3.
The problem is that sbt publish-local doesn't put name of main class to jar's manifest if I don't set it explicitly.
But interestingly enough this
mainClass in (Compile,run) := Some("Hi")
and
mainClass in (Compile,packageBin) := Some("Hi")
work separately but this
mainClass in (Compile,run,packageBin) := Some("Hi")
causes SBT fail with following error
C:\work\test_projects\hw\build.sbt:13: error: reassignment to val
mainClass in (run,Compile,packageBin) := Some("Hi")
^
[error] Type error in expression
Is it a bug or am I missing something ?
The (Compile,run) in
mainClass in (Compile,run) := Some("Hi")
is specifying the two axes of the four axes that a setting has, so (Compile,run,packageBin) doesn't make sense. If you want to grab the value from the other, you could say:
mainClass in (Compile,packageBin) <<= mainClass in (Compile,run)
For more details, check out Getting Started guide.