1. よくある質問

よくある質問 

プロジェクト情報 

「sbt」という名前は何の略ですか?また、なぜ「SBT」と書いてはいけないのですか? 

要約: sbt という名前は何かの略ではなく、単に「sbt」です。そのように書く必要があります。

Mark Harrah (@harrah) が最初にこのプロジェクトを作成したとき、「Simple Build Tool」と呼んでいましたが、最初の公式発表では、すでに単に「sbt」と呼んでいました。時が経つにつれて、sbt を「Scala Build Tool」の略として再定義する人もいましたが、Java のみのプロジェクトをビルドするためにも使用できることを考えると、それも正確ではないと考えています。

現在では、sbt を単に「sbt」と呼んでおり、名前がもはや頭字語ではないことを強調するために、常にすべて小文字で記述しています。ただし、酢豚 (subuta) をニックネームとして使用することは問題ありません。

ヘルプを表示するにはどうすればよいですか? 

バグを報告するにはどうすればよいですか? 

どのように貢献できますか? 

使用方法 

最後に入力したコマンドが機能しませんでした。しかし、説明が表示されません。なぜですか? 

sbt 1.9.8 は、デフォルトでは、ほとんどのスタックトレースとデバッグ情報を抑制します。画面上のノイズを少なくするという良い副作用がありますが、初心者にとっては説明がわからなくなる可能性があります。コマンドの以前の出力をより詳細な冗長性で表示するには、「last <task>」と入力します。ここで、「<task>」は失敗したタスク、または詳細な出力を表示するタスクです。たとえば、「update」が期待どおりにすべての依存関係をロードできないことがわかった場合は、次のように入力します。

> last update

すると、「update」コマンドの最後の実行からの完全な出力が表示されます。

出力で ANSI コードを無効にするにはどうすればよいですか? 

sbt が ANSI コードがサポートされていないことを検出しない場合があり、次のような出力が表示されることがあります。

