Berkas proyek

Berkas proyek GPRbuild: susunan sumber, konfigurasi, dan switch.

Daftar isi

Berkas proyek (project file) adalah berkas teks berakhiran .gpr yang memuat konfigurasi pembangunan (build) sebuah program Ada. Alat gprbuild membaca berkas proyek tersebut untuk menentukan letak sumber, berkas utama, direktori hasil, dan switch, yaitu pengaturan berawalan tanda minus yang diteruskan ke alat yang dipanggil. Topik ini membahas atribut inti berkas proyek, package Compiler untuk switch kompilator, serta pengimporan proyek lain. Setelah topik ini dibaca, proyek multiunit dapat ditulis, dikonfigurasi, dan dibangun dengan satu perintah gprbuild.

Susunan berkas proyek#

Setiap proyek ditulis dalam satu berkas .gpr yang namanya sama dengan nama proyeknya. Proyek bernama Kalkulator wajib disimpan sebagai kalkulator.gpr, dan ketidakcocokan antara nama berkas dan nama proyek dilaporkan oleh gprbuild sebagai peringatan. Isi berkas proyek berupa deklarasi yang dibuka dengan kata project dan ditutup dengan end. Atribut-atribut proyek diletakkan di antara kedua kata tersebut. Bentuk paling sederhana dari berkas proyek hanya memuat satu atribut.

ada Contoh: berkas proyek paling sederhana
-- tidak-dijalankan
project Sapa is

   for Source_Dirs use (".");

end Sapa;

Atribut Source_Dirs menentukan direktori yang memuat sumber proyek, dan nilainya berupa daftar direktori yang ditulis relatif terhadap letak berkas proyek. Tanda titik menunjuk direktori berkas proyek itu sendiri, sehingga seluruh berkas .ads dan .adb pada direktori tersebut ikut menjadi bagian proyek. Apabila atribut ini tidak dituliskan, direktori tempat berkas proyek berada yang digunakan. Pembangunan dijalankan dengan perintah gprbuild diikuti switch -P dan nama berkas proyeknya.

Proyek kalkulator#

Contoh pada topik ini adalah proyek kalkulator yang terdiri atas empat berkas, yaitu spesifikasi dan badan package Kalkulator_Ops, prosedur utama Kalkulator, dan berkas proyeknya. Package tersebut memuat fungsi Tambah serta fungsi Bagi yang dilengkapi kontrak Pre dan Post, sedangkan prosedur utama mencetak dua hasil perhitungan. Berkas proyek menggabungkan keempat berkas tersebut dalam satu pembangunan.

ada kalkulator_ops.ads
package Kalkulator_Ops is

   --  Kontrak: penyebut tidak boleh nol, dan hasilnya mengikuti
   --  sifat pembagian bilangan bulat.
   function Bagi (Pembilang, Penyebut : in Integer) return Integer with
     Pre  => Penyebut /= 0,
     Post => Bagi'Result * Penyebut + Pembilang rem Penyebut = Pembilang;

   --  Menjumlahkan dua nilai bulat.
   function Tambah (Kiri, Kanan : in Integer) return Integer;

end Kalkulator_Ops;
ada kalkulator_ops.adb
package body Kalkulator_Ops is

   function Bagi (Pembilang, Penyebut : in Integer) return Integer is
   begin
      return Pembilang / Penyebut;
   end Bagi;

   function Tambah (Kiri, Kanan : in Integer) return Integer is
   begin
      return Kiri + Kanan;
   end Tambah;

end Kalkulator_Ops;
ada kalkulator.adb
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Kalkulator_Ops;

procedure Kalkulator is
begin
   Ada.Text_IO.Put ("Tambah (7, 2) = ");
   Ada.Integer_Text_IO.Put (Kalkulator_Ops.Tambah (7, 2), Width => 1);
   Ada.Text_IO.New_Line;

   Ada.Text_IO.Put ("Bagi (100, 8) = ");
   Ada.Integer_Text_IO.Put (Kalkulator_Ops.Bagi (100, 8), Width => 1);
   Ada.Text_IO.New_Line;
