带有 sbt native packager 的附加资源生成器
Additional resource generator with sbt native packager
我有一个子模块,它是通过调用外部命令编译的。我想将生成的文件包含到 jar 中。所以我写了一个任务:
```
myTask := {
import sys.process.stringSeqToProcess
Seq("my", "command") !
}
unmanagedResourceDirectories in Compile += baseDirectory.value / "dist"
cleanFiles <+= baseDirectory { base => base / "dist" }
Keys.`package` <<= (Keys.`package` in Compile) dependsOn npmBuildTask.toTask
并且当我调用 mySubmodule/package
任务时它运行良好。但是当我从 sbt-native-packager
调用 stage
任务时,我的任务被忽略(未执行)。
有几个选项可以解决这个问题。我假设您想将 dist
文件夹添加到生成的应用程序 jar 中。
您的配置无效,因为 stage
不依赖于 package
。这导致 npmBuildTask
未被调用。
1。添加依赖到阶段
解决此问题的最简单方法是将 npmBuildTask
作为依赖项添加到 stage
stage <<= stage dependsOn npmBuildTask.toTask
我不推荐这种方法。
2。资源生成器
SBT Resoure Generators 正是为此目的而定义的。内联版本可能如下所示
resourceGenerators in Compile += Def.task {
streams.value.log.info("running npm generator")
val base = (resourceManaged in Compile).value / "dist"
// A resource generator returns a Seq[File]. This is just an example
List("index.js", "test.js").map { file =>
IO.writeLines(base / file, List("var x = 1"))
base / file
}
}.taskValue
或者您可以将其提取到 AutoPlugin
中以分隔 "what" 和“how.
3。自动插件和资源生成器
创建project/NpmPlugin.scala
并添加以下内容
import sbt._
import sbt.Keys._
import sbt.plugins.JvmPlugin
object NpmPlugin extends AutoPlugin {
override val requires = JvmPlugin
override val trigger = AllRequirements
object autoImport {
val npmBuildTask = TaskKey[Seq[File]]("npm-build-task", "Runs npm and builds the application")
}
import autoImport._
override def projectSettings: Seq[Setting[_]] = Seq(
// define a custom target directory for npm
target in npmBuildTask := target.value / "npm",
// the actual build task
npmBuildTask := {
val npmSource = (target in npmBuildTask).value
val npmTarget = (resourceManaged in Compile).value / "dist"
// run npm here, which generates the necessary values
streams.value.log.info("running npm generator")
// move generated sources to target folder
IO.copyDirectory(npmSource, npmTarget)
// recursively get all files in the npmTarget
(npmTarget ***).get
},
resourceGenerators in Compile += npmBuildTask.taskValue
)
}
build.sbt
看起来像这样
name := "resource-gen-test"
version := "1.0"
enablePlugins(JavaAppPackaging)
很干净:)
4。使用映射
最后但同样重要的是,您 可以 使用 mappings
。它们是驱动 sbt 中大量包生成的底层细节。这个解决方案的主要思想是
- 创建一个 returns 映射定义 (
Seq[(File, String)]
) 的任务
- 将其附加到适当的映射中
这种方法的优点是您可以更灵活地放置映射。
import sbt._
import sbt.Keys._
import sbt.plugins.JvmPlugin
import com.typesafe.sbt.SbtNativePackager.Universal
import com.typesafe.sbt.SbtNativePackager.autoImport.NativePackagerHelper._
object NpmMappingsPlugin extends AutoPlugin {
override val requires = JvmPlugin
override val trigger = AllRequirements
object autoImport {
val npmBuildTask = TaskKey[Seq[(File, String)]]("npm-build-task", "Runs npm and builds the application")
}
import autoImport._
override def projectSettings: Seq[Setting[_]] = Seq(
// define a custom target directory for npm
target in npmBuildTask := target.value / "npm" / "dist",
// the actual build task
npmBuildTask := {
val npmTarget = (target in npmBuildTask).value
// run npm here, which generates the necessary values
streams.value.log.info("running npm generator")
// recursively get all files in the npmTarget
// contentOf(npmTarget) would skip the top-level-directory
directory(npmTarget)
},
// add npm resources to the generated jar
mappings in (Compile, packageBin) ++= npmBuildTask.value,
// add npm resources to resulting package
mappings in Universal ++= npmBuildTask.value
)
}
正如您在这种方法中看到的那样,我们可以轻松地将生成的文件添加到不同的映射中。
但是,如果您需要这种灵活性,我只推荐这种方法,因为它需要更多的 native-packager 知识。
我有一个子模块,它是通过调用外部命令编译的。我想将生成的文件包含到 jar 中。所以我写了一个任务: ```
myTask := {
import sys.process.stringSeqToProcess
Seq("my", "command") !
}
unmanagedResourceDirectories in Compile += baseDirectory.value / "dist"
cleanFiles <+= baseDirectory { base => base / "dist" }
Keys.`package` <<= (Keys.`package` in Compile) dependsOn npmBuildTask.toTask
并且当我调用 mySubmodule/package
任务时它运行良好。但是当我从 sbt-native-packager
调用 stage
任务时,我的任务被忽略(未执行)。
有几个选项可以解决这个问题。我假设您想将 dist
文件夹添加到生成的应用程序 jar 中。
您的配置无效,因为 stage
不依赖于 package
。这导致 npmBuildTask
未被调用。
1。添加依赖到阶段
解决此问题的最简单方法是将 npmBuildTask
作为依赖项添加到 stage
stage <<= stage dependsOn npmBuildTask.toTask
我不推荐这种方法。
2。资源生成器
SBT Resoure Generators 正是为此目的而定义的。内联版本可能如下所示
resourceGenerators in Compile += Def.task {
streams.value.log.info("running npm generator")
val base = (resourceManaged in Compile).value / "dist"
// A resource generator returns a Seq[File]. This is just an example
List("index.js", "test.js").map { file =>
IO.writeLines(base / file, List("var x = 1"))
base / file
}
}.taskValue
或者您可以将其提取到 AutoPlugin
中以分隔 "what" 和“how.
3。自动插件和资源生成器
创建project/NpmPlugin.scala
并添加以下内容
import sbt._
import sbt.Keys._
import sbt.plugins.JvmPlugin
object NpmPlugin extends AutoPlugin {
override val requires = JvmPlugin
override val trigger = AllRequirements
object autoImport {
val npmBuildTask = TaskKey[Seq[File]]("npm-build-task", "Runs npm and builds the application")
}
import autoImport._
override def projectSettings: Seq[Setting[_]] = Seq(
// define a custom target directory for npm
target in npmBuildTask := target.value / "npm",
// the actual build task
npmBuildTask := {
val npmSource = (target in npmBuildTask).value
val npmTarget = (resourceManaged in Compile).value / "dist"
// run npm here, which generates the necessary values
streams.value.log.info("running npm generator")
// move generated sources to target folder
IO.copyDirectory(npmSource, npmTarget)
// recursively get all files in the npmTarget
(npmTarget ***).get
},
resourceGenerators in Compile += npmBuildTask.taskValue
)
}
build.sbt
看起来像这样
name := "resource-gen-test"
version := "1.0"
enablePlugins(JavaAppPackaging)
很干净:)
4。使用映射
最后但同样重要的是,您 可以 使用 mappings
。它们是驱动 sbt 中大量包生成的底层细节。这个解决方案的主要思想是
- 创建一个 returns 映射定义 (
Seq[(File, String)]
) 的任务
- 将其附加到适当的映射中
这种方法的优点是您可以更灵活地放置映射。
import sbt._
import sbt.Keys._
import sbt.plugins.JvmPlugin
import com.typesafe.sbt.SbtNativePackager.Universal
import com.typesafe.sbt.SbtNativePackager.autoImport.NativePackagerHelper._
object NpmMappingsPlugin extends AutoPlugin {
override val requires = JvmPlugin
override val trigger = AllRequirements
object autoImport {
val npmBuildTask = TaskKey[Seq[(File, String)]]("npm-build-task", "Runs npm and builds the application")
}
import autoImport._
override def projectSettings: Seq[Setting[_]] = Seq(
// define a custom target directory for npm
target in npmBuildTask := target.value / "npm" / "dist",
// the actual build task
npmBuildTask := {
val npmTarget = (target in npmBuildTask).value
// run npm here, which generates the necessary values
streams.value.log.info("running npm generator")
// recursively get all files in the npmTarget
// contentOf(npmTarget) would skip the top-level-directory
directory(npmTarget)
},
// add npm resources to the generated jar
mappings in (Compile, packageBin) ++= npmBuildTask.value,
// add npm resources to resulting package
mappings in Universal ++= npmBuildTask.value
)
}
正如您在这种方法中看到的那样,我们可以轻松地将生成的文件添加到不同的映射中。
但是,如果您需要这种灵活性,我只推荐这种方法,因为它需要更多的 native-packager 知识。