Sbt / metals error: No build target for:

metals output error:

No build target for: /Users/john/projects/testgame/core/src/main.scala

root structure

├── build.sbt
├── core
│   └── src
│       └── main.scala

build.sbt

lazy val core = project.in(file("."))
   .settings(
      name := "core",
      scalaVersion := "3.6.2",
      scalacOptions ++= Seq(
         "-language:experimental.namedTuples"
      ),
   )

What is the issue?

1 Like

It should be core/src/main/main.scala according to the sbt standard layout (same as with maven)

3 Likes

Also I think you should have project.in(file("core")) or perhaps just project if you want the core subproject to be located in the core directory.

2 Likes

For future readers: what solved the error for me was specifying the entry point by

Compile / scalaSource := baseDirectory.value / "core" / "src",

or changing the base to core = project.in(file("core")) with the entry as

Compile / scalaSource := baseDirectory.value / "src",

Since I was wanting to avoid the verbose java-style folder structure and keep it simpler like other languages have.

2 Likes

I think if the project is in(file(".")), it is the root project and default source position would be src/main/scala/main.scala. Unless the project included multiple modules, I see no need to place it in the additional directory.

As suggested by @Jasper-M, if the sources should be located in core directory, a natural thing would be to use just project or project.in(file("core")), which is the same thing if the project variable is called core, and then the default source position would then be core/src/main/scala/main.scala.

Overriding scalaSource is always possible, or you can manipulate unmanagedSourceDirectories , e.g. in my project I use this to add additional source folder:

  Compile / unmanagedSourceDirectories ++= Seq((ThisBuild / baseDirectory).value / "shared" / "src" / "main" / "scala"),
  Test / unmanagedSourceDirectories  ++= Seq((ThisBuild / baseDirectory).value / "shared" / "src" / "test" / "scala"),

Point was that I don’t want core/src/main/scala/main.scala, that is a verbose java-ism that I want to avoid. I simply want core/src/main.scala or src/core/main.scala like I do in every other language. Setting this should not be complicated in a build tool, yet it always causes me great confusion every few months in SBT where I have to scurrage for blog posts or internet chatrooms on how to fix it – like tonight, where I am once again getting “no build target found” with zero additional information in the error message in my project :roll_eyes:.

Unfortunately, it would be hard to change in sbt currently, but Scala CLI already allows for more relaxed directory structure if you want, but that can only be done for simpler single module projects.

2 Likes

I know it is possible as I have done it before. But something broke a few days ago. Do you see any problem in my build.sbt?

import org.scalajs.linker.interface.ModuleSplitStyle

lazy val livechart = project.in(file("src"))
  .enablePlugins(ScalaJSPlugin)
  .settings(
    scalaVersion := "3.6.2",

    scalacOptions += "-Yexplicit-nulls",
    scalacOptions += "-experimental",
    Compile / scalaSource := baseDirectory.value,
    scalaJSUseMainModuleInitializer := true,
    scalaJSLinkerConfig ~= {
      _.withModuleKind(ModuleKind.ESModule)
        .withModuleSplitStyle(
          ModuleSplitStyle.SmallModulesFor(List("livechart")))
    },
    libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.8.0",
  )

given a repo structure of

.
├── build.sbt
├── src
│   ├── main.scala

?
Getting

no build target for /Users/john/myproject/src/main.scala
no build target for /Users/john/myproject/build.sbt
no build target found for /Users/john/myproject/build.sbt. Using presentation compiler with project's scala-library version: 3.3.4

Is there anything else in the logs? Looks like we haven’t managed to connect to the build server correctly and it’s not giving us information about the sources.

Could it be related to the ScalaJS plugin? If not, then the best is to remove it and further minimize the reproducer.
If yes, then likely there is the “problem”.

Having said that, I still think wasting time and effort in avoid a couple of directories is a bad idea.

This is the complete output for Metals

Metals version: 1.5.1
Using coursier located at /opt/homebrew/bin/coursier
Searching for Java on PATH. Found java executable under /usr/bin/java that resolves to /usr/bin/java
Using Java Home: /opt/homebrew/Cellar/openjdk/23.0.1/libexec/openjdk.jdk/Contents/Home
INFO  logging to files /Users/john/myproject/.metals/metals.log
INFO  Started: Metals version 1.5.1 in folders '/Users/john/myproject' for client Cursor 1.96.2.
Initializing Scala Debugger
Release notes was not shown: not showing release notes since they've already been seen for your current version
INFO  Database: jdbc:h2:file:/Users/john/myproject/.metals/metals (H2 2.3)
INFO  Successfully validated 6 migrations (execution time 00:00.012s)
INFO  Current version of schema "PUBLIC": 6
INFO  Schema "PUBLIC" is up to date. No migration necessary.
INFO  Attempting to connect to the build server...
INFO  Found a Bloop server running
INFO  no build target found for /Users/john/myproject/build.sbt. Using presentation compiler with project's scala-library version: 3.3.4
INFO  tracing is disabled for protocol BSP, to enable tracing of incoming and outgoing JSON messages create an empty file at /Users/john/myproject/.metals/bsp.trace.json or /Users/john/myprojects/org.scalameta.metals/bsp.trace.json
INFO  time: Connected to build server in 5.18s
INFO  Connected to Build server: Bloop v2.0.8
INFO  running doctor check
INFO  java targets: 
INFO  Database: jdbc:h2:file:/Users/john/myprojectcation Support/metals/metals (H2 2.3)
INFO  Successfully validated 1 migration (execution time 00:00.001s)
INFO  Current version of schema "PUBLIC": 1
INFO  Schema "PUBLIC" is up to date. No migration necessary.
INFO  time: indexed workspace in 1.16s
WARN  no build target for: /Users/john/myproject/build.sbt
INFO  no build target found for /Users/john/myproject/build.sbt. Using presentation compiler with project's scala-library version: 3.3.4
INFO  no build target found for /Users/john/myproject/src/foo/foo.scala. Using presentation compiler with project's scala-library version: 3.3.4
INFO  no build target found for /Users/john/myproject/src/main.scala. Using presentation compiler with project's scala-library version: 3.3.4

