scalacenter / bloop

Bloop is a build server and CLI tool to compile, test and run Scala fast from any editor or build tool.
https://scalacenter.github.io/bloop/
Apache License 2.0
909 stars 201 forks source link

Bloop link does not work for Scala.js projects without a main class #1304

Open MaximeKjaer opened 4 years ago

MaximeKjaer commented 4 years ago

Bug description

bloop link is not able to link Scala.js projects without a main class. It reports the following error:

> bloop link root
[E] No main classes defined in project 'root'

However, Scala.js projects do not always need to have a main class: for instance, a valid use-case is to have no main class, but have methods with @JSExport annotations in order to export functionality to JavaScript code.

Reproduction

I created a simple project with a small build.sbt config:

lazy val root = project
  .in(file("."))
  .enablePlugins(ScalaJSPlugin)
  .settings(
    scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
  )

The project only contains a single Scala file, which JSExports a single hello world function:

import scalajs.js.annotation._

@JSExportTopLevel("HelloWorld")
object HelloWorld {
  @JSExport
  def sayHello(): Unit = {
    println("Hello world!")
  }
}

If I run sbt fastOptJS, sbt produces a bundle from which JS code can import things:

> require("./target/scala-2.12/root-fastopt.js").HelloWorld.sayHello()
Hello world!

Running bloop compile root works as expected, but bloop link root produces the following output:

> bloop link root
[E] No main classes defined in project 'root'

Here is the generated Bloop configuration:

.bloop/root.json ```json { "version": "1.4.0", "project": { "name": "root", "directory": "/home/maxime/code/tmp", "workspaceDir": "/home/maxime/code/tmp", "sources": [ "/home/maxime/code/tmp/src/main/scala-2.12", "/home/maxime/code/tmp/src/main/scala", "/home/maxime/code/tmp/src/main/java", "/home/maxime/code/tmp/target/scala-2.12/src_managed/main" ], "dependencies": [ ], "classpath": [ "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-library.jar", "/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-library_2.12/1.1.0/scalajs-library_2.12-1.1.0.jar" ], "out": "/home/maxime/code/tmp/.bloop/root", "classesDir": "/home/maxime/code/tmp/.bloop/root/scala-2.12/classes", "resources": [ "/home/maxime/code/tmp/src/main/resources", "/home/maxime/code/tmp/target/scala-2.12/resource_managed/main" ], "scala": { "organization": "org.scala-lang", "name": "scala-compiler", "version": "2.12.10", "options": [ "-Xplugin:/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-compiler_2.12.10/1.1.0/scalajs-compiler_2.12.10-1.1.0.jar" ], "jars": [ "/home/maxime/.sbt/boot/scala-2.12.10/lib/jline.jar", "/home/maxime/.sbt/boot/scala-2.12.10/lib/jansi.jar", "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-xml_2.12.jar", "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-reflect.jar", "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-library.jar", "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-compiler.jar" ], "analysis": "/home/maxime/code/tmp/target/streams/compile/bloopAnalysisOut/_global/streams/inc_compile_2.12.zip", "setup": { "order": "mixed", "addLibraryToBootClasspath": true, "addCompilerToClasspath": false, "addExtraJarsToClasspath": false, "manageBootClasspath": true, "filterLibraryFromClasspath": true } }, "java": { "options": [ ] }, "test": { "frameworks": [ { "names": [ "org.scalacheck.ScalaCheckFramework" ] }, { "names": [ "org.specs2.runner.Specs2Framework", "org.specs2.runner.SpecsFramework" ] }, { "names": [ "org.specs.runner.SpecsFramework" ] }, { "names": [ "org.scalatest.tools.Framework", "org.scalatest.tools.ScalaTestFramework" ] }, { "names": [ "com.novocode.junit.JUnitFramework" ] } ], "options": { "excludes": [ ], "arguments": [ ] } }, "platform": { "name": "js", "config": { "version": "1.1.0", "mode": "debug", "kind": "none", "emitSourceMaps": false, "jsdom": false, "toolchain": [ ] }, "mainClass": [ ] }, "resolution": { "modules": [ { "organization": "org.scala-lang", "name": "scala-library", "version": "2.12.10", "configurations": "default", "artifacts": [ { "name": "scala-library", "path": "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-library.jar" }, { "name": "scala-library", "classifier": "sources", "path": "/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.10/scala-library-2.12.10-sources.jar" } ] }, { "organization": "org.scala-js", "name": "scalajs-library_2.12", "version": "1.1.0", "configurations": "default", "artifacts": [ { "name": "scalajs-library_2.12", "path": "/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-library_2.12/1.1.0/scalajs-library_2.12-1.1.0.jar" }, { "name": "scalajs-library_2.12", "classifier": "sources", "path": "/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-library_2.12/1.1.0/scalajs-library_2.12-1.1.0-sources.jar" } ] }, { "organization": "org.scala-lang", "name": "scala-library", "version": "2.12.10", "configurations": "optional", "artifacts": [ { "name": "scala-library", "path": "/home/maxime/.sbt/boot/scala-2.12.10/lib/scala-library.jar" }, { "name": "scala-library", "classifier": "sources", "path": "/home/maxime/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.10/scala-library-2.12.10-sources.jar" } ] } ] }, "tags": [ "library" ] } } ```
jvican commented 4 years ago

Thanks for the descriptive bug report!