[0m[ [0minfo [0m]  [0mSet current project to root

または、ANSI コードはサポートされていますが、色付きの出力を無効にしたい場合があります。ANSI コードを完全に無効にするには、「-no-colors」オプションを渡します。

$ sbt -no-colors

sbt プロジェクト設定 (依存関係など) で Scala インタプリタ (REPL) を起動するにはどうすればよいですか? 

sbt のシェルで「console」を実行します。

ビルド定義 

「:=」、「+=」、および「++=」メソッドとは何ですか? 

これらは、「Setting」または「Task」を構築するために使用されるキーのメソッドです。入門ガイドでは、これらのすべてのメソッドについて説明しています。たとえば、.sbt ビルド定義タスクグラフ値の追加を参照してください。

「%」メソッドとは何ですか? 

管理された依存関係を指定するときに、文字列から「ModuleID」を作成するために使用されます。ライブラリの依存関係に関する入門ガイドをお読みください。

「ThisBuild / scalaVersion」とはどういう意味ですか? 

`ThisBuild` は、ビルドのデフォルト値を定義するために使用できる特別なサブプロジェクト名として機能します。1 つ以上のサブプロジェクトを定義し、サブプロジェクトが `scalaVersion` キーを定義していない場合、`ThisBuild / scalaVersion` を探します。

ビルド全体の設定を参照してください。

「ModuleID」、「Project」、…とは何ですか? 

不明な型またはメソッドを調べるには、まだの場合は入門ガイドをご覧ください。また、一般的に使用されるメソッド、値、および型の索引と、API ドキュメントも試してみてください。

jar パッケージにファイルを追加するにはどうすればよいですか? 

アーティファクトに含まれるファイルは、デフォルトでは、関連するパッケージタスクによってスコープが設定されたタスク「mappings」によって設定されます。「mappings」タスクは、含めるファイルから jar 内のパスへのマッピングのシーケンス `Seq[(File,String)]` を返します。これらのマッピングの作成の詳細については、ファイルのマッピングを参照してください。

たとえば、生成されたソースをパッケージ化されたソースアーティファクトに追加するには、次のようにします。

Compile / packageSrc / mappings ++= {
  import Path.{flat, relativeTo}
  val base = (Compile / sourceManaged).value
  val srcs = (Compile / managedSources).value
  srcs pair (relativeTo(base) | flat)
}

これは、「managedSources」タスクからソースを取得し、「managedSource」ベースディレクトリに対して相対化し、フラット化されたマッピングにフォールバックします。ソース生成タスクが「managedSource」ディレクトリにソースを書き込まない場合、マッピング関数を調整して、追加のディレクトリに対して相対化を試みるか、ジェネレーターに適したものにする必要があります。

ソースコードまたはリソースを生成するにはどうすればよいですか? 

ファイルの生成を参照してください。

入力ファイルが変更されていない場合、タスクはどのように作業のやり直しを回避できますか? 

キャッシングを参照してください。

sbt の拡張 

新しい依存関係設定を追加するにはどうすればよいですか? 

カスタム依存関係設定を定義する方法を参照してください。

テスト設定を追加するにはどうすればよいですか? 

テスト追加のテスト設定セクションを参照してください。

「run」に加えて、カスタム実行タスクを作成するにはどうすればよいですか? 

この回答は、メーリングリストのディスカッションから抜粋したものです。

背景については、カスタム設定までの入門ガイドをお読みください。

基本的な実行タスクは、次のように作成されます。

lazy val myRunTask = taskKey[Unit]("A custom run task.")

// this can go either in a `build.sbt` or the settings member
//   of a Project in a full configuration
fullRunTask(myRunTask, Test, "foo.Foo", "arg1", "arg2")

コマンドラインで引数を指定できるようにするには、「TaskKey」を「InputKey」に、「fullRunTask」を「fullRunInputTask」に置き換えます。「Test」部分は、「Compile」などの別の設定に置き換えて、その設定のクラスパスを使用できます。

この実行タスクは、スコープでタスクキーを指定することで、個別に設定できます。たとえば、

myRunTask / fork := true

myRunTask / javaOptions += "-Xmx6144m"

Proguardのような外部ツールへの依存関係はどのように表現すればよいですか? 

ツールの依存関係はタスクの実装に使用され、プロジェクトのソースコードでは必要ありません。これらの依存関係は、独自の構成とクラスパスで宣言できます。手順は以下のとおりです。

  1. 新しい構成を定義します。
  2. その構成でツールの依存関係を宣言します。
  3. updateによって生成された更新レポートから依存関係を取得するクラスパスを定義します。
  4. クラスパスを使用してタスクを実装します。

例として、proguardタスクを考えてみましょう。このタスクは、ツールを実行するためにProGuard jarを必要とします。まず、新しい構成を定義して追加します。

lazy val ProguardConfig = config("proguard").hide

ivyConfigurations += ProguardConfig

次に、

// Add proguard as a dependency in the custom configuration.
//  This keeps it separate from project dependencies.
libraryDependencies +=
   "net.sf.proguard" % "proguard" % "4.4" % ProguardConfig.name

// Extract the dependencies from the UpdateReport.
ProguardConfig / managedClasspath := {
    // these are the types of artifacts to include
    val artifactTypes: Set[String] = (ProguardConfig / classpathTypes).value
    Classpaths.managedJars(proguardConfig, artifactTypes, update.value)
}

// Use the dependencies in a task, typically by putting them
//  in a ClassLoader and reflectively calling an appropriate
//  method.
proguard := {
    val cp: Seq[File] = (ProguardConfig / managedClasspath).value
  // ... do something with , which includes proguard ...
}

中間クラスパスの定義はオプションですが、デバッグに役立つ場合や、複数のタスクで使用される必要がある場合に便利です。アーティファクトタイプをインラインで指定することも可能です。この代替のproguardタスクは次のようになります。

proguard := {
   val artifactTypes = Set("jar")
    val cp =
      Classpaths.managedJars(proguardConfig, artifactTypes, update.value)
  // ... do something with , which includes proguard ...
}

sbtのクラスパスを動的に変更するにはどうすればよいですか? 

sbtのクラスパスに配置される追加のjarを登録することができます。Stateを通して、アプリケーションコンポーネントを管理するxsbti.ComponentProviderを取得できます。コンポーネントは~/.sbt/boot/ディレクトリにあるファイルのグループであり、この場合はアプリケーションはsbtです。基本クラスパスに加えて、「extra」コンポーネントのコンポーネントがsbtのクラスパスに含まれます。

(注:アプリケーションのクラスパスに追加されるコンポーネントは、ランチャー構成ファイルboot.properties[main]セクションのcomponentsプロパティによって宣言されます。)

これらのコンポーネントは~/.sbt/boot/ディレクトリに追加され、~/.sbt/boot/は読み取り専用である可能性があるため、これは失敗する可能性があります。この場合、ユーザーは一般的に意図的にsbtをこのように設定しているため、エラー回復は通常必要ありません(状況を説明する短いエラーメッセージだけで十分です)。

動的クラスパス拡張の例 

以下のコードは、State => Stateが必要な場合、例えば、onLoad設定(下記参照)やコマンドなどで使用できます。これは「extra」コンポーネントにいくつかのファイルを追加し、まだ追加されていない場合はsbtをリロードします。リロードすると、ユーザーのセッション状態が失われることに注意してください。

def augment(extra: Seq[File])(s: State): State = {
    // Get the component provider
  val cs: xsbti.ComponentProvider = s.configuration.provider.components()

    // Adds the files in 'extra' to the "extra" component
    //   under an exclusive machine-wide lock.
    //   The returned value is 'true' if files were actually copied and 'false'
    //   if the target files already exists (based on name only).
  val copied: Boolean = s.locked(cs.lockFile, cs.addToComponent("extra", extra.toArray))

    // If files were copied, reload so that we use the new classpath.
  if(copied) s.reload else s
}

プロジェクトがロードまたはアンロードされたときにアクションを実行するにはどうすればよいですか? 

起動時にアクションを実行する方法を参照してください。

プロジェクトのロード/アンロードフックの例 

次の例では、プロジェクトがロードされた回数をカウントし、その数を表示します。

{
  // the key for the current count
  val key = AttributeKey[Int]("loadCount")
  // the State transformer
  val f = (s: State) => {
    val previous = s get key getOrElse 0
    println("Project load count: " + previous)
    s.put(key, previous + 1)
  }
  Global / onLoad := {
    val previous = (Global / onLoad).value
    f compose previous
  }
}

エラー 

プロジェクトのロード時に、「初期化されていない設定への参照」 

設定イニシャライザは順番に実行されます。設定の初期化が初期化されていない他の設定に依存している場合、sbtはロードを停止します。

この例では、空のシーケンスで初期化する前に、libraryDependenciesにライブラリを追加しようとしています。

libraryDependencies += "commons-io" % "commons-io" % "1.4" % "test"

disablePlugins(plugins.IvyPlugin)

これを修正するには、libraryDependencies := Seq()を含むIvyPluginプラグイン設定を含めます。そのため、明示的な無効化を削除するだけです。

libraryDependencies += "commons-io" % "commons-io" % "1.4" % "test"

このエラーのより微妙なバリエーションは、スコープ設定を使用する場合に発生します。

// error: Reference to uninitialized setting
settings = Seq(
  libraryDependencies += "commons-io" % "commons-io" % "1.2" % "test",
  fullClasspath := fullClasspath.value.filterNot(_.data.name.contains("commons-io"))
)

この設定は、テストスコープとコンパイルスコープで異なります。解決策は、イニシャライザへの入力として、そして更新する設定として、スコープ設定を使用することです。

Compile / fullClasspath := (Compile / fullClasspath).value.filterNot(_.data.name.contains("commons-io"))

依存関係管理 

チェックサムエラーを解決するにはどうすればよいですか? 

このエラーは、sha1やmd5ハッシュなどの公開されているチェックサムが、jarやpom.xmlなどのダウンロードされたアーティファクトに対して計算されたチェックサムと異なる場合に発生します。このようなエラーの例は次のとおりです。

[warn]  problem while downloading module descriptor:
https://repo1.maven.org/maven2/commons-fileupload/commons-fileupload/1.2.2/commons-fileupload-1.2.2.pom:
invalid sha1: expected=ad3fda4adc95eb0d061341228cc94845ddb9a6fe computed=0ce5d4a03b07c8b00ab60252e5cacdc708a4e6d8 (1070ms)

無効なチェックサムは、一般的にリポジトリの所有者に報告する必要があります(上記のエラーについてはこちらで行われました)。 一時的にチェックを無効にするには、次の設定を使用します。

checksums in update := Nil

詳細は、ライブラリ管理を参照してください。

プラグインを追加したら、クロスコンパイルが失敗するようになりました! 

この問題は頻繁に発生します。プラグインは、sbtが使用するScalaバージョン(現在は2.12)に対してのみ公開されます。 sbtはプラグインの2.12バージョンのみを検索するため、クロスコンパイル中にプラグインを*使用*することはできます。

…間違った場所にプラグインを指定しない限り!

典型的な間違いは、グローバルプラグイン定義を~/.sbt/plugins.sbtに配置することです。 **これは間違っています。** ~/.sbtにある.sbtファイルは、*各*ビルド、つまり*各*クロスコンパイルに対してロードされます。そのため、Scala 2.11.0用にビルドする場合、sbtは2.11.0用にコンパイルされたプラグインのバージョンを見つけようとしますが、通常は見つかりません。依存関係がプラグインであることを*知ら*ないからです。

依存関係がsbtプラグインであることをsbtに伝えるには、グローバルプラグインを~/.sbt/plugins/にある.sbtファイルで定義してください。 sbtは、~/.sbt/plugins内のファイルはsbt自体によってのみ使用され、一般的なビルド定義の一部としては使用されないことを認識しています。 *その*ディレクトリの下にあるファイルでプラグインを定義すると、クロスコンパイルが混乱することはありません。 .sbtで終わるファイル名であれば何でも構いませんが、ほとんどの人は~/.sbt/plugins/build.sbtまたは~/.sbt/plugins/plugins.sbtを使用します。

その他 

1.9.8のプラグインはどこにありますか? 

現在利用可能なプラグインのリストについては、コミュニティプラグインを参照してください。