Kita sudah membuktikan sendiri pada Chapter Separate Compilation bahwa build yang benar adalah pekerjaan menjalankan aturan: file .cpp berubah → kompilasi ulang .o-nya; header berubah → kompilasi ulang semua yang memakainya; baru kemudian link. Mengetik semua itu dengan tangan untuk tiga file sudah melelahkan, untuk tiga ratus file mustahil. Karena itu tahun 1976 Stuart Feldman menulis make — tool yang membaca aturan build dari file bernama Makefile, membandingkan stempel waktu antar file, dan hanya menjalankan perintah yang benar-benar perlu. Hampir setengah abad kemudian, make masih dipasang bawaan di praktis semua sistem Unix, dan memahaminya adalah tiket masuk ke semua build system modern, termasuk CMake.
Makefile Pertama Kita #
Kita bangun ulang modul matematika (isi ketiga filenya persis seperti pada Chapter Header dan Source Files: matematika.h, matematika.cpp, utama.cpp), kali ini dengan otak build-nya:
CXX := g++
CXXFLAGS := -std=c++23 -Wall -Wextra
OBJS := utama.o matematika.o
utama: $(OBJS)
$(CXX) $(OBJS) -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f utama $(OBJS)
.PHONY: cleanBedah strukturnya, satu blok per satu aturan:
- Tiga variabel —
CXX,CXXFLAGS, danOBJSmenyimpan nama compiler, flag, dan daftar object file. Mengubah flag kompilasi berarti mengubah satu baris, bukan enam. utama: $(OBJS)— target bernamautamabergantung pada prerequisitesutama.odanmatematika.o. Bila salah satu prerequisite lebih baru dari target, recipe di bawahnya dijalankan.- Recipe target
utama— baris yang diawali TAB:$(CXX) $(OBJS) -o $@. Automatic variable$@berarti “target aturan ini”, jadi recipe-nya tetap benar bila nama target diganti. %.o: %.cpp— pattern rule: untuk setiap.cppyang dibutuhkan, cara membuat pasangan.o-nya sama.$<berarti prerequisite pertama, yaitu file.cppmiliknya.clean+.PHONY— target utilitas untuk menghapus hasil build..PHONYmemberi tahu make bahwacleanbukan nama file sungguhan, sehingga selalu dijalankan meski kebetulan ada file bernamaclean.
Menjalankan make #
Cukup ketik make di folder yang berisi Makefile — make memilih target pertama (utama) dan menuntaskan seluruh rantai dependensinya. Log di bawah ini hasil eksekusi nyata di lingkungan praktikum:
makeOutput yang Dihasilkan:
g++ -std=c++23 -Wall -Wextra -c utama.cpp -o utama.o
g++ -std=c++23 -Wall -Wextra -c matematika.cpp -o matematika.o
g++ utama.o matematika.o -o utamaProgram siap dijalankan, dan outpunya persis seperti versi manual kita:
./utamaOutput yang Dihasilkan:
8 + 5 = 13
8 x 5 = 40
9 kuadrat = 81
Rata-rata = 81.6667Sekarang bagian yang membuat make layak dipakai — jalankan make lagi tanpa mengubah apa pun:
makeOutput yang Dihasilkan:
make: 'utama' is up to date.Make membandingkan stempel waktu: utama lebih baru daripada kedua .o, dan kedua .o lebih baru daripada .cpp-nya, maka tidak ada pekerjaan. Lakukan perubahan pada satu file — touch matematika.cpp mensimulasikannya — dan make langsung tahu batas minimal pekerjaannya:
touch matematika.cpp
makeOutput yang Dihasilkan:
g++ -std=c++23 -Wall -Wextra -c matematika.cpp -o matematika.o
g++ utama.o matematika.o -o utamaHanya matematika.o yang dikompilasi ulang; utama.o dibiarkan apa adanya, lalu link diulang. Inilah incremental build yang pada Chapter lalu kita lakukan manual — sekarang otomatis. Terakhir, target utilitas:
make cleanOutput yang Dihasilkan:
rm -f utama utama.o matematika.oAturan Emas: Recipe Memakai TAB #
Satu jebakan historis wajib Anda tahu sejak hari pertama: baris recipe harus diawali karakter TAB, bukan spasi. Editor yang menyemprot spasi di tempat TAB — sengaja atau tidak — merusak Makefile dengan pesan yang seadanya:
Makefile-rusak:7: *** missing separator. Stop.Pesan missing separator ini hampir selalu berarti TAB yang hilang di baris yang disebut, dan ia jadi bahan lelucon tetap di komunitas make. Pastikan editor Anda menampilkan whitespace, dan bila menyalin Makefile dari internet, curigai baris recipe yang kehilangan TAB-nya di jalan.
Posisi make dalam Kehidupan C++ #
make tidak tahu apa-apa tentang C++ — ia tool umum untuk “jika file A lebih baru dari file B, jalankan perintah ini”. Sifat umum itu kekuatannya (dipakai dari C sampai dokumentasi LaTeX), tetapi juga batasnya: kita sendiri yang harus menulis daftar file, pattern rule, dan dependensi header. Build system modern seperti CMake tidak menggantikan make — melainkan menggantikan pekerjaan menulis Makefile-nya: kita mendeskripsikan proyek dalam bahasa yang lebih tinggi, dan CMake yang membuat Makefile atau build file lain untuk kita. Bagaimana persisnya ia bekerja itulah topik Chapter berikutnya.
Referensi: Manual GNU Make .