end Kalkulator;
gpr kalkulator.gpr
project Kalkulator is

   for Source_Dirs use (".");
   for Object_Dir use "obj";
   for Exec_Dir use "bin";
   for Main use ("kalkulator.adb");

   package Compiler is
      for Default_Switches ("Ada") use ("-gnata");
   end Compiler;

end Kalkulator;
bash
# bangun proyek dari direktori yang memuat berkas proyeknya
gprbuild -q -P kalkulator.gpr
# jalankan program utama proyek
./bin/kalkulator
text Keluaran
Tambah (7, 2) = 9
Bagi (100, 8) = 12

Perintah gprbuild mengompilasi bukan hanya berkas utama, tetapi juga seluruh unit yang digunakannya, baik langsung maupun tidak langsung. Pada contoh ini, Kalkulator_Ops ikut dikompilasi karena prosedur utama mengimpornya melalui with Kalkulator_Ops, sehingga tidak ada perintah kompilasi terpisah untuk package tersebut. Atribut Main menerima daftar berkas utama, dan setiap berkas dalam daftar tersebut menghasilkan satu program.

Atribut Object_Dir dan Exec_Dir memindahkan hasil pembangunan keluar dari direktori sumber. Berkas objek, berkas .ali, dan berkas sementara lainnya berada di obj, sedangkan program yang dapat dijalankan ditempatkan di bin. Apabila keduanya tidak dituliskan, hasil pembangunan bercampur dengan berkas sumber pada direktori yang sama.

text Susunan direktori setelah pembangunan
kalkulator.gpr
kalkulator.adb
kalkulator_ops.ads
kalkulator_ops.adb
obj/
   kalkulator.o
   kalkulator_ops.o
   kalkulator.ali
   kalkulator_ops.ali
bin/
   kalkulator

Switch pada package Compiler#

Switch kompilator dituliskan pada berkas proyek melalui package Compiler. Atribut Default_Switches dengan indeks “Ada” berlaku untuk seluruh berkas Ada pada proyek, sedangkan atribut Switches dengan indeks nama berkas berlaku untuk satu berkas tertentu. Pada proyek kalkulator, satu switch bernama -gnata diteruskan ke kompilator untuk seluruh sumbernya.

SwitchEfek
-gnataMengaktifkan pemeriksaan assertion dan kontrak saat run time.
-gnatwaMengaktifkan sebagian besar peringatan opsional.
-gMenghasilkan informasi debug untuk debugger.

Switch lain dituliskan dengan cara yang sama, misalnya tingkat optimasi -O1 dan -O2 atau switch versi bahasa -gnat2022. Perubahan pada package Compiler berlaku bagi kompilasi yang dilakukan pada pembangunan berikutnya, dan perintah gprbuild yang sama meneruskan switch tersebut tanpa pengaturan tambahan. Dengan penempatan switch pada berkas proyek, baris perintah pembangunan tetap pendek, sedangkan riwayat pengaturan tersimpan bersama sumber.

Mengimpor proyek lain#

Proyek berskala besar biasanya terdiri atas beberapa subproyek, sehingga berkas proyek dapat mengimpor proyek lain melalui klausa with. Klausa ini dituliskan sebelum deklarasi proyek dan menyebut nama berkas .gpr yang diimpor. Jalur berkas .gpr yang diimpor ditulis relatif terhadap berkas proyek pengimpor. Pustaka yang sudah terpasang cukup diimpor dengan namanya karena gprbuild mencarinya pada jalur pencarian proyek, yaitu jalur yang diatur melalui variabel lingkungan GPR_PROJECT_PATH.

ada Contoh: proyek yang mengimpor proyek lain
-- tidak-dijalankan
with "satuan.gpr";

