Proyek fpm

Struktur fpm.toml, manajemen dependensi, dan test harness bawaan pada proyek fpm.

Daftar isi

Fortran Package Manager (fpm) adalah alat resmi ekosistem Fortran modern untuk menyusun, menguji, dan membagikan proyek beserta dependensinya. Alat ini hanya menuntut satu berkas manifest bernama fpm.toml dan tiga direktori bawaan, yaitu src/ untuk pustaka, app/ untuk program, serta test/ untuk pengujian. Struktur sesederhana itu sudah menggantikan skrip kompilasi manual. Topik ini membangun satu proyek fpm kecil dari nol, menampilkan manifest dan struktur pohonnya, lalu menjalankan fpm run dan fpm test untuk melihat perilaku keduanya. Kode sumber proyek tersedia sebagai berkas .f90 di direktori topik ini sehingga setiap perintah dapat diulang.

Manifest fpm.toml dan struktur proyek#

Manifest fpm.toml berisi metadata proyek dan daftar dependensinya. Manifest paling kecil hanya memuat nama dan versi, sedangkan kunci lain diisi bila diperlukan. Bentuk sesederhana ini justru menjadi nilai utamanya bagi kolaborasi: seluruh definisi cara proyek dibangun tercatat pada satu berkas teks pendek yang ikut tersimpan di git bersama kode sumbernya. Anggota tim yang baru menggandakan repositori tidak perlu membaca skrip atau catatan pribadi penulis aslinya karena semua langkah bangun diturunkan dari manifest dan struktur konvensional itu. Proyek contoh pada topik ini memakai manifest berikut.

toml Contoh: fpm.toml proyek-luas
name = "proyek-luas"
version = "0.1.0"

Nama proyek menentukan nama pustakanya, yaitu libproyek-luas.a, sekaligus nama program hasil kompilasi dari app/. Struktur direktori minimal yang dibaca fpm tampak seperti berikut.

text Struktur pohon proyek-luas
proyek-luas/
├── fpm.toml
├── src/
│   └── geometri.f90
├── app/
│   └── main.f90
└── test/
    └── check.f90

Berkas pada src/ menjadi satu pustaka yang dipakai bersama oleh seluruh program dan pengujian. fpm tidak menuntut nama berkas tertentu pada src/, karena setiap berkas .f90 di sana diindeks menurut modul yang dimuatnya. Setiap berkas .f90 pada app/ yang memuat program dibangun menjadi program terpisah, dan berkas app/main.f90 dianggap program utamanya. Berkas test/check.f90 adalah kerangka pengujian bawaan hasil perintah fpm new yang dibiarkan utuh pada proyek ini. Karena semua proyek fpm mengikuti pola pohon yang sama, anggota baru yang memahami satu proyek langsung tahu ke mana harus mencari pustaka, program, dan pengujian pada proyek berikutnya.

Dua berkas berikut dipindahkan ke struktur proyek pada langkah eksekusi. Modul geometri menjadi isi pustaka, sedangkan program cetak_luas menjadi isi app/main.f90.

fortran geometri.f90
module geometri
   implicit none
   private
   public :: luas_lingkaran, keliling_lingkaran

   real, parameter :: pi = acos(-1.0)
contains
   pure function luas_lingkaran(jari) result(luas)
      real, intent(in) :: jari
      real :: luas
      luas = pi * jari ** 2
   end function luas_lingkaran

   pure function keliling_lingkaran(jari) result(keliling)
      real, intent(in) :: jari
      real :: keliling
      keliling = 2.0 * pi * jari
   end function keliling_lingkaran
end module geometri
fortran cetak_luas.f90
program cetak_luas
   use geometri, only : luas_lingkaran, keliling_lingkaran
   implicit none
   integer :: i
   do i = 1, 3
      print '(a, i0, a, f8.3, a, f8.3)', &
         & "jari-jari ", i, ": luas ", luas_lingkaran(real(i)), &
         & ", keliling ", keliling_lingkaran(real(i))
   end do
end program cetak_luas

Membangun dan menjalankan proyek#

Perintah fpm new <direktori> membuat kerangka proyek lengkap dengan git terinisialisasi. Proyek contoh di sini tetap dibuat dengan perintah itu, tetapi isi berkas bawaannya diganti secara manual agar setiap bagian terlihat jelas. Blok berikut membersihkan sisa proyek sebelumnya, membuat kerangka dengan fpm new, mengganti berkas bawaannya dengan kode dari direktori topik, dan menulis manifest.

