Mengenal Makefile

3 min read

Jika melihat beberapa repositori di Github, misalnya Babel, kita akan menemui sebuah file dengan nama Makefile. Makefile adalah file konfigurasi yang dibaca oleh GNU Make untuk menentukan langkah-langkah menghasilkan suatu output.

GNU Make pada dasarnya adalah sebuah perkakas untuk menghasilkan output berupa file atau direktori dari daftar perintah yang kita definisikan. Penggunaannya dengan menjalankan perintah make [rule]. Contohnya seperti yang sering ditemui jika melakukan compiling kode sumber suatu program secara manual, biasanya akan diminta menjalankan perintah berikut:

./configure
make
sudo make install

Format Penulisan dalam Makefile

Makefile hanya berisi kumpulan kode yang disebut rule. Setiap rule harus memenuhi format:

target: dependencies...
	commands
	....
  • target adalah output berupa file atau direktori yang diinginkan.
  • dependencies adalah daftar rule lain yang harus dijalankan terlebih dahulu (opsional).
  • commands adalah daftar perintah untuk menghasilkan target.

Coba buat sebuah file Makefile dengan isi sebagai berikut:

build/content.md: build
  echo "Hello World" > build/content.md
  echo "The world is awesome" >> build/content.md

build:
  mkdir build

Lalu jalankan

make

Maksud dari Makefile di atas adalah:

  • Hasilkan target build/content.md dengan cara menjalankan command @echo "Hello World" > build/content.md dan @echo "The world is awesome" >> build/content.md, tapi tunggu hingga target build tersedia.
  • Hasilkan target build dengan cara menjalankan command mkdir build.

Hasil dari proses di atas adalah sebuah direktori build berisi berkas content.md. Berkas build/content.md inilah yang kita sebut dengan target atau bisa kita sebut juga sebagai output.

Contoh Makefile sederhana untuk menghasilkan berkas build/content.md
Contoh Makefile sederhana untuk menghasilkan berkas build/content.md
GNU Make pada dasarnya adalah sebuah perkakas untuk menghasilkan output berupa file atau direktori dari daftar perintah yang kita definisikan.

GNU Make Tidak Menimpa Berkas

Dengan Makefile yang barusan dibuat, coba jalankan lagi perintah make, maka tidak akan ada proses yang dijalankan.

Proses build tidak dieksekusi ketika target sudah tersedia
Proses build tidak dieksekusi ketika target sudah tersedia

Hal ini karena GNU Make akan memeriksa ketersediaan target sebelum mengeksekusi rule pada Makefile. Jika target yang diharapkan sudah tersedia maka tidak perlu diproses lagi. Jadi, kalau ingin proses build selalu terjadi setiap menjalankan perintah make, mari kita ubah isi Makefile seperti berikut:

build/content.md: clean build
  echo "Hello World" > build/content.md
  echo "The world is awesome" >> build/content.md

clean:
  rm -rf build

build:
  mkdir build

Lalu jalankan kembali perintah make berulang kali, maka proses build akan selalu dilakukan walaupun target sudah tersedia.

Menambahkan rule clean agar target selalu dibersihkan sebelum melakukan proses build
Menambahkan rule clean agar target selalu dibersihkan sebelum melakukan proses build

Ini bisa terjadi karena hal berikut:

  • Kita menambahkan rule clean sebagai dependency dari build/content.md, sehingga rule clean akan selalu dieksekusi terlebih dahulu (dependencies diperiksa sesuai urutan dari kiri ke kanan).
  • Rule clean hanya menjalankan command rm -rf build yang akan menghapus direktori build beserta isinya jika sudah ada.
  • Karena direktori build selalu dihapus terlebih dahulu, maka rule build akan selalu dieksekusi karena targetnya belum tersedia.
  • Karena rule clean tidak berisi perintah yang menyebabkan terbentuknya file/direktori bernama clean, maka rule ini akan selalu dieksekusi.

Coba buat direktori atau file bernama clean

touch clean

Lalu jalankan perintah make beberapa kali, maka di percobaan ke-2 kita tidak akan melakukan proses build lagi.

Keberadaan berkas bernama 'clean' menyebabkan rule clean tidak berjalan sesuai ekspektasi
Keberadaan berkas bernama 'clean' menyebabkan rule clean tidak berjalan sesuai ekspektasi

Hal ini terjadi karena:

  • Sudah terdapat file bernama clean sehingga rule clean sudah terpenuhi dan tidak dieksekusi lagi.
  • Karena rule clean tidak dieksekusi, maka direktori build tidak dihapus, yang menyebabkan rule build juga tidak dieksekusi.

PHONY

Untuk menandai bahwa rule tertentu tidak perlu menghasilkan file, kita bisa menambahkan PHONY target di awal Makefile:

.PHONY: [rule1] [rule2] ...

Rule yang didaftarkan ke dalam PHONY target ini memiliki karakteristik:

  • rule tersebut tidak akan peduli terhadap keberadaan target
  • karena tidak peduli dengan target, maka rule akan selalu dieksekusi walaupun terdapat berkas atau direktori sesuai dengan nama targetnya

Coba ubah Makefile sebelumnya seperti berikut:

.PHONY: help clean

build/content.md: clean build
  echo "Hello World" > build/content.md
  echo "The world is awesome" >> build/content.md

clean:
  rm -rf build

build:
  mkdir build

help:
  @echo "---- Simple Make ----"
  @echo "Usage: make <command>"
  @echo ""
  @echo "Available commands:"
  @echo "build: Create content"
  @echo "clean: Clean content"
  @echo "help : This guide"

Kemudian buat kembali berkas bernama help dan clean dengan perintah touch help clean dan jalankan perintah make, make clean dan make help beberapa kali. Kali ini perintah-perintah tersebut akan selalu dijalankan walaupun target help dan clean sudah tersedia.

Image
PHONY menyebabkan rule mengabaikan keberadaan target, sehingga rule tersebut selalu dieksekusi
PHONY menyebabkan rule mengabaikan keberadaan target, sehingga rule tersebut selalu dieksekusi

Ekstra

Apa perbedaan menggunakan perintah echo dan @echo?

Perbedaan cara menjalankan perintah pada Makefile
Perbedaan cara menjalankan perintah pada Makefile

Secara default setiap baris perintah yang kita cantumkan ke dalam rule di Makefile akan ditampilkan ketika perintah tersebut dieksekusi. Dengan menambahkan @, kita bisa mengeksekusi perintah tanpa menampilkannya (https://www.gnu.org/software/make/manual/html_node/Echoing.html#Echoing).

Referensi