make adalah program yang membaca Makefile dan menjalankan perintah-perintah di dalamnya. Walaupun konsepnya sederhana — make membaca target, prerequisite, dan recipe — program ini punya banyak flag command-line yang mengubah perilakunya. Pada chapter ini kita akan mempraktikkan workflow sehari-hari (make, make clean, make install), memahami flag umum (-n, -B, -j), dan mengamati bagaimana make memilih target yang dijalankan secara default. Menguasai flag-flag ini membuat kita bisa membaca CI script dan Makefile proyek open-source tanpa kebingungan.
Verifikasi Instalasi make #
make --versionOutput yang Dihasilkan:
GNU Make 4.4.1
Built for x86_64-pc-linux-gnuPesan di atas menunjukkan versi GNU Make (4.4.1) dan arsitektur target (x86_64-pc-linux-gnu). GNU Make adalah implementasi standar make di sistem GNU/Linux; alternatif lain adalah BSD Make yang ada di FreeBSD/macOS.
Workflow Standar: make, make clean, make install #
Kita pakai Makefile dari chapter sebelumnya. Struktur proyek:
greet.h, greet.c -- library greet
main.c -- program utama
Makefile -- script buildmake — Build Target Default #
Tanpa argumen, make memilih target pertama di Makefile sebagai target default. Makefile kita mendefinisikan $(TARGET) (app) sebagai target pertama, sehingga make membangun executable app:
makeOutput yang Dihasilkan:
gcc -std=c11 -Wall -Wextra -c main.c -o main.o
gcc -std=c11 -Wall -Wextra -c greet.c -o greet.o
gcc -std=c11 -Wall -Wextra main.o greet.o -o appmake menjalankan recipe dalam urutan dependensi: pertama mengompilasi main.o (karena app bergantung padanya), lalu greet.o, lalu link keduanya menjadi app. Bila kita menjalankan make lagi tanpa mengubah apa pun, make melaporkan target sudah up-to-date:
makeOutput yang Dihasilkan:
make: 'app' is up to date.make membandingkan timestamp file target (app) dengan timestamp prerequisite (main.o, greet.o). Karena target lebih baru, tidak ada yang perlu dilakukan.
make clean — Hapus Artifact Build #
Target clean menghapus object file dan executable hasil build:
make cleanOutput yang Dihasilkan:
rm -f main.o greet.o appSetelah clean, direktori kerja kembali bersih. Target clean biasanya dideklarasikan sebagai .PHONY (bukan file target) — lihat chapter Makefile.
make install — Install ke Lokasi Sistem #
Makefile profesional biasanya punya target install yang menyalin executable ke lokasi sistem. Pola idiomatik memakai DESTDIR untuk pengujian tanpa benar-benar memodifikasi sistem:
install: $(TARGET)
install -m 0755 $(TARGET) $(DESTDIR)/usr/local/bin/$(TARGET)
mkdir -p fake_root/usr/local/bin
DESTDIR=$(pwd)/fake_root make install
ls -l fake_root/usr/local/bin/Output yang Dihasilkan:
install -m 0755 app /tmp/test_make/fake_root/usr/local/bin/app
total 16
-rwxr-x-x 1 z z 16016 Oct 13 07:38 appVariabel DESTDIR dipakai sistem build (Autoconf, CMake, Makefile manual) untuk mendukung staged install — proses install ke direktori sementara yang nantinya di-tar atau di-package oleh maintainer distro. Tanpa DESTDIR, kita perlu sudo untuk menulis ke /usr/local/bin. Dengan DESTDIR, kita bisa menguji install tanpa hak root.
Mari kita telaah perintah install -m 0755 $(TARGET) $(DESTDIR)/usr/local/bin/$(TARGET):
install: program dari GNU Coreutils yang menyalin file sambil mengatur permission dan ownership. Berbeda daricp,installmempertahankan permission mode yang kita tentukan, bukan permission file sumber.-m 0755: atur permission mode0755(owner read/write/execute, group/others read/execute). Inilah mode standar executable.$(TARGET): file sumber (appdi direktori kerja).$(DESTDIR)/usr/local/bin/$(TARGET): tujuan akhir, dengan prefix$(DESTDIR). BilaDESTDIRkosong (default), install ke/usr/local/bin/app(membutuhkan sudo). BilaDESTDIR=/tmp/test_make/fake_root, install ke/tmp/test_make/fake_root/usr/local/bin/app(tidak butuh sudo).
Flag make Penting #
-n (dry run): Tampilkan Perintah Tanpa Menjalankan #
make -n cleanOutput yang Dihasilkan:
rm -f main.o greet.o appFlag -n (alias --dry-run) menampilkan perintah yang akan dijalankan, tetapi tidak benar-benar menjalankannya. Berguna untuk memeriksa apa yang akan make lakukan sebelum commit ke build.
-B (always make): Paksa Rebuild Semua #
make -BOutput yang Dihasilkan:
gcc -std=c11 -Wall -Wextra -c main.c -o main.o
gcc -std=c11 -Wall -Wextra -c greet.c -o greet.o
gcc -std=c11 -Wall -Wextra main.o greet.o -o appFlag -B mengabaikan timestamp dan menganggap semua target out-of-date. Berguna bila kita menduga cache build rusak atau bila kita mengubah flag compiler (misalnya menambah -O2) dan ingin memastikan semua object file dikompilasi ulang.
-j<N>: Build Paralel #
make -j2Output yang Dihasilkan:
gcc -std=c11 -Wall -Wextra -c main.c -o main.o
gcc -std=c11 -Wall -Wextra -c greet.c -o greet.o
gcc -std=c11 -Wall -Wextra main.o greet.o -o appFlag -j2 menyuruh make menjalankan hingga 2 recipe secara paralel. Pada proyek besar dengan banyak file, -j$(nproc) (semua core CPU) bisa mempercepat build 4-8 kali. Makefile kita terlalu kecil untuk menunjukkan efek paralel yang signifikan, tetapi urutan baris tetap menarik — main.o dan greet.o bisa dibangun paralel karena tidak saling bergantung, sedangkan app harus menunggu keduanya selesai.
-C <dir>: Build di Direktori Lain #
make -C /tmp/test_make cleanOutput yang Dihasilkan:
make: Entering directory '/tmp/test_make'
rm -f main.o greet.o app
make: Leaving directory '/tmp/test_make'Flag -C <dir> mengganti direktori kerja make ke <dir> sebelum membaca Makefile. Berguna untuk membangun sub-proyek atau dependency eksternal dari Makefile induk: cd /path/to/dep && make ekuivalen dengan make -C /path/to/dep.
Menentukan Target dari Command Line #
make menerima target sebagai argumen posisi:
make clean
make run
make main.o # build hanya satu target
make -B main.o # rebuild paksa satu targetBila beberapa target disebut, make memprosesnya berurutan:
make clean runPerintah di atas menjalankan clean terlebih dahulu, lalu run. Bila clean gagal (exit non-zero), make berhenti dan tidak menjalankan run.
Override Variabel dari Command Line #
Variabel Makefile bisa di-override dari command line:
make CC=clang CFLAGS="-std=c11 -O2 -Wall"Karena override command line memiliki prioritas lebih tinggi dari deklarasi di Makefile, perintah di atas mengompilasi dengan Clang alih-alih GCC. Pola ini sering dipakai di CI untuk menguji build dengan beberapa compiler.
make V=1Output yang Dihasilkan:
rm -f main.o greet.o app
gcc -std=c11 -Wall -Wextra -c main.c -o main.o
gcc -std=c11 -Wall -Wextra -c greet.c -o greet.o
gcc -std=c11 -Wall -Wextra main.o greet.o -o appKonvensi proyek open-source: V=1 (verbose) menampilkan command line lengkap yang dijalankan make. Makefile kita sudah menampilkan command secara default (karena recipe eksplisit), tetapi Makefile yang memakai @ untuk menyembunyikan command akan menampilkan output tambahan saat V=1.