I just now decided to give in and go with src/main/scala/ structuring, so I ran git mv src/X src/main/scala/ on all of my files to get them in the expected place, reloaded vscode, ran metals: clear caches and reimport, and now I look at the logs and I see

no build target found for /Users/john/myproject/src/main/scala/main.scala. Using presentation compiler with project's scala-library version: 3.3.4
Missing project 'livechart' may cause compilation issues in project 'myproject'

with my build.sbt

import org.scalajs.linker.interface.ModuleSplitStyle

lazy val livechart = project.in(file("."))
  .enablePlugins(ScalaJSPlugin)
  .settings(
    scalaVersion := "3.6.2",
    scalacOptions += "-Yexplicit-nulls",
    scalacOptions += "-experimental",
    scalaJSUseMainModuleInitializer := true,
    scalaJSLinkerConfig ~= {
      _.withModuleKind(ModuleKind.ESModule)
        .withModuleSplitStyle(
          ModuleSplitStyle.SmallModulesFor(List("livechart")))
    },

    libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.8.0",
  )

and tree showing

.
├── src
│   ├── main
│   │   └── scala
│   │       ├── main.scala

???

When changing the build definition you must later reimport the build to let Bloop know about the changes. In the first log it doesn’t see to finish indexing, it should log how much time it took and really only afterwards metals will be able to work fully

The Mill build tool uses the layout you describe by default for Scala. It works great. Maybe give it a try if you’re not too wedded to SBT!

1 Like

I would like to try it out, I hear good things, but I haven’t seen an easy quick-start for getting a vite scalajs template up and running with mill in a minute or two, I only saw walkthroughs. The “how” is not important to me, I just want the repo up and running. Would like something similar to sbt new scala/scala3.g8, … bun create vite, … npx create-react-app etc. an up-to-date git repo I can clone. Is there something like that for mill and scalajs/vite?

I found GitHub - vitaliis/ScalaJS-Mill-WebApp: An example of scala.js app built using Mill build tool but I don’t think this uses vite?

There’s a Mill Scalajs Vite example GitHub - lolgab/scalajs-vite-example: Example on how to use Vite with Scala.js that seems relatively recently updated, can clone it and try it out

Now you may have to fiddle with Mill to make it do what you want, but it seems like you’re already fiddling with SBT a lot anyway. Whether Mill requires more or less fiddling for your use case is an empirical question I can’t answer up front, but it could be worth a shot

1 Like

I have clicked reimport. I’ve closed and re-opened vscode. I’ve rm -rf nuked the cache folders. I am still getting this No build target error. Zero error highlighting in the IDE.

OK now I see

ERROR Bloop 'bsp' command exited with code 1. Something may be wrong with the current configuration.Running the cleanecommand to clear the working directory and remove caches might help.

Which command is this? Is it not the GUI interaction Metals: clear caches and reimport project?

I would offer a +1 for that mill template, there is another by the same author which goes full stack and I’ve had a good experience with.

I had desire for a zero-config-reload-on-change approach and attempted a CLI tool for my own use which hooks into scala-cli.

https://github.com/Quafadas/live-server-scala-cli-js

I use it for small experiments in scala-js and enjoy it very much for that. I would note it doesn’t offer the reliability / extensibility you’ll get from a successfully configured mill / sbt / vite setup, but it either works instantly, or not :-).

If you are feeling adventurous in a terminal.

scala-cli --version && \
cs version && \
git clone https://github.com/Quafadas/viteless.git && \
cd viteless && \
cs launch io.github.quafadas:sjsls_3:0.2.5

If that isn’t live reloading in <20 seconds, then I wouldn’t spend more time on it…

1 Like

OK apparently I needed to run sbt bloopInstall after nuking the .bsp/.bloop (even though I had already ran sbt ~fastLinkJS which looked successful). Please, someone, make and contribute a singlular command sbt reset that will nuke all cache files for this conglomerate of micro-services scala uses (bsp bloop metals sbt) and restart all of them. This trial-and-error process of nuking x cache folders and trying y amount of commands and restarting vscode/metals and (then trying different permutations of those to see what order it needed to be done in) has wasted so many hours of my life already. If stale caches are frequently a culprit in the ecosystem, a catch-all sort of command to exhaustively refresh all of them is a good idea.

1 Like