Play / sbt: What are these 2 Scala sources that are always compiled on when restarting on Code change - scala

Whenever I change code and Play does a restart, it always compiles 2 Scala sources, like:
[info] Compiling 2 Scala sources to /Users/mpa/dev/myplayproject/server/target/scala-2.13/classes ...
Only after that the sources I changed compiles.
What are these 2 Sources?
Is there a way this can be avoided?

With the tip of #cbley I found the problematic class:
BuildInfo.scala from the sbt-buldinfo Plugin. By default on every compile it creates a new timestamp, which then causes a recompile of BuildInfo.scala.
I actually had a similar problem with scoverage - see here: scoverage: Combine Coverage from test and it:test
Adding the accepted answer from there fixed the problem:
lazy val buildTime: SettingKey[String] = SettingKey[String]
("buildTime", "time of build")
ThisBuild / buildTime := ZonedDateTime.now(ZoneOffset.UTC).toString
buildInfoKeys :=
Seq[BuildInfoKey](
name,
version,
scalaVersion,
sbtVersion,
buildTime
)

Related

sbt subProject: dependsOn

I have the following build.sbt with two sub projects. Everything compiles and runs fine.
One is a thin scala play project. dataextractor has a lot of util classes I want to call in the play project.
However, the configurarion below still leads to the following compilation error:
[error]
/Users/foo.bar/_vws/com.corp.enablement.scripts/sirf_extract_serve/tools_sirf_server/app/corp/tools/es_result_server/service/SystemInitializer.scala:6:21:
object dataextraction is not a member of package corp.tools [error]
import corp.tools.dataextraction.providers.confluence
This is my first sbt multi-project. Advice would be genuinley appreciated
lazy val tools_dataextractor = (project in file("tools_dataextractor")).settings(
Defaults.itSettings,
libraryDependencies += scalatest % "it,test",
name := "corp_tools_dataextractor",
version := "0.1",
mainClass in Compile := Some("corp.tools.ExtractionStartUp")
)
lazy val tools_sirf_server = (project in file("tools_sirf_server")).settings(
).enablePlugins(PlayScala).dependsOn(tools_dataextractor)
lazy val root = (project in file("."))
.aggregate(tools_dataextractor, tools_sirf_server)
The configuration looks good.
2 possibilities what the problem might be:
You are in a sbt-console and haven't reloaded the console after you changed build.sbt
You work with Intellij and did not reload the sbt projects
If this does not help - adjust your question with the steps you take.
OK, the answer is neophyte error.
I had a build.sbt in the root and a build.sbt in each sub project (which is permissible).
Everything will built fine.... Until I started adding dependencies from one sub-project to another. In this case, the super build.sbt "dependsOn" is ignored and compilation errors occur.
Side note, the main reason for keeping sub-project build.sbt was simply laziness. It took half a day to get everything working in a single build.sbt at the root level. However, it is defintiely worth the effort.

scoverage: Combine Coverage from test and it:test

I splitted my Unit- and Integration-Tests with a Filter:
lazy val FunTest = config("it") extend Test
def funTestFilter(name: String): Boolean = name endsWith "Spec"
def unitTestFilter(name: String): Boolean = name endsWith "Test"
...
testOptions in Test := Seq(Tests.Filter(unitTestFilter)),
testOptions in FunTest := Seq(Tests.Filter(funTestFilter)),
...
So I can do something like that:
sbt clean coverage test dockerComposeUp it:test dockerComposeStop coverageReport
Sadly that kills all my Coverage, only the generated BuildInfo has a Coverage.
Using only sbt clean coverage test coverageReport or sbt clean coverage it:test coverageReport work as expected.
The whole project can be found here: https://github.com/pme123/play-binding-form
scoverage Version: 1.5.1
SBT supports incremental compilation, but Scoverage does not support it. Scoverage clears instrumentation information before compilation starts and starts instrumentation process from scratch every time. Compilation of a subset of all classes with Scoverage enabled will result in wrong coverage reports.
In this case sbt-buldinfo plugin is enabled in server module. It registers source generator, which is executed before every compilation and generates server/target/scala_2.12/src_managed/main/sbt-buildinfo/BuildInfo.scala file.
SBT BuildInfo plugin is smart enough to regenerate this file only when its content changes, but since BuildInfoOption.BuildTime is included in buildInfoOptions setting,
this file is regeneraged before every compilation.
When it comes to compilation process, compiler finds one modified file (BuildInfo.scala) every time and starts incremental compilation of this one file. Scoverage clears its previous instrumentation information and saves only information about BuildInfo.scala file.
In case of execution like sbt clean coverage test dockerComposeUp it:test dockerComposeStop coverageReport the first compilation process is part of test task, and the second one it:test task. That's why there is no problem, when they are used separately.
Docker has nothing to do with our problem.
To fix the problem you have to prevent from BuildInfo.scala file regeneration on every compilation, at least when coverage is enabled.
I did it by modifying project/Settings.scala file in this way:
private lazy val buildInfoSettings = Seq(
buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion),
buildInfoOptions ++= { if (coverageEnabled.value) Seq() else Seq(BuildInfoOption.BuildTime) }, // <-- this line was changed
buildInfoOptions += BuildInfoOption.ToJson,
buildInfoPackage := "pme123.adapters.version"
)
buildInfoOptions does not include BuildTime option when coverage is turned on.
It doesn't look elegeant, but it works. You can probably find better way.
instead of having different buildinfo objects depending on the phase, which could lead to compilation errors, you can use your own build time.
lazy val buildTime: SettingKey[String] = SettingKey[String]("buildTime", "time of build")
ThisBuild / buildTime := ZonedDateTime.now(ZoneOffset.UTC).toString
buildInfoKeys :=
Seq[BuildInfoKey](
name,
version,
scalaVersion,
sbtVersion,
buildTime
)
This should resolve this issue.
I have this configuration in a project of mine because I wanted a better control over the way the date is formatted, and I don't have the same issue

