Locked History Actions

sbt/Getting-Started-Using-Plugins

プラグインを使う

https://github.com/harrah/xsbt/wiki/Getting-Started-Using-Pluginsの訳(2011/10/28時点)

Using Plugins

  • Page History

Previous Getting Started Guide page 11 of 14. Next

Please read the earlier pages in the Getting Started Guide first, in particular you need to understand build.sbt, library dependencies, and .scala build definition before reading this page.

プラグインとは?

プラグインはビルド定義を拡張するが、多くの場合それは新しいsettingを追加することで行われる。 新しいsettingは新しいタスクでよい。 例えば、プラグインはテストカバレッジレポートを生成するcode-coverageタスクを追加するかもしれない。

プラグインを追加する

短い答え

君のプロジェクトがhelloディレクトリにあるとし、hello/project/build.sbtを編集し、resolverとしてプラグインロケーションを追加する。 そして、プラグインのivyモジュールIDを指定してaddSbtPluginを呼び出す。

resolvers += Classpaths.typesafeResolver

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse" % "1.4.0")

当然ながら、もデフォルトリポジトリ中にプラグインが存在するのであればresolverを追加する必要はない。

これだけだ。何が起こっているのかを説明していこう。

どうして動くの?

以前に説明したsbtの再帰的な性質と、管理依存の追加方法をしていることを前提とするよ。

ビルド定義のための依存

プラグインを追加するということは、ビルド定義にライブラリ依存を追加することを意味する。 これを行うには、「ビルド定義のビルド定義」を編集する必要がある。

helloプロジェクトについて思い起こそう。ビルド定義プロジェクトはhello/*.sbtとhello/project/*.scalaにあった。

 hello/                  # your project's base directory

     build.sbt           # build.sbt is part of the source code for the
                         #   build definition project inside project/

     project/            # base directory of the build definition project

         Build.scala     # a source file in the project/ project,
                         #   that is, a source file in the build definition

もしhelloプロジェクトに管理依存を追加したい場合、libraryDependenciesに追加するわけだが、それは hello/*.sbtあるいはhello/project/*.scalaで行う必要がある。

例えばhello.build.sbtで以下のようにする。

libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % "test"

このひょうにして、sbtの対話モードを開始し、「show dependency-classpath」と入力すれば、クラスパスにderbyのjarが追加されていることが確認できるだろう。

プラグインを追加するにも同じことを行うのだが、ただし1レベル下がる必要がある。 ここでは、ビルド定義プロジェクトに新しい依存を加えたいのだ。これは、ビルド定義のビルド定義のlibrariDependenciesの変更を意味する。

ビルド定義のビルド定義とは、君のプロジェクトがhelloの場合は、hello/project/*.sbtあるいはhello/project/project/*.scalaになる。

sbtのサポートの不要な単純なプラグインは単なるjarファイルだ。 例えば、hello/project/build.sbtを編集して次の行を加えよう。

libraryDependencies += "net.liftweb" % "lift-json" % "2.0"

Now, at the sbt interactive prompt, reload plugins to enter the build definition project, and try show dependency-classpath. You should see the lift-json jar on the classpath. This means: you could use classes from lift-json in your Build.scala or build.sbt to implement a task. You could parse a JSON file and generate other files based on it, for example. Remember, use reload return to leave the build definition project and go back to the parent project.

(Stupid sbt trick: type reload plugins over and over. You'll find yourself in the project rooted in project/project/project/project/project/project/. Don't worry, it isn't useful. Also, it creates target directories all the way down, which you'll have to clean up.) addSbtPlugin

addSbtPlugin is just a convenience method. Here's its definition:

def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =

  • libraryDependencies <+= (sbtVersion in update,scalaVersion) { (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) }

Remember from more about settings that <+= combines <<= and +=, so this builds a value based on other settings, and then appends it to libraryDependencies. The value is based on sbtVersion in update (sbt's version scoped to the update task) and scalaVersion (the version of scala used to compile the project, in this case used to compile the build definition). sbtPluginExtra adds the sbt and Scala version information to the module ID. plugins.sbt

Some people like to list plugin dependencies (for a project hello) in hello/project/plugins.sbt to avoid confusion with hello/build.sbt. sbt does not care what .sbt files are called, so both build.sbt and project/plugins.sbt are conventions. sbt does of course care where the sbt files are located. hello/*.sbt would contain dependencies for hello and hello/project/*.sbt would contain dependencies for hello's build definition. Plugins can add settings and imports automatically

In one sense a plugin is just a jar added to libraryDependencies for the build definition; you can then use the jar from build definition code as in the lift-json example above.

However, jars intended for use as sbt plugins can do more.

If you download a plugin jar (here's one for sbteclipse) and unpack it with jar xf, you'll see that it contains a text file sbt/sbt.plugins. In sbt/sbt.plugins there's an object name on each line like this:

com.typesafe.sbteclipse.SbtEclipsePlugin

com.typesafe.sbteclipse.SbtEclipsePlugin is the name of an object that extends sbt.Plugin. The sbt.Plugin trait is very simple:

trait Plugin {

  • def settings: Seq[Setting[_]] = Nil

}

sbt looks for objects listed in sbt/sbt.plugins. When it finds com.typesafe.sbteclipse.SbtEclipsePlugin, it adds com.typesafe.sbteclipse.SbtEclipsePlugin.settings to the settings for the project. It also does import com.typesafe.sbteclipse.SbtEclipsePlugin._ for any .sbt files, allowing a plugin to provide values, objects, and methods to .sbt files in the build definition. Adding settings manually from a plugin

If a plugin defines settings in the settings field of a Plugin object, you don't have to do anything to add them.

However, plugins often avoid this because you could not control which projects in a multi-project build would use the plugin.

sbt provides a method called seq which adds a whole batch of settings at once. So if a plugin has something like this:

object MyPlugin extends Plugin {

  • val myPluginSettings = Seq(settings in here)

}

You could add all those settings in build.sbt with this syntax:

seq(myPluginSettings: _*)

If you aren't familiar with the _* syntax:

  • seq is defined with a variable number of arguments: def seq(settings: Setting[_]*) _* converts a sequence into a variable argument list

Short version: seq(myPluginSettings: _*) in a build.sbt adds all the settings in myPluginSettings to the project. Creating a plugin

After reading this far, you pretty much know how to create an sbt plugin as well. There's one trick to know; set sbtPlugin := true in build.sbt. If sbtPlugin is true, the project will scan its compiled classes for instances of Plugin, and list them in sbt/sbt.plugins when it packages a jar. sbtPlugin := true also adds sbt to the project's classpath, so you can use sbt APIs to implement your plugin.

Learn more about creating a plugin at Plugins and Plugins Best Practices. Global plugins

Plugins can be installed for all your projects at once by dropping them in ~/.sbt/plugins/. ~/.sbt/plugins/ is an sbt project whose classpath is exported to all sbt build definition projects. Roughly speaking, any .sbt files in ~/.sbt/plugins/ behave as if they were in the project/ directory for all projects, and any .scala files in ~/.sbt/plugins/project/ behave as if they were in the project/project/ directory for all projects.

You can create ~/.sbt/plugins/build.sbt and put addSbtPlugin() expressions in there to add plugins to all your projects at once. Available Plugins

There's a list of available plugins.

Some especially popular plugins are:

  • those for IDEs (to import an sbt project into your IDE) those supporting web frameworks, such as xsbt-web-plugin.

Check out the list.

次はマルチプロジェクト