LoginSignup
4
4

More than 5 years have passed since last update.

sbt でコード生成ツールをコンパイル前に実行

Last updated at Posted at 2014-12-01

IDL や O/R Mapper などソース自動生成を行うツールはコンパイル前に自動実行させておくと便利です。

例えば Java/Scala で作成された foo.CodeGenerator という main() を持つツールを sbt コンパイル前に実行させるには Build.scala に上記のように記述します:

import sbt._
import Keys._
import Tests._

object Build extends sbt.Build {
  lazy val mainProject = Project(
    id="myproject",
    base=file("."),
    settings = Project.defaultSettings ++ Seq(
      libraryDependencies ++= List(
        "foo.codegen" % "codegen"   % "1.0.0",
        "org.slf4j"   % "slf4j-nop" % "1.6.4"
      ),
      // sbt codeGen でマニュアル実行できるようにコマンド登録
      codeGen <<= myCodeGenTask,
      // コンパイルごとにソース自動生成タスクを実行するよう登録
      sourceGenerators in Compile <+= myCodeGenTask
    )
  )

  lazy val codeGen = TaskKey[Seq[File]]("generate my code.")
  lazy val myCodeGenTask = (sourceManaged, dependencyClasspath in Compile, runner in Compile, streams) map { (dir, cp, r, s) =>
    val outdir = (dir / "autogen").getPath
    toError(r.run("foo.CodeGenerator", cp.files, Array(outdir /* コマンドライン引数 */), s.log))
    Seq("Foo.scala", "Bar.scala").map{ fname => file(outdir + "/" + fname) }
  }
}

ここで Maven リポジトリ foo.codegen:codegen:1.0.0 には foo.CodeGenerator が含まれているものとします。

タスクは自動生成されたファイルの一覧を返すことでそれらがコンパイル対象に含まれます。上記の例では src_managed/autogen の下に以下の 2 ファイルが生成されるものと仮定し:

case class Foo(x:Int)
case class Bar(y:String)

自動生成されたコードを使用するプログラムを作成して実行します。

object Hoge {
  def main(args:Array[String]):Unit = {
    println(Foo(99))
    println(Bar("hoge"))
  }
}
$ sbt compile run
[info] Loading project definition from <dir>/project
[info] Set current project to myproject (in build file:<dir>/)
[info] Updating {file:<dir>/}myproject...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Running foo.CodeGenerator <dir>/target/scala-2.10/src_managed/autogen
[info] Compiling 3 Scala sources to <dir>/target/scala-2.10/classes...
[success] Total time: 5 s, completed 2014/12/01 9:25:18
[info] Running foo.CodeGenerator <dir>/target/scala-2.10/src_managed/autogen
[info] Running Hoge
Foo(99)
Bar(hoge)
[success] Total time: 0 s, completed 2014/12/01 9:25:18

compilerun とで 2 度実行されているようですがコンパイルは 1 度だけですかね。自動生成とコンパイルが成功しました。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4