project Aplikasi is

   for Source_Dirs use (".");
   for Main use ("utama.adb");

end Aplikasi;

Proyek Aplikasi pada contoh mewarisi akses ke sumber proyek Satuan, sehingga fungsi yang diekspor oleh proyek tersebut dapat dipanggil dari utama.adb. Pola yang sama digunakan untuk mengimpor pustaka pihak ketiga yang dipasang melalui Alire maupun pustaka AUnit yang terpasang sebagai proyek bernama aunit. Proyek pengujian yang menggunakan AUnit menuliskan with "aunit"; karena pustaka itu ditemukan melalui jalur pencarian proyek yang sama.

Kesalahan umum#

Kesalahan pada berkas proyek umumnya tertangkap saat gprbuild membaca berkas proyek. Dua kesalahan pertama diperlihatkan dengan berkas proyek yang sengaja dibuat salah dan diletakkan pada direktori yang sama dengan proyek kalkulator.

Kesalahan pertama adalah menamai berkas proyek secara berbeda dari nama proyeknya. Berkas salahnama.gpr berikut memuat deklarasi proyek Kalkulator yang sama seperti kalkulator.gpr, tetapi nama berkasnya tidak cocok dengan nama proyek yang dideklarasikan di dalamnya.

gpr salahnama.gpr
project Kalkulator is

   for Source_Dirs use (".");

end Kalkulator;
bash
# bangun proyek yang nama berkasnya tidak cocok dengan nama proyeknya
gprbuild -q -P salahnama.gpr
text Keluaran
salahnama.gpr:1:20: warning: file name does not match project name, should be "kalkulator.gpr"

Pesan peringatan menyebut nama berkas yang seharusnya, yaitu kalkulator.gpr. Pembangunan tetap dilanjutkan karena perbedaan ini tidak menghalangi pencarian sumber, tetapi peringatan tersebut menandai berkas proyek yang perlu diganti namanya. Perbaikannya, samakan nama berkas dengan nama proyek yang dideklarasikan.

Kesalahan kedua adalah menunjuk direktori sumber yang tidak ada. Berkas salahdir.gpr berikut menuliskan direktori sumber sumber yang belum dibuat.

gpr salahdir.gpr
project Salahdir is

   for Source_Dirs use ("sumber");

end Salahdir;
bash
# bangun proyek yang direktori sumbernya tidak ada
gprbuild -q -P salahdir.gpr
text Keluaran
salahdir.gpr:3:25: "sumber" is not a valid directory
gprbuild: "salahdir.gpr" processing failed

Pembangunan berhenti karena gprbuild gagal memproses berkas proyek tersebut. Pesan error menyebut baris atribut yang bermasalah beserta nama direktori yang tidak ditemukan. Perbaikannya, buat direktori tersebut atau tuliskan direktori yang memang memuat sumber.

Kesalahan ketiga adalah mengubah switch pada berkas proyek lalu menyangka perubahan tersebut langsung berlaku pada hasil pembangunan. gprbuild mengompilasi ulang hanya berkas sumber yang isinya berubah, sedangkan perubahan switch pada berkas proyek tidak memicu kompilasi ulang, sehingga berkas objek yang dikompilasi dengan switch lama masih digunakan. Perbaikannya, hapus direktori objek sebelum membangun ulang agar seluruh sumber dikompilasi dengan switch yang baru.

Ringkasan#

  • Berkas proyek .gpr memusatkan konfigurasi pembangunan, dan namanya wajib sama dengan nama proyek yang dideklarasikan di dalamnya.
  • Perintah gprbuild -P membangun berkas utama beserta seluruh unit yang digunakannya, sedangkan Object_Dir dan Exec_Dir memisahkan hasil pembangunan dari sumber.
  • Switch kompilator dituliskan pada package Compiler, proyek lain diimpor dengan klausa with, dan pustaka terpasang ditemukan melalui GPR_PROJECT_PATH.

Referensi#