这个SBT 构建定义有效:
目录结构:
build.sbt
src/main/resources/config.yml
project/build.sbt
project/build.properties
build.sbt:
ThisBuild / scalaVersion := "2.13.8"
ThisBuild / organization := "com.example"
lazy val hello = (project in file("."))
.settings(
name := "Hello",
//libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.1"
)
lazy val loadEnv = TaskKey[Unit]("load-dev-env")
loadEnv := {
import _root_.io.circe._
import _root_.io.circe.yaml.parser
import scala.io.Source
val filename = "src/main/resources/config.yml"
val confStr = Source.fromFile(filename).getLines.mkString("\n")
println(confStr)
val json: Either[ParsingFailure, Json] = parser.parse(confStr)
println(json)
}
project/build.sbt:
libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.1"
project/build.properties:
sbt.version=1.6.1
src/main/resources/config.yml:
---
system:
port: 123
service: name
运行示例:
sbt:Hello> loadDevEnv
---
system:
port: 123
service: name
Right({
"system" : {
"port" : 123,
"service" : "name"
}
})
它从文件中打印字符串,然后是解析的 json。
重要的细节是:
- 您需要将库依赖项放在
project 目录中的其他构建文件中。
- 您需要使用
_root_,否则如果它们不是核心 Scala 或 SBT 插件的一部分,导入将无法解析。至少我还没有找到路。
您可以在此处查看代码:https://github.com/izmailoff/sbt-import-test。
--- 更新 ---:
我在 repo 中添加了完整的示例。这需要进行一些更改,因为您无法从 Task 更新 SBT 设置,您需要在 Command 中进行更新。更新文件如下:
build.sbt:
ThisBuild / scalaVersion := "2.13.8"
ThisBuild / organization := "com.example"
// This is needed to get new env values from SBT:
fork := true
lazy val hello = (project in file("."))
.settings(
name := "Hello",
//libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.1"
)
commands += Command.command("loadDevEnv") { state =>
val env = Config.getEnvFromConf()
val envStr = Config.prettyPrint(env)
s"set envVars ++= ${envStr}" :: state
}
project/Build.scala:
case class Service(port: Integer, service: String)
case class System(system: Service)
object Config {
def getEnvFromConf(): Map[String, String] = {
val filename = "src/main/resources/config.yml"
val confStr = readConfig(filename)
val conf = parseConfig(confStr)
println(conf)
val env = toEnv(conf)
env
}
def readConfig(filename: String): String = {
import scala.io.Source
Source.fromFile(filename).getLines.mkString("\n") // use better way?
}
def parseConfig(conf: String): System = {
import _root_.io.circe._
import _root_.io.circe.yaml
import _root_.io.circe.yaml._
import _root_.io.circe.yaml.syntax._
import _root_.io.circe.generic.auto._
import cats.syntax.either._
val json: Either[ParsingFailure, Json] = yaml.parser.parse(conf)
json
.leftMap(err => err: Error)
.flatMap(_.as[System])
.valueOr(throw _)
}
def toEnv(conf: System): Map[String, String] = {
Map(s"service.${conf.system.service}" -> conf.system.port.toString)
}
def prettyPrint(x: Map[String, String]): String = {
"Map(" + (x.map{ case (k, v) => s""""${k}"->"${v}""""}).mkString(", ") + ")"
}
}
project.build.sbt:
val circeVersion = "0.14.1"
libraryDependencies ++= Seq(
"io.circe" %% "circe-yaml",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
src/main/scala/Main.scala:
object Main extends App {
println("Found the following environment variable:")
println(System.getenv("service.name"))
}
示例:
从您的操作系统外壳运行 SBT:
> sbt
运行应用检查是否设置了环境变量:
sbt:Hello> run
[info] running (fork) Main
[info] Found the following environment variable:
[info] null
获取null。加载环境:
sbt:Hello> loadDevEnv
[info] Defining envVars
[info] The new value will be used by Compile / bspBuildTargetRun, Compile / bspScalaMainClassesItem and 6 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] set current project to Hello (in build file:/home/tvc/repos/sbt_test/)
运行应用再次检查:
sbt:Hello> run
[info] running (fork) Main
[info] Found the following environment variable:
[info] 123
找到值123。