アーティファクト
説明
サブプロジェクトの特定バージョンを公開するためのファイルは、特別に「アーティファクト」と呼ばれる。この概念は Apache Maven と Ivy に由来する。
JVM エコシステムでは、一般的なアーティファクトは Java アーカイブ(JAR ファイル)である。管理・ダウンロード・保存が容易なため、圧縮パッケージ形式が好まれる。
例として、ライブラリのアーティファクト一覧を ivy.xml ファイルで示す:
<publications>
<artifact name="core_3" type="jar" ext="jar" conf="compile"/>
<artifact e:classifier="sources" name="core_3" type="src" ext="jar" conf="sources"/>
<artifact e:classifier="javadoc" name="core_3" type="doc" ext="jar" conf="docs"/>
<artifact name="core_3" type="pom" ext="pom" conf="pom"/>
</publications>
ここから、アーティファクトは name、type、extension という属性を持ち、オプションで classifier があることが分かる。
- name。サブプロジェクトのモジュール名と同じになる。
- type。アーティファクトの機能カテゴリ。
jar、src、docなど。 - extension。
jar、war、zip、xmlなどのファイル拡張子。 - classifier。Maven では、代替または二次アーティファクト用に付加できる任意の文字列である。
デフォルト・アーティファクトの選択
デフォルトで公開されるアーティファクトは以下の通りである:
- メインのバイナリ JAR
- メインのソースとリソースを含む JAR
- API ドキュメントを含む JAR
テストクラス、ソース、API 用のアーティファクトを追加したり、メインアーティファクトの一部を無効にしたりできる。
すべての Test アーティファクトを追加する場合:
lazy val app = (project in file("app"))
.settings(
Test / publishArtifact := true,
)
個別に追加する場合:
lazy val app = (project in file("app"))
.settings(
// enable publishing the jar produced by `Test/package`
Test / packageBin / publishArtifact := true,
// enable publishing the test API jar
Test / packageDoc / publishArtifact := true,
// enable publishing the test sources jar
Test / packageSrc / publishArtifact := true,
)
メインアーティファクトを個別に無効にする場合:
lazy val app = (project in file("app"))
.settings(
// disable publishing the main jar produced by `package`
Compile / packageBin / publishArtifact := false,
// disable publishing the main API jar
Compile / packageDoc / publishArtifact := false,
// disable publishing the main sources jar
Compile / packageSrc / publishArtifact := false,
)
デフォルト・アーティファクトの変更
組み込みアーティファクトには publishArtifact に加え、いくつかの設定可能なセッティングがある。基本となるのは artifact(型 SettingKey[Artifact])、mappings(型 TaskKey[(File, String)])、artifactPath(型 SettingKey[File])である。前セクションで示した通り、(Config / <task>) でスコープされる。
メインアーティファクトの type を変更する例:
Compile / packageBin / artifact := {
val prev: Artifact = (Compile / packageBin / artifact).value
prev.withType("bundle")
}
生成されるアーティファクト名は artifactName セッティングで決まる。このセッティングの型は (ScalaVersion, ModuleID, Artifact) => String である。ScalaVersion 引数は Scala のフルバージョン文字列とバイナリ互換部分を提供する。結果の文字列は生成するファイル名である。デフォルト実装は Artifact.artifactName _ である。この関数を変更すると、artifact 定義とリポジトリパターンで決まる公開名に影響せず、ローカル名を変えられる。
例えば、classifier や cross path なしの最小限の名前を生成する場合:
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
artifact.name + "-" + module.revision + "." + artifact.extension
}
(実際には classifier を削除することはほとんどない。)
最後に、packagedArtifact タスクをマッピングしてアーティファクトの (Artifact, File) ペアを取得できる。Artifact が不要な場合は、パッケージタスク(package、packageDoc、packageSrc)から File のみ取得できる。いずれの場合も、タスクをマッピングしてファイルを取得すると、アーティファクトが先に生成され、ファイルが最新であることが保証される。
例:
val myTask = taskKey[Unit]("My task.")
myTask := {
val (art, file) = (Compile / packageBin / packagedArtifact).value
println("Artifact definition: " + art)
println("Packaged file: " + file.getAbsolutePath)
}
カスタムアーティファクトの定義
組み込みアーティファクトの設定に加え、公開する他のアーティファクトを宣言できる。Ivy メタデータでは複数アーティファクトが許可されるが、Maven POM ファイルは classifier による区別のみサポートし、これらは POM に記録されない。
基本的な Artifact の構築は以下のようになる:
Artifact("name", "type", "extension")
Artifact("name", "classifier")
Artifact("name", url: URL)
Artifact("name", Map("extra1" -> "value1", "extra2" -> "value2"))
例:
Artifact("myproject", "zip", "zip")
Artifact("myproject", "image", "jpg")
Artifact("myproject", "jdk15")
アーティファクトの詳細はIvy ドキュメントを参照。上記パラメータの組み合わせと [Configurations] および追加属性の指定はArtifact APIを参照。
これらのアーティファクトを公開用に宣言するには、アーティファクトを生成するタスクにマッピングする:
val myImageTask = taskKey[File](...)
myImageTask := {
val artifact: File = makeArtifact(...)
artifact
}
addArtifact(Artifact("myproject", "image", "jpg"), myImageTask)
addArtifact はセッティングのシーケンスを返す(SettingsDefinition でラップされる)。完全なビルドコンフィギュレーションでは、以下のように使用する:
lazy val app = (project in file("app"))
.settings(
addArtifact(...)
)
.war ファイルの公開
Web アプリケーションの一般的な用途として、.jar ファイルの代わりに .war ファイルを公開する。
lazy val app = (project in file("app"))
.settings(
// disable .jar publishing
Compile / packageBin / publishArtifact := false,
// create an Artifact for publishing the .war file
Compile / packageWar / artifact := {
val prev: Artifact = (Compile / packageWar / artifact).value
prev.withType("war").withExtension("war")
},
// add the .war file to what gets published
addArtifact(Compile / packageWar / artifact, packageWar),
)
アーティファクト付きライブラリ依存性の使用
カスタムまたは複数アーティファクトを持つライブラリ依存性から使用するアーティファクトを指定するには、ライブラリ依存性の artifacts メソッドを使用する。例:
libraryDependencies += ("org" % "name" % "rev").artifacts(Artifact("name", "type", "ext"))
from と classifier メソッド(sbt update で説明)は、実際にはartifacts に変換される便利メソッドである:
def from(url: String) = artifacts(Artifact(name, new URL(url)))
def classifier(c: String) = artifacts(Artifact(name, c))
つまり、以下の 2つのライブラリ依存性宣言は等価である:
libraryDependencies += ("org.testng" % "testng" % "5.7").classifier("jdk15")
libraryDependencies += ("org.testng" % "testng" % "5.7").artifacts(Artifact("testng", "jdk15"))