Home > Software engineering >  Why is "compile" called 2 times when calling "run" in SBT Play Framework Project
Why is "compile" called 2 times when calling "run" in SBT Play Framework Project

Time:12-24

In my play framework project using SBT, I'm trying to run a custom task before the compile task. This is easily done by adding this in the build.sbt.

lazy val hello = taskKey[Unit]("says hello to everybody :)")

hello := {
  println("hello, world")
}

(compile in Compile) := ((compile in Compile) dependsOn hello).value

When I do sbt compile, it runs the hello task once then it compiles the code. Like it was expected!

Strangely, when I run sbt run, the hello task is run 2 times. Like this

(Server started, use Enter to stop and go back to the console...)
hello, world
[info] Compiling 1 Java source to C:\dev\CS\CSBackEnd\target\scala-2.12\classes ...
hello, world
[info] p.a.d.DefaultDBApi - Database [default] initialized
[info] p.a.d.HikariCPConnectionPool - Creating Pool for datasource 'default'

Any idea how to prevent this or at least understand what is going on under the hood? In this example, it's only to print a string but in real life, a complex validation will be called instead and it can't run 2 times because it will take too much time.

Thanks

** EDIT **

Here is the output when I do sbt inspect tree run.

[info] welcome to sbt 1.3.13 (Oracle Corporation Java 1.8.0_201)
[info] loading global plugins from C:\Users\jcote\.sbt\1.0\plugins
[info] loading settings for project csbackend-build from plugins.sbt ...
[info] loading project definition from C:\dev\CS\CSBackEnd\project
[info] loading settings for project root from build.sbt ...
[info] set current project to S360ControlSite (in build file:/C:/dev/CS/CSBackEnd/)
[info] Compile / run = InputTask[Unit]
[info]    -Compile / run / mainClass = Task[scala.Option[java.lang.String]]
[info]    -Global / javaOptions = Task[scala.collection.Seq[java.lang.String]]
[info]    -baseDirectory =
[info]   |  -thisProject = Project(id root, base: C:\dev\CS\CSBackEnd, configurations: List(compile, runtime, test, provided, optional, web-assets, web-assets-test, web-plugin, universal, universal-docs, universal-src, windows, docker, linux, rpm, debian), plugins: List(org.openapitools.openapistylevalidator..
[info]   |
[info]    -fileWatchService = play.dev.filewatch.DefaultFileWatchService@205b0b3a
[info]   |  -Global / pollInterval = 500 milliseconds
[info]   |  -Global / sLog = sbt.internal.LogManager$$anon$1@6531d251
[info]   |  -target = target
[info]   |    -baseDirectory =
[info]   |      -thisProject = Project(id root, base: C:\dev\CS\CSBackEnd, configurations: List(compile, runtime, test, provided, optional, web-assets, web-assets-test, web-plugin, universal, universal-docs, universal-src, windows, docker, linux, rpm, debian), plugins: List(org.openapitools.openapistylevalid.. 
[info]   |
[info]    -playAssetsClassloader = Task[scala.Function1[java.lang.ClassLoader, java.lang.ClassLoader]]
[info]   |  -playAllAssets = Task[scala.collection.Seq[scala.Tuple2[java.lang.String, java.io.File]]]
[info]   |    -playPrefixAndAssets = Task[scala.Tuple2[java.lang.String, java.io.File]]
[info]   |      -Web-assets / webPublic = target\web\public\main
[info]   |     |  -assetsTarget = target\web
[info]   |     |    -target = target
[info]   |     |      -baseDirectory =
[info]   |     |        -thisProject = Project(id root, base: C:\dev\CS\CSBackEnd, configurations: List(compile, runtime, test, provided, optional, web-assets, web-assets-test, web-plugin, universal, universal-docs, universal-src, windows, docker, linux, rpm, debian), plugins: List(org.openapitools.openapist.. 
[info]   |     |
[info]   |      -assetsPrefix = public/
[info]   |
[info]    -playCommonClassloader = Task[java.lang.ClassLoader]
[info]   |  -Compile / dependencyClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   | |  -Compile / dependencyClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | |
[info]   | |  -Compile / externalDependencyClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   | | |  -Compile / externalDependencyClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | | |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | | |
[info]   | | |  -Compile / managedClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   | | | |  -Global / appConfiguration = xsbt.boot.AppConfiguration@5f22d8ea
[info]   | | | |  -Compile / classpathConfiguration = Task[sbt.librarymanagement.Configuration]
[info]   | | | | |  -Compile / configuration = compile
[info]   | | | | |  -Global / internalConfigurationMap = sbt.Defaults$$$Lambda$1562/1187225933@797c8f80
[info]   | | | | |  -update = Task[sbt.librarymanagement.UpdateReport]
[info]   | | | | |
[info]   | | | |  -Global / classpathTypes = Set(eclipse-plugin, maven-plugin, bundle, scala-jar, hk2-jar, orbit, test-jar, jar)
[info]   | | | |  -Global / isMetaBuild = false
[info]   | | | |  -Compile / managedClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | | | |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | | | |
[info]   | | | |  -Global / reresolveSbtArtifacts = false
[info]   | | | |  -update = Task[sbt.librarymanagement.UpdateReport]
[info]   | | | |  -Global / useCoursier = true
[info]   | | | |
[info]   | | |  -Compile / unmanagedClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   | | |    -Global / buildDependencies = sbt.internal.BuildDependencies@6c0a821a
[info]   | | |    -Compile / configuration = compile
[info]   | | |    -Global / settingsData = Task[sbt.internal.util.Settings[sbt.Scope]]
[info]   | | |    -thisProjectRef = ProjectRef(file:/C:/dev/CS/CSBackEnd/,root)
[info]   | | |    -Compile / unmanagedClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | |      -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | | |
[info]   | |  -Compile / internalDependencyClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   | |    -Global / buildDependencies = sbt.internal.BuildDependencies@6c0a821a
[info]   | |    -Compile / classpathConfiguration = Task[sbt.librarymanagement.Configuration]
[info]   | |   |  -Compile / configuration = compile
[info]   | |   |  -Global / internalConfigurationMap = sbt.Defaults$$$Lambda$1562/1187225933@797c8f80
[info]   | |   |  -update = Task[sbt.librarymanagement.UpdateReport]
[info]   | |   |
[info]   | |    -Compile / configuration = compile
[info]   | |    -Compile / exportedProductJars / transitiveClasspathDependency = ()
[info]   | |    -Compile / exportedProductJarsIfMissing / transitiveClasspathDependency = ()
[info]   | |    -Compile / exportedProductJarsNoTracking / transitiveClasspathDependency = ()
[info]   | |    -Compile / exportedProducts / transitiveClasspathDependency = ()
[info]   | |    -Compile / exportedProductsIfMissing / transitiveClasspathDependency = ()
[info]   | |    -Compile / exportedProductsNoTracking / transitiveClasspathDependency = ()
[info]   | |    -Compile / internalDependencyClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | |   |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   | |   |
[info]   | |    -Global / settingsData = Task[sbt.internal.util.Settings[sbt.Scope]]
[info]   | |    -thisProjectRef = ProjectRef(file:/C:/dev/CS/CSBackEnd/,root)
[info]   | |    -Global / trackInternalDependencies = TrackAlways
[info]   | |
[info]   |  -playCommonClassloader / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |    -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |
[info]    -playDefaultAddress = 0.0.0.0
[info]    -playDefaultPort = 9000
[info]    -playDependencyClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   |  -Runtime / externalDependencyClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   |    -Runtime / externalDependencyClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |   |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |   |
[info]   |    -Runtime / managedClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   |   |  -Global / appConfiguration = xsbt.boot.AppConfiguration@5f22d8ea
[info]   |   |  -Runtime / classpathConfiguration = Task[sbt.librarymanagement.Configuration]
[info]   |   | |  -Runtime / configuration = runtime
[info]   |   | |  -Global / internalConfigurationMap = sbt.Defaults$$$Lambda$1562/1187225933@797c8f80
[info]   |   | |  -update = Task[sbt.librarymanagement.UpdateReport]
[info]   |   | |
[info]   |   |  -Global / classpathTypes = Set(eclipse-plugin, maven-plugin, bundle, scala-jar, hk2-jar, orbit, test-jar, jar)
[info]   |   |  -Global / isMetaBuild = false
[info]   |   |  -Runtime / managedClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |   | |  -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |   | |
[info]   |   |  -Global / reresolveSbtArtifacts = false
[info]   |   |  -update = Task[sbt.librarymanagement.UpdateReport]
[info]   |   |  -Global / useCoursier = true
[info]   |   |
[info]   |    -Runtime / unmanagedClasspath = Task[scala.collection.Seq[sbt.internal.util.Attributed[java.io.File]]]
[info]   |      -Global / buildDependencies = sbt.internal.BuildDependencies@6c0a821a
[info]   |      -Runtime / configuration = runtime
[info]   |      -Global / settingsData = Task[sbt.internal.util.Settings[sbt.Scope]]
[info]   |      -thisProjectRef = ProjectRef(file:/C:/dev/CS/CSBackEnd/,root)
[info]   |      -Runtime / unmanagedClasspath / streams = Task[sbt.std.TaskStreams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |        -Global / streamsManager = Task[sbt.std.Streams[sbt.internal.util.Init$ScopedKey[_ <: Any]]]
[info]   |
[info]    -playDevSettings = List()
[info]    -playInteractionMode = Console Interaction Mode
[info]    -playMonitoredFiles = Task[scala.collection.Seq[java.io.File]]
[info]   |  -Compile / twirlCompileTemplates / sourceDirectories = List(C:\dev\CS\CSBackEnd\app)
[info]   | |  -Compile / sourceDirectory = app
[info]   | |    -baseDirectory =
[info]   | |      -thisProject = Project(id root, base: C:\dev\CS\CSBackEnd, configurations: List(compile, runtime, test, provided, optional, web-assets, web-assets-test, web-plugin, universal, universal-docs, universal-src, windows, docker, linux, rpm, debian), plugins: List(org.openapitools.openapistyleval.. 
[info]   | |
[info]   |  -Global / settingsData = Task[sbt.internal.util.Settings[sbt.Scope]]
[info]   |  -thisProjectRef = ProjectRef(file:/C:/dev/CS/CSBackEnd/,root)
[info]   |
[info]    -playRunHooks = Task[scala.collection.Seq[play.sbt.PlayRunHook]]
[info]    -Global / sbtVersion = 1.3.13
[info]    -Global / state = Task[sbt.State]

CodePudding user response:

I can't tell you why you're seeing the behaviour you're observing. I can reproduce the error with SBT 1.3.13. When I use SBT 1.4.9 the custom task only runs once as you would expect.

  • Related