Apa itu Makefile
Makefile adalah alat otomatisasi build yang telah digunakan selama beberapa dekade untuk mengompilasi dan menghubungkan kode sumber, menghasilkan eksekutables, dan mengelola dependensi dalam proyek pengembangan perangkat lunak. Ini menyediakan cara yang nyaman untuk menentukan dan mengeksekusi tugas, juga dikenal sebagai "rules," yang menggambarkan cara membangun target tertentu dan dependensinya. Makefile mengandalkan utilitas make
, sebuah alat baris perintah yang membaca Makefile dan secara otomatis mengeksekusi tugas yang sesuai.
Memulai dengan Makefile
Menginstal Make
Sebelum Anda dapat mulai menggunakan Makefile, Anda perlu menginstal utilitas make
pada sistem Anda. Kebanyakan sistem berbasis Unix, seperti Linux dan macOS, sudah dilengkapi dengan make
pre-installed. Namun, jika belum terinstal, Anda dapat menggunakan perintah berikut:
Untuk Linux (Debian/Ubuntu):
$ sudo apt-get update
$ sudo apt-get install build-essential
Untuk macOS (menggunakan Homebrew):
$ brew install make
Untuk Windows, Anda dapat menginstal make
menggunakan metode berikut:
- Menggunakan WSL (Windows Subsystem for Linux): Instal distribusi Linux dari Microsoft Store dan ikuti instruksi instalasi Linux.
- Menggunakan MSYS2 atau Cygwin: Unduh dan instal salah satu lingkungan mirip Unix untuk Windows ini, lalu ikuti instruksi instalasi untuk Linux.
Membuat Makefile
Untuk membuat Makefile, cukup buat file baru dengan nama Makefile
(tanpa ekstensi file) di direktori utama proyek Anda. Anda dapat menggunakan editor teks apa saja untuk menulis dan mengedit file tersebut.
Berikut contoh sederhana Makefile yang mengompilasi program C:
CC = gcc
CFLAGS = -Wall -Wextra
hello: hello.c
$(CC) $(CFLAGS) -o hello hello.c
clean:
rm -f hello
Pada contoh ini, kita mendefinisikan dua variabel (CC
dan CFLAGS
) dan menggunakannya dalam rule untuk membangun target hello
. Rule clean
adalah target palsu yang digunakan untuk menghapus file eksekutabel hello
yang dihasilkan.
Sintaks dan Rules Dasar Makefile
Makefile terdiri dari rules, penugasan variabel, dan komentar. Berikut ringkasan singkat tentang sintaks dasar:
Rules
Rule terdiri dari target
, dependencies
, dan recipe
. Formatnya sebagai berikut:
target: dependencies
recipe
recipe
adalah serangkaian perintah shell yang ditabulasi dengan karakter tab.
Variabel
Variabel dalam Makefile ditugaskan dengan operator =
:
VAR_NAME = value
Anda dapat menggunakan variabel dalam rule dengan menyertakan namanya dalam tanda kurung dan memasukkan tanda dollar sebelumnya, seperti ini: $(VAR_NAME)
.
Komentar
Komentar dalam Makefile dimulai dengan karakter #
dan dilanjutkan hingga akhir baris:
# This is a comment
Phony
Target palsu adalah target khusus yang tidak mewakili file yang sebenarnya tetapi berfungsi sebagai cara untuk mengelompokkan tugas terkait. Untuk mendefinisikan target palsu, tambahkan direktif .PHONY
sebelum rule:
.PHONY: clean
clean:
rm -f hello
Menjalankan Makefile
Setelah Anda membuat Makefile untuk proyek Anda, Anda dapat mengeksekusinya menggunakan utilitas make
. Secara default, make
mencari file bernama Makefile
di direktori saat ini dan mengeksekusi aturan pertama yang ditemukan di file tersebut. Anda juga dapat menentukan target yang ingin dibangun dengan menyediakan namanya sebagai argumen.
Jalankan make
untuk membangun target default (biasanya target pertama yang didefinisikan di Makefile):
$ make
Untuk membangun target tertentu, berikan namanya sebagai argumen ke perintah make:
$ make clean
Dalam contoh kita, perintah ini akan mengeksekusi aturan clean
, menghapus file hello
yang dapat dieksekusi.
Anda dapat menentukan beberapa target dengan menyediakan namanya yang dipisahkan oleh spasi:
$ make target1 target2 target3
Jika Anda ingin mengeksekusi Makefile dengan nama yang berbeda atau berada di direktori yang berbeda, Anda dapat menggunakan opsi -f
atau --file
:
$ make -f path/to/MyMakefile
Teknik Lanjutan Makefile
Mendefinisikan dan Menggunakan Variabel
Variabel dalam Makefile memungkinkan Anda menyimpan dan menggunakan kembali nilai, membuat Makefile Anda lebih mudah dipelihara dan lebih mudah dibaca. Variabel dapat ditugaskan dengan salah satu operator berikut:
=
: Penugasan variabel rekursif:=
: Penugasan variabel sederhana (non-rekursif)?=
: Penugasan variabel bersyarat (hanya jika variabel belum ditetapkan)+=
: Menambahkan ke variabel
Berikut adalah contoh yang menggambarkan penggunaan variabel:
CC := gcc
CFLAGS := -Wall -Wextra
SOURCES := main.c util.c
OBJECTS := $(SOURCES:.c=.o)
main: $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
Pernyataan Kondisional dan Perulangan
Makefile mendukung pernyataan kondisional dan perulangan, yang dapat berguna untuk menyesuaikan perilaku Makefile Anda berdasarkan lingkungan atau platform target.
Pernyataan kondisional ditulis dengan menggunakan direktif ifeq
, ifneq
, ifdef
, dan ifndef
:
ifeq ($(OS),Windows_NT)
EXE_EXT := .exe
else
EXE_EXT :=
endif
hello: hello.c
$(CC) $(CFLAGS) -o hello$(EXE_EXT) hello.c
Perulangan dapat dibuat menggunakan direktif foreach
dan eval
, serta fungsi call
dan value
:
TARGETS := target1 target2 target3
RULES := $(foreach target,$(TARGETS),$(eval $(call create_rule,$(target))))
define create_rule
$(1): $(1).c
$(CC) $(CFLAGS) -o $(1) $(1).c
endef
$(RULES)
Aturan Pola dan Wildcard
Aturan pola memungkinkan Anda untuk mendefinisikan aturan generik untuk beberapa target berdasarkan ekstensi file atau pola. Wildcard dapat digunakan untuk mencocokkan sekelompok file, menyederhanakan Makefile Anda.
Berikut adalah contoh penggunaan aturan pola dan wildcard:
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
all: main
main: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
Mengelola Dependensi
Makefile dapat secara otomatis mengelola dependensi antara target, memastikan bahwa hanya tugas yang diperlukan yang dieksekusi ketika file berubah.
Untuk mengelola dependensi, Anda dapat menggunakan direktif -include
untuk menyertakan file dependensi yang dihasilkan oleh kompiler:
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
DEPS := $(SRCS:.c=.d)
all: main
main: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -MMD -c -o $@ $<
-include $(DEPS)
Dalam contoh ini, flag -MMD
memberitahu kompiler untuk menghasilkan file dependensi untuk setiap file sumber, yang kemudian disertakan dalam Makefile menggunakan direktif -include
.