Pengantar Singkat 'Makefiles' dalam Pengembangan Perangkat Lunak Sumber Terbuka dengan GNU Make


GNU Make adalah utilitas pengembangan yang menentukan bagian dari basis kode tertentu yang akan dikompilasi ulang dan dapat mengeluarkan perintah untuk melakukan operasi tersebut pada basis kode. Utilitas make khusus ini dapat digunakan dengan bahasa pemrograman apa pun asalkan kompilasinya dapat dilakukan dari shell dengan mengeluarkan perintah.

Untuk menggunakan GNU Make, kita perlu memiliki seperangkat aturan yang mendefinisikan hubungan antara berbagai file dalam program kita dan perintah untuk memperbarui setiap file. Ini ditulis ke dalam file khusus yang disebut ‘makefile‘. Perintah 'make' menggunakan basis data 'makefile' dan waktu modifikasi terakhir file untuk memutuskan yang mana semua file akan dikompilasi ulang lagi.

Isi Makefile

Secara umum 'makefiles' berisi 5 macam hal yaitu: aturan implisit, aturan eksplisit, definisi variabel , perintah, dan komentar.

  1. Sebuah Aturan eksplisit menetapkan cara membuat/membuat ulang satu atau beberapa file (disebut target, akan dijelaskan nanti) dan kapan melakukan hal yang sama.
  2. Sebuah Aturan implisit menetapkan cara membuat/membuat ulang satu atau beberapa file berdasarkan namanya. Ini menjelaskan bagaimana nama file target terkait dengan satu file dengan nama yang mirip dengan target.
  3. Definisi variabel adalah baris yang menetapkan nilai string untuk variabel yang akan diganti nanti.
  4. Direktif adalah instruksi make untuk melakukan sesuatu yang istimewa saat membaca makefile.
  5. Simbol '#' digunakan untuk mewakili awal komentar di dalam makefiles . Baris yang dimulai dengan ‘#’ diabaikan begitu saja.

Struktur Makefile

Informasi yang memberitahu make cara mengkompilasi ulang sistem berasal dari membaca basis data yang disebut makefile. makefile sederhana akan terdiri dari aturan sintaksis berikut:

target ... : prerequisites ... 
	recipe 
... 
...

target didefinisikan sebagai file keluaran yang dihasilkan oleh program. Bisa juga merupakan target palsu, yang akan dijelaskan di bawah. Contoh file target mencakup file yang dapat dieksekusi, file objek atau target palsu seperti bersih, memasang, mencopot, dll.

prasyarat adalah file yang digunakan sebagai masukan untuk membuat file target.

resep adalah tindakan yang dilakukan make untuk membuat file target berdasarkan prasyarat. Penting untuk menempatkan karakter tab sebelum setiap resep di dalam makefiles kecuali kita menetapkan variabel '.RECIPEPREFIX' untuk mendefinisikan beberapa karakter lain sebagai awalan untuk resep.

Contoh Makefile

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f main.o end.o inter.o start.o

Dalam contoh di atas kami menggunakan 4 file sumber C dan dua file header untuk membuat final yang dapat dieksekusi. Di sini setiap file ‘.o’ merupakan target dan prasyarat di dalam makefile. Sekarang lihat nama target terakhir clean. Ini hanyalah sebuah tindakan, bukan file target.

Karena biasanya kita tidak memerlukan ini selama kompilasi, ini tidak ditulis sebagai prasyarat dalam aturan lainnya. Target yang tidak mengacu pada file namun hanya berupa tindakan disebut target palsu. Mereka tidak akan memiliki prasyarat seperti file target lainnya.

Bagaimana GNU Make memproses Makefile

Secara default, make dimulai dengan target pertama di 'makefile' dan disebut sebagai ' sasaran bawaan'. Mengingat contoh kita, kita mempunyai final sebagai target pertama kita. Karena prasyaratnya mencakup file objek lain, maka file tersebut harus diperbarui sebelum membuat final. Masing-masing prasyarat ini diproses menurut aturannya masing-masing.

Kompilasi ulang terjadi jika ada modifikasi yang dilakukan pada file sumber atau file header atau jika file objek tidak ada sama sekali. Setelah mengkompilasi ulang file objek yang diperlukan, make memutuskan apakah akan menautkan ulang final atau tidak. Hal ini harus dilakukan jika file final tidak ada, atau jika ada file objek yang lebih baru dari file tersebut.

Jadi jika kita mengubah file inter.c, maka saat menjalankan make maka file sumber akan dikompilasi ulang untuk diperbarui file objek inter.o dan kemudian link final.

Menggunakan variabel di dalam Makefiles

Dalam contoh kita, kita harus mencantumkan semua file objek dua kali dalam aturan untuk final seperti yang ditunjukkan di bawah ini.

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o

Untuk menghindari duplikasi seperti itu, kita bisa memasukkan variabel untuk menyimpan daftar file objek yang digunakan di dalam makefile. Dengan menggunakan variabel OBJ kita dapat menulis ulang sampel makefile menjadi serupa seperti yang ditunjukkan di bawah ini.

OBJ = main.o end.o inter.o start.o
final: $(OBJ)
	gcc -o final $(OBJ)
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f $(OBJ)

Aturan untuk membersihkan direktori sumber

Seperti yang kita lihat di contoh makefile, kita bisa mendefinisikan aturan untuk membersihkan direktori sumber dengan menghapus file objek yang tidak diinginkan setelah kompilasi. Misalkan kita memiliki file target bernama clean. Bagaimana cara membuat membedakan kedua situasi di atas? Inilah konsep target palsu.

Target palsu adalah target yang sebenarnya bukan nama file, melainkan hanya nama resep yang akan dieksekusi setiap kali permintaan eksplisit dibuat dari makefile. Salah satu alasan utama menggunakan target palsu adalah untuk menghindari konflik dengan file dengan nama yang sama. Alasan lainnya adalah untuk meningkatkan kinerja.

Untuk menjelaskan hal ini, saya akan mengungkapkan satu perubahan yang tidak terduga. Resep untuk clean tidak akan dijalankan secara default saat menjalankan make. Sebaliknya, hal yang sama perlu dilakukan dengan mengeluarkan perintah make clean.

.PHONY: clean
clean:
	rm -f $(OBJ)

Sekarang cobalah membuat makefiles untuk basis kode Anda sendiri. Jangan ragu untuk berkomentar di sini dengan keraguan Anda.