bash
# hapus sisa proyek lama, lalu buat kerangka proyek baru
rm -rf /tmp/proyek-luas && fpm new /tmp/proyek-luas > /dev/null 2>&1
# buang berkas contoh bawaan kerangka
rm /tmp/proyek-luas/src/proyek-luas.f90 /tmp/proyek-luas/app/main.f90
# salin kode dari direktori topik ke struktur proyek
cp geometri.f90 /tmp/proyek-luas/src/geometri.f90
cp cetak_luas.f90 /tmp/proyek-luas/app/main.f90
# tulis manifest proyek
cat > /tmp/proyek-luas/fpm.toml <<'EOF'
name = "proyek-luas"
version = "0.1.0"
EOF

Perintah fpm run menyusun proyek lalu menjalankan programnya dalam satu langkah. Pada bangun pertama, fpm mencetak kemajuan kompilasi setiap objek berikut baris [100%] Project compiled successfully., dan urutan baris kemajuan itu bergantung pada penjadwalan bangun. Tiga baris terakhir keluarannya adalah keluaran program itu sendiri, dan tiga baris itulah yang diambil dengan tail pada blok berikut. Pada eksekusi berikutnya keluaran kemajuan jauh lebih pendek karena fpm memakai kembali artefak bangun yang masih sesuai dan hanya menyusun ulang berkas sumber yang berubah.

bash
# susun dan jalankan program utama
(cd /tmp/proyek-luas && fpm run 2>&1 | tail -n 3)
text Keluaran
jari-jari 1: luas    3.142, keliling    6.283
jari-jari 2: luas   12.566, keliling   12.566
jari-jari 3: luas   28.274, keliling   18.850

Baris kemajuan pada eksekusi lengkap menunjukkan urutan bangun: modul geometri dikompilasi lebih dahulu menjadi pustaka libproyek-luas.a, kemudian main.f90 ditautkan terhadapnya menjadi program proyek-luas. Seluruh artefak bangun ditempatkan pada direktori build/ sehingga pohon sumber tetap bersih, dan direktori itu aman dihapus kapan pun karena dapat dibangun ulang dari sumbernya. Sifat murni turunan itu pula yang membuat build/ lazim dikeluarkan dari repositori git: keberadaannya sepenuhnya ditentukan oleh manifest dan isi src/, app/, serta test/.

Dependensi dan test harness bawaan#

Dependensi dideklarasikan pada bagian [dependencies] manifest dengan sumber git atau jalur lokal. fpm mengunduh dependensi git saat proyek dibangun dan menyimpannya pada build/dependencies/, sehingga opsi penyambung tidak perlu diatur manual untuk menunjuk pustaka dependensinya. Bagi kolaborasi, mekanisme ini memindahkan beban pemasangan pustaka dari setiap anggota tim kepada fpm: satu baris pada manifest membuat semua orang yang membangun proyek memperoleh pustaka yang sama tanpa langkah pemasangan manual.

toml Contoh: deklarasi dependensi
[dependencies]
test-drive = { git = "https://github.com/fortran-lang/test-drive" }

Perintah fpm test membangun dan menjalankan setiap program pada test/, satu per satu. Perilaku yang seragam ini membuat fpm test layak dijadikan perintah verifikasi tunggal sebuah proyek: ketika jumlah pengujian bertambah, pemeriksaannya tetap berjalan dengan satu ketukan tanpa daftar program yang harus dirawat manual. Proyek yang baru dirakit masih memakai kerangka pengujian bawaan dari fpm new, sehingga satu-satunya keluarannya adalah pesan bahwa pengujian sungguhan belum ditulis.

bash
# jalankan seluruh program pengujian
(cd /tmp/proyek-luas && fpm test 2>&1 | tail -n 1)
text Keluaran
 Put some tests in here!

Kerangka bawaan itu baru diganti ketika pengujian sungguhan ditulis. Penggunaan pustaka test-drive pada test/, beserta keluaran keberhasilan dan kegagalannya, dibahas pada topik pengujian kode numerik di modul ini.

Kesalahan umum#

  • Menaruh modul pustaka di app/ alih-alih src/. Berkas pada app/ dianggap program, sehingga modul di sana dikompilasi ulang untuk setiap program dan pengujian yang memakainya. Modul yang dipakai bersama ditempatkan pada src/.
  • Mengubah nama proyek sembari mengandalkan sisa build/. Perubahan nama pada fpm.toml mengubah nama pustaka dan program, sedangkan artefak lama tetap tersisa. Hapus build/ agar bangun ulangnya bersih.
  • Menulis manifest sebagai JSON atau YAML. fpm hanya membaca format TOML, dan kesalahan sintaks TOML dilaporkan beserta nomor barisnya saat fpm build dijalankan.

Ringkasan#

  • Proyek fpm berdiri di atas fpm.toml dan tiga direktori bawaan: src/ untuk pustaka, app/ untuk program, dan test/ untuk pengujian.
  • fpm run dan fpm test menyusun lalu menjalankan program dan pengujian, dengan artefak bangun terpusat di build/.
  • Dependensi dideklarasikan pada [dependencies] dan diunduh otomatis saat proyek dibangun.

Referensi#