/framework/src/sbt-plugin/src/main/scala/play/sbt/PlaySettings.scala

http://github.com/playframework/Play20 · Scala · 271 lines · 186 code · 59 blank · 26 comment · 13 complexity · dda3e3df40bbd7ccd1b864882793ee46 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com>
  3. */
  4. package play.sbt
  5. import scala.collection.JavaConverters._
  6. import scala.language.postfixOps
  7. import sbt._
  8. import sbt.Keys._
  9. import play.TemplateImports
  10. import play.runsupport.FileWatchService
  11. import play.sbt.PlayImport.PlayKeys._
  12. import play.sbt.PlayInternalKeys._
  13. import play.sbt.routes.RoutesKeys
  14. import play.sbt.run._
  15. import play.sbt.run.PlayRun.DocsApplication
  16. import play.twirl.sbt.Import.TwirlKeys
  17. import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport._
  18. import com.typesafe.sbt.packager.archetypes.JavaAppPackaging
  19. import com.typesafe.sbt.packager.Keys._
  20. import com.typesafe.sbt.web.SbtWeb.autoImport._
  21. import WebKeys._
  22. object PlaySettings {
  23. lazy val defaultJavaSettings = Seq[Setting[_]](
  24. TwirlKeys.templateImports ++= TemplateImports.defaultJavaTemplateImports.asScala,
  25. RoutesKeys.routesImport ++= Seq(
  26. "play.libs.F"
  27. )
  28. )
  29. lazy val defaultScalaSettings = Seq[Setting[_]](
  30. TwirlKeys.templateImports ++= TemplateImports.defaultScalaTemplateImports.asScala
  31. )
  32. /** Ask SBT to manage the classpath for the given configuration. */
  33. def manageClasspath(config: Configuration) = managedClasspath in config <<= (classpathTypes in config, update) map { (ct, report) =>
  34. Classpaths.managedJars(config, ct, report)
  35. }
  36. lazy val defaultSettings = Seq[Setting[_]](
  37. playPlugin := false,
  38. externalizeResources := true,
  39. javacOptions in (Compile, doc) := List("-encoding", "utf8"),
  40. libraryDependencies <+= (playPlugin) {
  41. isPlugin =>
  42. if (isPlugin) {
  43. "com.typesafe.play" %% "play" % play.core.PlayVersion.current % "provided"
  44. } else {
  45. "com.typesafe.play" %% "play-server" % play.core.PlayVersion.current
  46. }
  47. },
  48. libraryDependencies += "com.typesafe.play" %% "play-test" % play.core.PlayVersion.current % "test",
  49. ivyConfigurations += DocsApplication,
  50. playOmnidoc := !play.core.PlayVersion.current.endsWith("-SNAPSHOT"),
  51. playDocsName := { if (playOmnidoc.value) "play-omnidoc" else "play-docs" },
  52. playDocsModule := Some("com.typesafe.play" %% playDocsName.value % play.core.PlayVersion.current % DocsApplication.name),
  53. libraryDependencies ++= playDocsModule.value.toSeq,
  54. manageClasspath(DocsApplication),
  55. playDocsJar := (managedClasspath in DocsApplication).value.files.find(_.getName.startsWith(playDocsName.value)),
  56. parallelExecution in Test := false,
  57. fork in Test := true,
  58. testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "sequential", "true", "junitxml", "console"),
  59. testOptions in Test += Tests.Argument(TestFrameworks.JUnit, "--ignore-runners=org.specs2.runner.JUnitRunner"),
  60. // Adds app directory's source files to continuous hot reloading
  61. watchSources <++= (sourceDirectory in Compile, sourceDirectory in Assets) map { (sources, assets) =>
  62. (sources ** "*" --- assets ** "*").get
  63. },
  64. commands ++= {
  65. import PlayCommands._
  66. import PlayRun._
  67. Seq(playStartCommand, playRunProdCommand, playTestProdCommand, playStopProdCommand, h2Command)
  68. },
  69. // THE `in Compile` IS IMPORTANT!
  70. Keys.run in Compile <<= PlayRun.playDefaultRunTask,
  71. mainClass in (Compile, Keys.run) := Some("play.core.server.DevServerStart"),
  72. PlayInternalKeys.playStop := {
  73. playInteractionMode.value match {
  74. case nonBlocking: PlayNonBlockingInteractionMode =>
  75. nonBlocking.stop()
  76. case _ => throw new RuntimeException("Play interaction mode must be non blocking to stop it")
  77. }
  78. },
  79. shellPrompt := PlayCommands.playPrompt,
  80. // all dependencies from outside the project (all dependency jars)
  81. playDependencyClasspath <<= externalDependencyClasspath in Runtime,
  82. // all user classes, in this project and any other subprojects that it depends on
  83. playReloaderClasspath <<= Classpaths.concatDistinct(exportedProducts in Runtime, internalDependencyClasspath in Runtime),
  84. // filter out asset directories from the classpath (supports sbt-web 1.0 and 1.1)
  85. playReloaderClasspath ~= { _.filter(_.get(WebKeys.webModulesLib.key).isEmpty) },
  86. playCommonClassloader <<= PlayCommands.playCommonClassloaderTask,
  87. playDependencyClassLoader := PlayRun.createURLClassLoader,
  88. playReloaderClassLoader := PlayRun.createDelegatedResourcesClassLoader,
  89. playCompileEverything <<= PlayCommands.playCompileEverythingTask,
  90. playReload <<= PlayCommands.playReloadTask,
  91. ivyLoggingLevel := UpdateLogging.DownloadOnly,
  92. RoutesKeys.routesImport ++= Seq("controllers.Assets.Asset"),
  93. sources in (Compile, RoutesKeys.routes) ++= {
  94. val dirs = (unmanagedResourceDirectories in Compile).value
  95. (dirs * "routes").get ++ (dirs * "*.routes").get
  96. },
  97. playMonitoredFiles <<= PlayCommands.playMonitoredFilesTask,
  98. fileWatchService := FileWatchService.defaultWatchService(target.value, pollInterval.value, sLog.value),
  99. playDefaultPort := 9000,
  100. playDefaultAddress := "0.0.0.0",
  101. // Default hooks
  102. playRunHooks := Nil,
  103. playInteractionMode := PlayConsoleInteractionMode,
  104. // sbt-web
  105. jsFilter in Assets := new PatternFilter("""[^_].*\.js""".r.pattern),
  106. WebKeys.stagingDirectory := WebKeys.stagingDirectory.value / "public",
  107. playAssetsWithCompilation := {
  108. val ignore = ((assets in Assets)?).value
  109. (compile in Compile).value
  110. },
  111. // Assets for run mode
  112. PlayRun.playPrefixAndAssetsSetting,
  113. PlayRun.playAllAssetsSetting,
  114. PlayRun.playAssetsClassLoaderSetting,
  115. assetsPrefix := "public/",
  116. // Assets for distribution
  117. WebKeys.packagePrefix in Assets := assetsPrefix.value,
  118. playPackageAssets := (packageBin in Assets).value,
  119. scriptClasspathOrdering += {
  120. val (id, art) = (projectID.value, (artifact in (Assets, packageBin)).value)
  121. val jarName = JavaAppPackaging.makeJarName(id.organization, id.name, id.revision, art.name, Some("assets"))
  122. playPackageAssets.value -> ("lib/" + jarName)
  123. },
  124. // Assets for testing
  125. public in TestAssets := (public in TestAssets).value / assetsPrefix.value,
  126. fullClasspath in Test += Attributed.blank((assets in TestAssets).value.getParentFile),
  127. // Settings
  128. devSettings := Nil,
  129. // Native packaging
  130. mainClass in Compile := Some("play.core.server.ProdServerStart"),
  131. // Support for externalising resources
  132. mappings in Universal ++= {
  133. if (externalizeResources.value) {
  134. val resourceMappings = (playExternalizedResources in Compile).value
  135. resourceMappings.map {
  136. case (resource, path) => resource -> ("conf/" + path)
  137. }
  138. } else Nil
  139. },
  140. scriptClasspath := {
  141. if (externalizeResources.value) {
  142. "../conf/" +: scriptClasspath.value
  143. } else scriptClasspath.value
  144. },
  145. // taskDyn ensures we only build the sans externalised jar if we need to
  146. scriptClasspathOrdering <<= Def.taskDyn {
  147. val oldValue = scriptClasspathOrdering.value
  148. if (externalizeResources.value) {
  149. Def.task {
  150. // Filter out the regular jar
  151. val jar = (packageBin in Runtime).value
  152. val jarSansExternalized = (playJarSansExternalized in Runtime).value
  153. oldValue.map {
  154. case (packageBinJar, _) if jar == packageBinJar =>
  155. val id = projectID.value
  156. val art = (artifact in Compile in playJarSansExternalized).value
  157. val jarName = JavaAppPackaging.makeJarName(id.organization, id.name, id.revision, art.name, art.classifier)
  158. jarSansExternalized -> ("lib/" + jarName)
  159. case other => other
  160. }
  161. }
  162. } else {
  163. Def.task(oldValue)
  164. }
  165. },
  166. mappings in Universal ++= {
  167. val docDirectory = (doc in Compile).value
  168. val docDirectoryLen = docDirectory.getCanonicalPath.length
  169. val pathFinder = docDirectory ** "*"
  170. pathFinder.get map {
  171. docFile: File =>
  172. docFile -> ("share/doc/api/" + docFile.getCanonicalPath.substring(docDirectoryLen))
  173. }
  174. },
  175. mappings in Universal ++= {
  176. val pathFinder = baseDirectory.value * "README*"
  177. pathFinder.get map {
  178. readmeFile: File =>
  179. readmeFile -> readmeFile.getName
  180. }
  181. },
  182. // Adds the Play application directory to the command line args passed to Play
  183. bashScriptExtraDefines += "addJava \"-Duser.dir=$(realpath \"$(cd \"${app_home}/..\"; pwd -P)\" $(is_cygwin && echo \"fix\"))\"\n",
  184. generateSecret <<= ApplicationSecretGenerator.generateSecretTask,
  185. updateSecret <<= ApplicationSecretGenerator.updateSecretTask
  186. ) ++ inConfig(Compile)(externalizedSettings)
  187. /**
  188. * Settings for creating a jar that excludes externalized resources
  189. */
  190. private def externalizedSettings: Seq[Setting[_]] =
  191. Defaults.packageTaskSettings(playJarSansExternalized, mappings in playJarSansExternalized) ++ Seq(
  192. playExternalizedResources := {
  193. val rdirs = unmanagedResourceDirectories.value
  194. (unmanagedResources.value --- rdirs) pair (relativeTo(rdirs) | flat)
  195. },
  196. mappings in playJarSansExternalized := {
  197. // packageBin mappings have all the copied resources from the classes directory
  198. // so we need to get the copied resources, and map the source files to the destination files,
  199. // so we can then exclude the destination files
  200. val packageBinMappings = (mappings in packageBin).value
  201. val externalized = playExternalizedResources.value.map(_._1).toSet
  202. val copied = copyResources.value
  203. val toExclude = copied.collect {
  204. case (source, dest) if externalized(source) => dest
  205. }.toSet
  206. packageBinMappings.filterNot {
  207. case (file, _) => toExclude(file)
  208. }
  209. },
  210. artifactClassifier in playJarSansExternalized := Option("sans-externalized")
  211. )
  212. }