Revision 2 as of 2011-10-30 08:47:58

Clear message
Locked History Actions

sbt/dt_Classpaths

クラスパス、ソース、リソース

https://github.com/harrah/xsbt/wiki/Classpathsの訳(2011/10/30時点)

ここでは、sbtがどのようにしてcompile,run,testのようなアクションについてクラスパスを構築するかを説明し、 また、これらのオーバライドあるいは拡張の方法について説明する。

基本事項

sbt0.10以降では、classpathはScalaライブラリを含み、(依存で宣言されているならば)Scalaコンパイラをも含む。 Classpath関連のSettingは通常Classpathタイプの値を提供するが、これはSeq[Attributed[File]]の別名になっている。Attributedというのは、それぞれのクラスパスエントリのヘテロジニアスなマップを構成するものである(訳注:?)。 Currently, this allows sbt to associate the Analysis resulting from compilation with the corresponding classpath entry and for managed entries, the ModuleID and Artifact that defined the dependency.

明示的に生のSeq[File]を取得するには、Classpathに暗黙的に追加されたfilesメソッドを使用する。

val cp: Classpath = ...
val raw: Seq[File] = cp.files

Seq[File]からClasspathを作成するにはclasspathメソッドを使い、 FileからAttributed[File]を作成するには、Attribugted.blankを使えばいい。

val raw: Seq[File] = ...
val cp: Classpath = raw.classpath

val rawFile: File = ..
val af: Attributed[File] = Attributed.blank(rawFile)

非管理下(Unmanaged)と管理下(managed)

クラスパス、ソース、リソースは、unmanagedとmanagedという二つのメインカテゴリに分割できる。 unmanagedファイルはマニュアルで作成されたファイルであり、ビルドのコントロール外にあり、それらはビルドの入力になる。 managedファイルはビルドのコントロール下にある。これらには、生成されたソースやリソース、解決され取得された依存、コンパイル済classがある。

managedファイルを生成するタスクは以下のように追加することができる。

sourceGenerators in Compile <+= sourceManaged in Compile map { out =>
        generate(out / "some_directory")
}

この例においてgenerateとは「File => Seq[File]」型の何らかの関数であり、その仕事を実際に行うものだ。 <+=メソッドは+=のようなものだが、右辺に何らかの入力を許す(ちょうど:=と<<=の違いと同じ)。 このようにして、メインのソースジェネレータ(sourceGenerators in Compile)のリストに新たなタスクを追加することができる。

プラグインの場合には、名前付きのタスクを追加したほうがよいだろう。

sourceGenerators in Compile <+= (mySourceGenerator in Compile).task

mySourceGenerator in Compile <<= sourceManaged in Compile map { out =>
    generate(out / "some_directory")
}

mySourceGeneratorは以下のように定義されている。

val mySourceGenerator = TaskKey[Seq[File]](...)

The task method is used to refer to the actual task instead of the result of the task.

For resources, there are similar keys resourceGenerators and resourceManaged. Excluding source files by name

The project base directory is by default a source directory in addition to src/main/scala. You can exclude source files by name (butler.scala in the example below) like:

excludeFilter in unmanagedSources := "butler.scala" 

Read more on How to exclude .scala source file in project folder - Google Groups External v. internal

Classpaths are also divided into internal and external dependencies. The internal dependencies are inter-project dependencies. These effectively put the outputs of one project on the classpath of another project.

External classpaths are the union of the unmanaged and managed classpaths. Keys

For classpaths, the relevant keys are:

  • unmanaged-classpath
  • managed-classpath
  • external-dependency-classpath
  • internal-dependency-classpath

For sources:

  • unmanaged-sources These are by default built up from unmanaged-source-directories, which consists of scala-source and java-source. managed-sources These are generated sources. sources Combines managed-sources and unmanaged-sources. source-generators These are tasks that generate source files. Typically, these tasks will put sources in the directory provided by source-managed.

For resources

  • unmanaged-resources These are by default built up from unmanaged-resource-directories, which by default is resource-directory, excluding files matched by default-excludes. managed-resources By default, this is empty for standard projects. sbt plugins will have a generated descriptor file here. resource-generators These are tasks that generate resource files. Typically, these tasks will put resources in the directory provided by resource-managed.

Use the inspect command for more details. Example

You have a standalone project which uses a library that loads xxx.properties from classpath at run time. You put xxx.properties inside directory "config". When you run "sbt run", you want the directory to be in classpath.

unmanagedClasspath in Runtime <<= (unmanagedClasspath in Runtime, baseDirectory) map { (cp, bd) => cp :+ Attributed.blank(bd / "config") }

Or shorter:

unmanagedClasspath in Runtime <+= (baseDirectory) map { bd => Attributed.blank(bd / "config") }