sbt adalah alat build utama ekosistem Scala yang mengompilasi kode, mengelola dependensi, menjalankan pengujian, dan mengemas hasil dalam satu proses build. Topik ini membahas anatomi build.sbt, struktur direktori proyek, notasi dependensi, pembagian proyek menjadi beberapa modul, serta tugas utama seperti compile, test, dan run. Bagian akhir menempatkan sbt berdampingan dengan Scala CLI agar pemilihan alatnya tepat. Setelah topik ini diikuti, berkas build Scala yang lazim dijumpai pada proyek nyata dapat dibaca dan disusun.
Struktur direktori proyek sbt#
sbt mengenali sebuah folder sebagai proyek apabila folder itu memuat berkas build.sbt pada akarnya. Kode produksi ditempatkan pada src/main/scala, kode pengujian pada src/test/scala, dan konfigurasi pendukung build pada folder project. Susunan ini membuat pemisahan kode produksi, kode pengujian, dan konfigurasi terjadi otomatis tanpa daftar berkas manual.
kalkulator-suhu/
├── build.sbt
├── project/
│ └── build.properties
└── src/
├── main/
│ └── scala/
│ └── KonversiSuhu.scala
└── test/
└── scala/
└── UjiKonversiSuhu.scalaDefinisi build paling sederhana memuat identitas proyek, versi Scala, dan daftar dependensi. Berkas berikut adalah build.sbt utuh untuk proyek pada struktur di atas.
lazy val root = (project in file("."))
.settings(
name := "kalkulator-suhu",
version := "0.1.0",
scalaVersion := "3.9.0",
libraryDependencies ++= Seq(
"io.circe" %% "circe-generic" % "0.14.13",
"org.scalameta" %% "munit" % "1.1.1" % Test
)
)Setiap baris di dalam settings berbentuk kunci := nilai. Kunci name menyatakan nama proyek, version menyatakan versi artefak hasil build, dan scalaVersion menentukan kompiler Scala yang digunakan. Kunci libraryDependencies menampung daftar dependensi yang dijelaskan pada bagian berikutnya. Versi sbt sendiri tidak diatur pada build.sbt, melainkan pada berkas project/build.properties.
sbt.version=1.13.1Notasi dependensi dan resolusinya#
Dependensi dinyatakan pada kunci libraryDependencies dalam bentuk grup, artefak, dan versi. Operator %% di antara grup dan artefak berlaku untuk pustaka Scala yang diterbitkan silang, yaitu diterbitkan dalam beberapa varian per versi Scala. Operator itu menambahkan akhiran versi Scala secara otomatis, sehingga "io.circe" %% "circe-generic" % "0.14.13" diselesaikan menjadi artefak circe-generic_3 karena scalaVersion proyek adalah 3.9.0. Artefak Java murni tidak memiliki varian semacam itu dan ditulis dengan satu % saja.
libraryDependencies ++= Seq(
"io.circe" %% "circe-generic" % "0.14.13",
"org.slf4j" % "slf4j-nop" % "2.0.17",
"org.scalameta" %% "munit" % "1.1.1" % Test
)Konfigurasi % Test pada baris terakhir membuat munit hanya tersedia saat kompilasi dan eksekusi kode pengujian, tidak disertakan dalam artefak produksi. Operator ++= menambahkan seluruh isi daftar sekaligus. Sejak sbt 1.3, resolusi dependensi dikerjakan oleh Coursier, yaitu pustaka penyelesai dependensi yang mengunduh artefak dari Maven Central secara paralel dan menyimpannya pada cache bersama antarproyek. sbt juga menyelesaikan dependensi transitif secara otomatis, sehingga satu entri dapat menarik beberapa artefak pendampingnya.
Proyek multi-modul#
Build yang besar biasanya dipecah menjadi beberapa modul, yaitu subproyek dengan kode dan konfigurasi sendiri di dalam satu build. Pada build.sbt, setiap modul dinyatakan sebagai nilai project beserta pengaturannya, dan folder modulnya dinamai sesuai nilai tersebut.
lazy val inti = project
.settings(
name := "kalkulator-inti"
)
lazy val aplikasi = project
.dependsOn(inti)
.settings(
name := "kalkulator-aplikasi"
)
lazy val root = (project in file("."))
.aggregate(inti, aplikasi)Definisi di atas membuat modul inti dan aplikasi pada folder inti/ dan aplikasi/. Panggilan dependsOn menyatakan bahwa aplikasi menggunakan kelas dari inti, sehingga mengompilasi aplikasi otomatis mengompilasi inti lebih dahulu. Panggilan aggregate membuat tugas yang dijalankan pada root berlaku juga untuk kedua modulnya, misalnya satu perintah test memeriksa keduanya. Pola ini memisahkan kode yang digunakan ulang dari kode yang mengonsumsinya tanpa memisahkan repositori.
Tugas compile, test, dan run#
sbt dijalankan sebagai shell build, yaitu sesi interaktif yang menerima nama tugas. Mengetik sbt pada akar proyek membuka shell tersebut, kemudian tugas dipanggil dengan namanya.
# tidak-dijalankan
sbt compileTugas compile mengompilasi kode produksi, test menjalankan pengujian, dan run mengompilasi lalu mengeksekusi kelas utama. Tanda ~ di depan nama tugas mengaktifkan eksekusi ulang otomatis setiap berkas sumber berubah, misalnya ~compile. Perintah console membuka REPL Scala yang classpath-nya sudah memuat dependensi proyek. Semua tugas juga dapat dipanggil dalam satu proses tanpa shell, misalnya sbt clean compile, dan bentuk inilah yang lazim digunakan pada skrip build otomatis.
Posisi sbt dibanding Scala CLI#
Scala CLI mencakup kebutuhan belajar dan proyek kecil karena konfigurasinya melekat pada berkas sumber dan setiap perintah berjalan langsung dari terminal. sbt menjadi standar proyek besar karena mendukung build multi-modul, ekosistem plugin, publikasi artefak, dan integrasi dengan alat build otomatis. Keduanya mengunduh artefak melalui Coursier dan menargetkan kompiler Scala yang sama, sehingga pemahaman dependensi pada satu alat berlaku juga pada alat lainnya.
| Aspek | Scala CLI | sbt |
|---|---|---|
| Konfigurasi | Direktif pada berkas sumber | build.sbt dan folder project |
| Proyek multi-modul | Satu direktori proyek tunggal | Dukungan penuh dengan dependsOn dan aggregate |
| Cara menjalankan | Perintah tunggal dari terminal | Shell build interaktif atau mode satu proses |
| Perluasan | Opsi dan direktif bawaan | Ekosistem plugin yang luas |
Proyek belajar dan contoh berbentuk program kecil cukup dikelola dengan Scala CLI. Pindah ke sbt saat proyek membutuhkan pembagian modul, pengujian terjadwal pada build otomatis, atau konvensi yang dipahami seluruh ekosistem Scala.
Kesalahan umum#
Menggunakan %% untuk artefak Java murni. Operator itu menambahkan akhiran versi Scala pada nama artefak, sehingga pencarian artefak gagal dengan error dependensi tidak ditemukan. Perbaikannya adalah menulis satu % untuk artefak Java.
Tidak mengunci versi sbt pada project/build.properties. Peluncur kemudian menggunakan versi bawaan yang mungkin berbeda dari versi yang digunakan saat menulis build, sehingga perubahan perilaku antarversi dapat memicu error build yang membingungkan. Cantumkan sbt.version sejak proyek pertama.
Meletakkan kode sumber di luar src/main/scala. sbt hanya mengompilasi folder sumber yang dideklarasikannya, sehingga berkas yang berserakan di akar proyek tidak ikut terkompilasi dan kelas utamanya tidak ditemukan saat tugas run dipanggil. Ikuti struktur src/main/scala dan src/test/scala sejak awal.
Ringkasan#
- Proyek sbt diakui dari
build.sbtpada akar folder, dengan kode produksi padasrc/main/scaladan pengujian padasrc/test/scala. - Kunci
name,version, danscalaVersionmenyusun identitas proyek, sedangkanlibraryDependenciesbeserta operator%%dan%menyatakan dependensinya. - Versi sbt dikunci pada
project/build.properties, dan build besar dipecah menjadi modul melaluidependsOndanaggregate. - Tugas
compile,test, danrundipanggil dari shell sbt atau dari mode satu proses.
Referensi#
- Getting Started with sbt — sbt — Langkah pertama menggunakan sbt dan struktur dasar proyeknya.
- Basic Def — sbt
— Anatomi
build.sbtdan aturan penulisan pengaturannya. - Library Dependencies — sbt
— Cara menyatakan dependensi beserta notasi
%%dan konfigurasi% Test. - Multi-Project — sbt — Membagi satu build menjadi beberapa subproyek.