app-fastopt.js no longer properly added to resources after upgrading

I have been updating a project to scala 2.12, and one of my last remaining problems is that the fastOptJS task no longer seems to be providing the recompiled scala.js files to the new build.
I have the following lines in my build.sbt file:
lazy val appJVM = app.jvm
.settings(
(resources in Compile) ++= Seq(
(fastOptJS in (appJS, Compile)).value.data,
(packageJSDependencies in (appJS, Compile)).value
)
)
That used to do the task, but after updating to 2.12 my assets/app-fastopt.js file does not change despite running the fastOptJS task in every way I know how. The updated fastopt.js file DOES appear in the app/js/target/scala-2.12 subdirectory.
I am using version 0.6.25 of the scala.js plugin, on scala 2.12.6 and sbt 1.1.6
pacepalm
Please disregard. The browser was caching old versions.

sbt console - set scala-version for all sub-projects

I have a multi-project build with scalaVersion := "2.11.8" for each module.
I want to run test and publish-local for Scala 2.12.0-RC1 without touching the build file. I thought the following would work:
$ sbt
> set scalaVersion in ThisBuild := "2.12.0-RC1"
> test
But that does not alter the Scala version used, sbt still compiles with Scala 2.11.8. This only works for single module builds (without project definitions).
How do I effectively override scalaVersion for all sub-modules from the sbt console?
Your attempt doesn't work because the setting for the module takes priority over the setting for ThisBuild; it would work if you used scalaVersion in ThisBuild in the build file instead of setting it separately for each module. I don't know if there is a way to do this with anything except scalaVersion, but:
As a final note, you can use ++ to temporarily switch the Scala version currently being used to build. should be either a version for Scala published to a repository, as in ++ 2.10.0 or the path to a Scala home directory, as in ++ /path/to/scala/home. See Command Line Reference for details.
> ++2.12.0-RC1
> test

Play 2.3 run error

I'm experiencing a problem when running latest play framework 2.3.
It compiles just fine, although when I do activator run this error happens:
java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
Full error log
I explicitly tried scalaVersion in every build.sbt file and it is the same.
I tried several things like activator clean, full removal os sbt caches and local repo sbt stuff, updating dependencies to latest version but no success.
I have scala version defined.
My current dependencies are:
I tried with both %% and force _2.11 in the name of the dependency.
Dependency List
Other important files
build.sbt
Common.scala
Dependencies.scala
When I fully clean caches it downloads scala 2.10.4 for no reason:
in this download log it says the sbt need the old scala.
Any idea why is this?
Any ideas?
Firstly, it does not matter which version of Scala is used to generate your build. The build system can use version 2.10.4, and that does not prevent your code from using version 2.11.1.
To look at the issue with your scala version, you should consider that settings added directly in build.sbt are added to the root project, but not to other projects. You can see this with a minimal project such as:
$ cat build.sbt
scalaVersion := "2.11.1"
lazy val subproj = project in (file("subproj"))
Then the output of sbt looks like this:
> show scalaVersion
[info] subproj/*:scalaVersion
[info] 2.10.4
[info] sbttest/*:scalaVersion
[info] 2.11.1
So, how can this be fixed?
We can create a lazy val containing a Seq[Setting[_]], and add it to the sub-project definition with the settings() method.
Here's an example build.sbt which adds the same settings to all projects:
$ cat build.sbt
lazy val root = project.in(file("."))
.aggregate(subproj)
.dependsOn(subproj)
.settings(commonSettings: _*)
lazy val subproj = project.in(file("subproj"))
.settings(commonSettings: _*)
lazy val commonSettings = Seq(
scalaVersion := "2.11.1"
)
The _* is required because settings() is defined as requiring Setting[_]* rather than Seq[Setting[_]], so _* converts between the two types. See also: What does param: _* mean in Scala?
And the output from sbt is:
> show scalaVersion
[info] subproj/*:scalaVersion
[info] 2.11.1
[info] root/*:scalaVersion
[info] 2.11.1
This approach can easily be applied to your build.
You're defining your dependencies in the wrong way.
When using SBT, don't use:
"org.mydep" % "mydep_2.11" % "1.0.0"
Instead use:
"org.mydep" %% "mydep" % "1.0.0"
The %% operator automatically appends the current Scala version of the current build. If you use dependencies built against other Scala versions, you're going to be getting the weird errors.
Also make sure you explicitly specify your Scala version somewhere:
scalaVersion := "2.11.1"
The problem was related to some manually added jars that I discovered in the lib folder, that were causing issues with the dependencies of the project defined in the build.sbt.
The only way to find out was to generate a activator dist and look for similar dependencies with different versions since in the dependency graph there were no conflicts