Cara-cara standar tertentu untuk membuat ulang file target sangat sering digunakan. Misalnya, salah satu cara umum untuk membuat file objek adalah dari file sumber C menggunakan kompiler C, cc.
Aturan implisit memberi tahu make cara memakai teknik-teknik umum tersebut, sehingga Anda tidak perlu menuliskannya secara rinci setiap kali ingin memakainya. Misalnya, tersedia aturan implisit untuk kompilasi C. Nama file menentukan aturan implisit mana yang dijalankan. Misalnya, kompilasi C biasanya mengambil file .c dan menghasilkan file .o. Karena itu, make menerapkan aturan implisit untuk kompilasi C ketika ia menemukan kombinasi akhiran nama file seperti ini.
Rantai aturan implisit dapat diterapkan secara berurutan; misalnya, make akan membuat ulang file .o dari file .y melalui file .c.
Aturan implisit bawaan menggunakan sejumlah variabel dalam resep (recipe)-nya, sehingga dengan mengubah nilai variabel tersebut, Anda dapat mengubah cara kerja aturan implisit tanpa mendefinisikan ulang aturan itu sendiri. Misalnya, variabel CFLAGS mengendalikan flag yang diberikan ke kompiler C oleh aturan implisit untuk kompilasi C.
Anda dapat mendefinisikan aturan implisit sendiri dengan menulis aturan pola.
Aturan sufiks adalah cara yang lebih terbatas untuk mendefinisikan aturan implisit. Aturan pola lebih umum dan lebih jelas, tetapi aturan sufiks tetap dipertahankan demi kompatibilitas.
Agar make dapat menemukan metode umum untuk memperbarui file target, yang perlu Anda lakukan hanyalah tidak menuliskan resep sendiri. Tulislah aturan tanpa resep, atau jangan tulis aturan sama sekali untuk target tersebut. Maka make akan menentukan aturan implisit mana yang dipakai berdasarkan jenis file sumber apa yang ada atau dapat dibuat.
Misalnya, andaikan makefile terlihat seperti berikut:
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Karena Anda menyebutkan foo.o tetapi tidak memberikan aturan untuknya, make akan secara otomatis mencari aturan implisit yang memberi tahu cara memperbaruinya. Ini terjadi terlepas dari apakah file foo.o saat ini sudah ada atau belum.
Jika aturan implisit ditemukan, aturan tersebut dapat menyediakan baik resep maupun satu atau lebih prasyarat (prerequisite) (file sumber). Anda mungkin ingin menulis aturan tanpa resep untuk foo.o jika perlu menentukan prasyarat tambahan — misalnya file header — yang tidak dapat disediakan oleh aturan implisit.
Setiap aturan implisit memiliki pola target dan pola prasyarat. Bisa jadi ada banyak aturan implisit dengan pola target yang sama. Misalnya, ada banyak aturan yang membuat file .o: satu dari file .c dengan kompiler C, yang lain dari file .p dengan kompiler Pascal, dan seterusnya. Aturan yang benar-benar diterapkan adalah aturan yang prasyaratnya ada atau dapat dibuat. Jadi, jika Anda memiliki file foo.c, make akan menjalankan kompiler C; jika tidak dan Anda memiliki file foo.p, make akan menjalankan kompiler Pascal; dan seterusnya.
Tentu saja, ketika Anda menulis makefile, Anda sudah tahu aturan implisit mana yang Anda inginkan agar dipakai oleh make, dan Anda tahu make akan memilih aturan itu karena Anda tahu file prasyarat mana yang seharusnya ada. Lihat Katalog aturan bawaan untuk katalog semua aturan implisit yang telah didefinisikan sebelumnya.
Di atas, kita mengatakan bahwa aturan implisit diterapkan jika prasyarat yang diperlukan “ada atau dapat dibuat”. File “dapat dibuat” jika file itu disebutkan secara eksplisit dalam makefile sebagai target atau prasyarat, atau jika aturan implisit untuk membuatnya dapat ditemukan secara rekursif. Ketika sebuah prasyarat implisit merupakan hasil dari aturan implisit lain, kita katakan sedang terjadi perantaian (chaining). Lihat Rantai aturan implisit.
Secara umum, make mencari aturan implisit untuk setiap target, dan untuk setiap aturan titik dua ganda, yang tidak memiliki resep. File yang hanya disebutkan sebagai prasyarat dianggap sebagai target yang aturannya tidak menentukan apa pun, sehingga pencarian aturan implisit juga dilakukan untuknya. Lihat Algoritma pencarian aturan implisit untuk rincian tentang bagaimana pencarian ini dilakukan.
Perhatikan bahwa prasyarat eksplisit tidak memengaruhi pencarian aturan implisit. Misalnya, perhatikan aturan eksplisit berikut:
foo.o: foo.p
Prasyarat pada foo.p tidak serta-merta berarti bahwa make akan membuat ulang foo.o menurut aturan implisit yang membuat file objek, yaitu file .o, dari file sumber Pascal, yaitu file .p. Misalnya, jika foo.c juga ada, aturan implisit yang membuat file objek dari file sumber C akan dipakai sebagai gantinya, karena aturan itu muncul lebih dulu daripada aturan Pascal dalam daftar aturan implisit yang telah didefinisikan sebelumnya (lihat Katalog aturan bawaan).
Jika Anda tidak ingin aturan implisit dipakai untuk target yang tidak memiliki resep, Anda dapat memberikan resep kosong kepada target tersebut dengan menuliskan titik koma (lihat Menggunakan resep kosong).
Berikut adalah katalog aturan implisit yang telah didefinisikan sebelumnya, yang selalu tersedia kecuali makefile secara eksplisit menimpa atau membatalkannya. Lihat Membatalkan aturan implisit untuk informasi tentang cara membatalkan atau menimpa aturan implisit. Opsi -r atau --no-builtin-rules membatalkan semua aturan yang telah didefinisikan sebelumnya.
Manual ini hanya mendokumentasikan aturan default yang tersedia pada sistem operasi berbasis POSIX. Sistem operasi lain, seperti VMS, Windows, OS/2, dan sebagainya, mungkin memiliki kumpulan aturan default yang berbeda. Untuk melihat daftar lengkap aturan dan variabel default yang tersedia pada versi GNU make Anda, jalankan make -p di direktori tanpa makefile.
Tidak semua aturan ini akan selalu terdefinisi, bahkan ketika opsi -r tidak diberikan. Banyak aturan implisit yang telah didefinisikan sebelumnya diimplementasikan di dalam make sebagai aturan sufiks. Karena itu, aturan mana yang terdefinisi bergantung pada daftar sufiks (daftar prasyarat dari target khusus .SUFFIXES). Daftar sufiks default adalah:
.out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
Semua aturan implisit yang dijelaskan di bawah ini, yang prasyaratnya memiliki salah satu sufiks tersebut, sebenarnya adalah aturan sufiks. Jika Anda mengubah daftar sufiks, satu-satunya aturan sufiks bawaan yang tetap berlaku adalah yang dinamai oleh satu atau dua sufiks yang ada dalam daftar yang Anda tentukan; aturan yang sufiksnya tidak ada dalam daftar akan dinonaktifkan. Untuk rincian lengkap tentang aturan sufiks, lihat Aturan sufiks gaya lama.
n.o dibuat secara otomatis dari n.c dengan resep berbentuk $(CC) $(CPPFLAGS) $(CFLAGS) -c.
n.o dibuat secara otomatis dari n.cc, n.cpp, atau n.C dengan resep berbentuk $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c. Kami menganjurkan Anda menggunakan sufiks .cc atau .cpp untuk file sumber C++, bukan .C, agar lebih mendukung sistem file yang tidak membedakan huruf besar-kecil.
n.o dibuat secara otomatis dari n.p dengan resep $(PC) $(PFLAGS) -c.
n.o dibuat secara otomatis dari n.r, n.F, atau n.f dengan menjalankan kompiler Fortran. Resep persisnya adalah sebagai berikut:
$(FC) $(FFLAGS) -c.
$(FC) $(FFLAGS) $(CPPFLAGS) -c.
$(FC) $(FFLAGS) $(RFLAGS) -c.
n.f dibuat secara otomatis dari n.r atau n.F. Aturan ini hanya menjalankan preprosesor untuk mengubah program Ratfor atau program Fortran yang memerlukan praproses menjadi program Fortran murni. Resep persisnya adalah sebagai berikut:
$(FC) $(CPPFLAGS) $(FFLAGS) -F.
$(FC) $(FFLAGS) $(RFLAGS) -F.
n.sym dibuat dari n.def dengan resep berbentuk $(M2C) $(M2FLAGS) $(DEFFLAGS). n.o dibuat dari n.mod; bentuknya adalah $(M2C) $(M2FLAGS) $(MODFLAGS).
n.o dibuat secara otomatis dari n.s dengan menjalankan assembler as. Resep persisnya adalah $(AS) $(ASFLAGS).
n.s dibuat secara otomatis dari n.S dengan menjalankan preprosesor C, cpp. Resep persisnya adalah $(CPP) $(CPPFLAGS).
n dibuat secara otomatis dari n.o dengan menjalankan kompiler C untuk menautkan program. Resep persisnya adalah $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
Aturan ini bekerja dengan benar untuk program sederhana yang hanya memiliki satu file sumber. Aturan ini juga bekerja dengan benar jika ada beberapa file objek (kemungkinan berasal dari berbagai file sumber lain), salah satunya bernama sama dengan file executable. Jadi,
x: y.o z.o
ketika x.c, y.c, dan z.c semuanya ada akan menjalankan:
cc -c x.c -o x.o cc -c y.c -o y.o cc -c z.c -o z.o cc x.o y.o z.o -o x rm -f x.o rm -f y.o rm -f z.o
Pada kasus yang lebih rumit, misalnya ketika tidak ada file objek yang namanya berasal dari nama file executable, Anda harus menulis resep eksplisit untuk penautan.
Setiap jenis file yang secara otomatis dibuat menjadi file objek .o akan ditautkan secara otomatis dengan menggunakan kompiler ($(CC), $(FC), atau $(PC); kompiler C $(CC) dipakai untuk merakit file .s) tanpa opsi -c. Hal ini bisa saja dilakukan dengan memakai file objek .o sebagai perantara, tetapi mengompilasi dan menautkan dalam satu langkah lebih cepat, sehingga itulah yang dilakukan.
n.c dibuat secara otomatis dari n.y dengan menjalankan Yacc menggunakan resep $(YACC) $(YFLAGS).
n.c dibuat secara otomatis dari n.l dengan menjalankan Lex. Resep aktualnya adalah $(LEX) $(LFLAGS).
n.r dibuat secara otomatis dari n.l dengan menjalankan Lex. Resep aktualnya adalah $(LEX) $(LFLAGS).
Konvensi memakai sufiks .l yang sama untuk semua file Lex, terlepas dari apakah file itu menghasilkan kode C atau kode Ratfor, membuat make tidak bisa secara otomatis menentukan bahasa mana dari keduanya yang Anda pakai pada kasus tertentu. Jika make diminta membuat ulang file objek dari file .l, ia harus menebak kompiler mana yang dipakai. Ia akan menebak kompiler C, karena itu lebih umum. Jika Anda memakai Ratfor, pastikan make mengetahuinya dengan menyebutkan n.r di dalam makefile. Atau, jika Anda memakai Ratfor saja tanpa file C sama sekali, hapus .c dari daftar sufiks aturan implisit dengan cara berikut:
.SUFFIXES: .SUFFIXES: .o .r .f .l …
n.ln dibuat dari n.c dengan menjalankan lint. Resep persisnya adalah $(LINT) $(LINTFLAGS) $(CPPFLAGS) -i. Resep yang sama dipakai pada kode C yang dihasilkan dari n.y atau n.l.
n.dvi dibuat dari n.tex dengan resep $(TEX). n.tex dibuat dari n.web dengan $(WEAVE), atau dari n.w (dan dari n.ch jika ada atau dapat dibuat) dengan $(CWEAVE). n.p dibuat dari n.web dengan $(TANGLE), dan n.c dibuat dari n.w (dan dari n.ch jika ada atau dapat dibuat) dengan $(CTANGLE).
n.dvi dibuat dari n.texinfo, n.texi, atau n.txinfo, dengan resep $(TEXI2DVI) $(TEXI2DVI_FLAGS). n.info dibuat dari n.texinfo, n.texi, atau n.txinfo, dengan resep $(MAKEINFO) $(MAKEINFO_FLAGS).
File apa pun n akan diekstrak jika perlu dari file RCS bernama n,v atau RCS/n,v. Resep persisnya adalah $(CO) $(COFLAGS). n tidak akan diekstrak dari RCS jika file itu sudah ada, bahkan jika file RCS-nya lebih baru. Aturan untuk RCS bersifat terminal (lihat Aturan pola yang cocok dengan apa saja), sehingga file RCS tidak dapat dihasilkan dari sumber lain; file itu harus benar-benar ada.
File apa pun n akan diekstrak jika perlu dari file SCCS bernama s.n atau SCCS/s.n. Resep persisnya adalah $(GET) $(GFLAGS). Aturan untuk SCCS bersifat terminal (lihat Aturan pola yang cocok dengan apa saja), sehingga file SCCS tidak dapat dihasilkan dari sumber lain; file itu harus benar-benar ada.
Demi kemudahan SCCS, file n disalin dari n.sh dan dijadikan executable (untuk semua pengguna). Ini untuk skrip shell yang di-checkin ke SCCS. Karena RCS mempertahankan izin eksekusi suatu file, Anda tidak perlu memakai fitur ini dengan RCS.
Kami menganjurkan Anda menghindari penggunaan SCCS. RCS diakui secara luas lebih unggul, dan juga bebas (free). Dengan memilih perangkat lunak bebas alih-alih perangkat lunak berpemilik yang setara (atau lebih rendah), Anda mendukung gerakan perangkat lunak bebas.
Biasanya, variabel yang ingin Anda ubah hanyalah yang tercantum dalam tabel di atas, yang dijelaskan pada bagian berikut.
Namun, resep dalam aturan implisit bawaan sebenarnya memakai variabel seperti COMPILE.c, LINK.p, dan PREPROCESS.S, yang nilainya berisi resep-resep yang tercantum di atas.
make mengikuti konvensi bahwa aturan untuk mengompilasi file sumber .x memakai variabel COMPILE.x. Begitu pula, aturan untuk menghasilkan file executable dari file .x memakai LINK.x, dan aturan untuk melakukan praproses file .x memakai PREPROCESS.x.
Setiap aturan yang menghasilkan file objek memakai variabel OUTPUT_OPTION. make mendefinisikan variabel ini agar berisi -o $@, atau menjadi kosong, tergantung pada opsi waktu kompilasi. Anda memerlukan opsi -o untuk memastikan keluaran masuk ke file yang benar ketika file sumber berada di direktori lain, seperti saat memakai VPATH (lihat Mencari prasyarat dari direktori). Namun, kompiler pada beberapa sistem tidak menerima switch -o untuk file objek. Jika Anda memakai sistem semacam itu dan memakai VPATH, sebagian kompilasi akan menempatkan keluarannya di tempat yang salah. Salah satu solusi untuk masalah ini adalah memberi OUTPUT_OPTION nilai ; mv $*.o $@.
Resep dalam aturan implisit bawaan memakai sejumlah variabel yang telah didefinisikan sebelumnya secara luas. Anda dapat mengubah nilai variabel ini di dalam makefile, melalui argumen ke make, atau melalui lingkungan, untuk mengubah cara kerja aturan implisit tanpa mendefinisikan ulang aturan itu sendiri. Anda dapat membatalkan semua variabel yang dipakai oleh aturan implisit dengan opsi -R atau --no-builtin-variables.
Misalnya, resep yang dipakai untuk mengompilasi file sumber C sebenarnya berbunyi $(CC) -c $(CFLAGS) $(CPPFLAGS). Nilai default variabel yang dipakai adalah cc dan string kosong, sehingga menghasilkan perintah cc -c. Dengan mendefinisikan ulang CC menjadi ncc, Anda dapat membuat ncc dipakai untuk semua kompilasi C yang dilakukan oleh aturan implisit. Dengan mendefinisikan ulang CFLAGS menjadi -g, Anda dapat meneruskan opsi -g ke setiap kompilasi. Semua aturan implisit yang melakukan kompilasi C memakai $(CC) untuk mendapatkan nama program kompiler, dan semuanya menyertakan $(CFLAGS) di antara argumen yang diberikan ke kompiler.
Variabel yang dipakai dalam aturan implisit terbagi menjadi dua kelas: variabel yang merupakan nama program (seperti CC) dan variabel yang berisi argumen untuk program tersebut (seperti CFLAGS). (“Nama program” boleh juga berisi beberapa argumen perintah, tetapi harus dimulai dengan nama program executable yang sebenarnya.) Jika nilai suatu variabel berisi lebih dari satu argumen, pisahkan argumen-argumen itu dengan spasi.
Tabel berikut menjelaskan sebagian dari variabel yang telah didefinisikan sebelumnya yang relatif sering dipakai. Daftar ini tidak lengkap, dan nilai default yang ditampilkan di sini mungkin berbeda dari yang dipilih make pada lingkungan Anda. Untuk melihat daftar lengkap variabel yang telah didefinisikan sebelumnya untuk versi GNU make Anda, jalankan make -p di direktori tanpa makefile.
Berikut adalah tabel variabel yang relatif sering dipakai sebagai nama program dalam aturan bawaan:
ARProgram pengelola arsip. Default ar.
ASProgram untuk mengompilasi file assembly. Default as.
CCProgram untuk mengompilasi program C. Default cc.
CXXProgram untuk mengompilasi program C++. Default g++.
CPPProgram untuk menjalankan preprosesor C, dengan hasil ke standard output. Default $(CC) -E.
FCProgram untuk mengompilasi atau melakukan praproses program Fortran dan Ratfor. Default f77.
M2CProgram yang dipakai untuk mengompilasi kode sumber Modula-2. Default m2c.
PCProgram untuk mengompilasi program Pascal. Default pc.
COProgram untuk mengekstrak file dari RCS. Default co.
GETProgram untuk mengekstrak file dari SCCS. Default get.
LEXProgram yang dipakai untuk mengubah tata bahasa Lex menjadi kode sumber. Default lex.
YACCProgram yang dipakai untuk mengubah tata bahasa Yacc menjadi kode sumber. Default yacc.
LINTProgram yang dipakai untuk menjalankan lint pada kode sumber. Default lint.
MAKEINFOProgram untuk mengubah file sumber Texinfo menjadi file Info. Default makeinfo.
TEXProgram untuk membuat file DVI TeX dari sumber TeX. Default tex.
TEXI2DVIProgram untuk membuat file DVI TeX dari sumber Texinfo. Default texi2dvi.
WEAVEProgram untuk menerjemahkan Web menjadi TeX. Default weave.
CWEAVEProgram untuk menerjemahkan C Web menjadi TeX. Default cweave.
TANGLEProgram untuk menerjemahkan Web menjadi Pascal. Default tangle.
CTANGLEProgram untuk menerjemahkan C Web menjadi C. Default ctangle.
RMPerintah untuk menghapus file. Default rm -f.
Berikut adalah tabel variabel yang nilainya merupakan argumen tambahan untuk program-program di atas. Nilai default untuk semua variabel ini adalah string kosong, kecuali disebutkan lain.
ARFLAGSFlag yang diberikan ke program pengelola arsip. Default rv.
ASFLAGSFlag tambahan yang diberikan ke assembler (ketika dipanggil secara eksplisit pada file .s atau .S).
CFLAGSFlag tambahan yang diberikan ke kompiler C.
CXXFLAGSFlag tambahan yang diberikan ke kompiler C++.
COFLAGSFlag tambahan yang diberikan ke program co milik RCS.
CPPFLAGSFlag tambahan yang diberikan ke preprosesor C dan program yang memakainya (kompiler C dan Fortran).
FFLAGSFlag tambahan yang diberikan ke kompiler Fortran.
GFLAGSFlag tambahan yang diberikan ke program get milik SCCS.
LDFLAGSFlag tambahan yang diberikan ke kompiler ketika diharapkan memanggil linker ld, misalnya -L. Pustaka (library) (-lfoo) sebaiknya ditambahkan ke variabel LDLIBS sebagai gantinya.
LDLIBSFlag atau nama pustaka yang diberikan ke kompiler ketika diharapkan memanggil linker ld. LOADLIBES adalah alternatif usang (tetapi masih didukung) untuk LDLIBS. Flag linker yang bukan pustaka, seperti -L, sebaiknya dimasukkan ke variabel LDFLAGS.
LFLAGSFlag tambahan yang diberikan ke Lex.
YFLAGSFlag tambahan yang diberikan ke Yacc.
PFLAGSFlag tambahan yang diberikan ke kompiler Pascal.
RFLAGSFlag tambahan yang diberikan ke kompiler Fortran untuk program Ratfor.
LINTFLAGSFlag tambahan yang diberikan ke lint.
Kadang-kadang sebuah file dapat dibuat melalui serangkaian aturan implisit. Misalnya, file n.o dapat dibuat dari n.y dengan menjalankan Yacc terlebih dahulu, lalu cc. Rangkaian seperti ini disebut rantai (chain).
Jika file n.c sudah ada, atau disebutkan dalam makefile, tidak diperlukan pencarian khusus: make menemukan bahwa file objek dapat dibuat melalui kompilasi C dari n.c; nanti, ketika mempertimbangkan cara membuat n.c, aturan untuk menjalankan Yacc akan dipakai. Pada akhirnya, baik n.c maupun n.o diperbarui.
Namun, meskipun n.c tidak ada dan tidak disebutkan, make tahu cara membayangkannya sebagai mata rantai yang hilang antara n.o dan n.y! Dalam kasus ini, n.c disebut file perantara (intermediate file). Begitu make memutuskan untuk memakai file perantara, file itu dimasukkan ke dalam basis data seolah-olah disebutkan dalam makefile, lengkap dengan aturan implisit yang menjelaskan cara membuatnya.
File perantara juga dibuat ulang memakai aturannya masing-masing, sama seperti semua file lainnya. Namun, file perantara diperlakukan berbeda dalam dua hal.
Perbedaan pertama adalah apa yang terjadi jika file perantara tidak ada. Jika file biasa b tidak ada, dan make mempertimbangkan target yang bergantung pada b, make pasti akan membuat b lalu memperbarui target itu berdasarkan b. Namun jika b adalah file perantara, make boleh membiarkannya begitu saja: make tidak akan membuat b kecuali salah satu prasyaratnya sudah usang. Ini berarti target yang bergantung pada b juga tidak akan dibangun ulang, kecuali ada alasan lain untuk memperbarui target itu, misalnya target tersebut belum ada atau prasyarat lain lebih baru daripada target.
Perbedaan kedua adalah bahwa jika make benar-benar membuat b untuk memperbarui sesuatu yang lain, make akan menghapus b setelah tidak diperlukan lagi. Karena itu, file perantara yang tidak ada sebelum make dijalankan juga tidak akan ada setelah make selesai. make memberi tahu Anda tentang penghapusan itu dengan menampilkan perintah rm yang menunjukkan file mana yang dihapusnya.
Anda dapat menandai sebuah file secara eksplisit sebagai perantara dengan mencantumkannya sebagai prasyarat dari target khusus .INTERMEDIATE. Ini berlaku meskipun file tersebut juga disebutkan secara eksplisit dengan cara lain.
File tidak dapat menjadi perantara jika file itu disebutkan dalam makefile sebagai target atau prasyarat. Karena itu, salah satu cara untuk menghindari penghapusan file perantara adalah dengan menambahkannya sebagai prasyarat dari suatu target. Namun, melakukan hal ini dapat menyebabkan make melakukan pekerjaan tambahan ketika mencari aturan pola (lihat Algoritma pencarian aturan implisit).
Sebagai alternatif, mencantumkan sebuah file sebagai prasyarat dari target khusus .NOTINTERMEDIATE memaksa file itu untuk tidak dianggap sebagai perantara (sama seperti penyebutan file itu dengan cara lain mana pun). Selain itu, mencantumkan pola target dari suatu aturan pola sebagai prasyarat dari .NOTINTERMEDIATE memastikan bahwa target-target yang dihasilkan memakai aturan pola tersebut tidak dianggap sebagai perantara.
Anda dapat menonaktifkan file perantara sepenuhnya di dalam makefile dengan memberikan .NOTINTERMEDIATE sebagai target tanpa prasyarat: dalam kasus ini, hal itu berlaku untuk setiap file dalam makefile.
Jika Anda tidak ingin make membuat sebuah file hanya karena file itu belum ada, tetapi Anda juga tidak ingin make menghapusnya secara otomatis, Anda dapat menandainya sebagai file sekunder (secondary). Untuk melakukannya, cantumkan file itu sebagai prasyarat dari target khusus .SECONDARY. Menandai sebuah file sebagai sekunder juga menandainya sebagai perantara.
Rantai dapat melibatkan lebih dari dua aturan implisit. Misalnya, dimungkinkan untuk membuat file foo dari RCS/foo.y,v dengan menjalankan RCS, Yacc, dan cc. Dalam kasus ini, baik foo.y maupun foo.c adalah file perantara yang akan dihapus pada akhirnya.
Tidak ada satu aturan implisit yang dapat muncul lebih dari sekali dalam satu rantai. Ini berarti make bahkan tidak akan mempertimbangkan hal konyol seperti membuat foo dari foo.o.o dengan menjalankan linker dua kali. Batasan ini juga memberi manfaat tambahan, yaitu mencegah pencarian rantai aturan implisit terjebak dalam loop tak terhingga.
Ada beberapa aturan implisit khusus untuk mengoptimalkan kasus-kasus tertentu yang jika tidak demikian akan ditangani oleh rantai aturan. Misalnya, membuat foo dari foo.c bisa saja ditangani dengan mengompilasi dan menautkan memakai rantai aturan yang terpisah, menggunakan foo.o sebagai file perantara. Namun, yang sebenarnya terjadi adalah aturan khusus untuk kasus ini melakukan kompilasi dan penautan dengan satu perintah cc. Aturan yang dioptimalkan ini dipakai lebih dulu daripada rantai bertahap, karena posisinya lebih awal dalam urutan aturan.
Terakhir, demi alasan performa, make tidak akan mempertimbangkan aturan yang cocok dengan apa saja dan tidak terminal (yaitu %:) ketika mencari aturan untuk membuat prasyarat dari suatu aturan implisit (lihat Aturan pola yang cocok dengan apa saja).
Anda mendefinisikan aturan implisit dengan menulis aturan pola. Aturan pola terlihat seperti aturan biasa, tetapi targetnya mengandung karakter % (tepat satu buah). Target diperlakukan sebagai pola untuk mencocokkan nama file; % cocok dengan substring tidak kosong apa pun, sedangkan karakter lain hanya cocok dengan dirinya sendiri. Prasyarat juga memakai % dengan cara yang sama untuk menunjukkan bagaimana namanya berhubungan dengan nama target.
Jadi, aturan pola %.o : %.c menjelaskan cara membuat file stem.o mana pun dari file lain stem.c.
Perhatikan bahwa ekspansi memakai % dalam aturan pola terjadi setelah ekspansi variabel atau fungsi. Ekspansi variabel dan fungsi terjadi ketika makefile dibaca. Lihat Cara menggunakan variabel dan Fungsi untuk transformasi teks.
Aturan pola mengandung karakter % (tepat satu buah) pada targetnya; selain itu, aturan pola terlihat persis seperti aturan biasa. Target merupakan pola untuk mencocokkan nama file; % cocok dengan substring tidak kosong apa pun, sedangkan karakter lain hanya cocok dengan dirinya sendiri.
Misalnya, %.c sebagai pola cocok dengan nama file apa pun yang berakhiran .c. s.%.c sebagai pola cocok dengan nama file apa pun yang diawali s., berakhiran .c, dan panjangnya minimal lima karakter. (Harus ada setidaknya satu karakter yang cocok dengan %.) Substring yang cocok dengan % disebut stem.
% dalam prasyarat aturan pola mewakili stem yang sama dengan yang dicocokkan oleh % pada target. Agar aturan pola dapat diterapkan, pola targetnya harus cocok dengan nama file yang sedang dipertimbangkan, dan semua prasyaratnya (setelah substitusi pola) harus merujuk ke file yang ada atau dapat dibuat. File-file ini menjadi prasyarat dari target.
Jadi, aturan berbentuk
%.o : %.c ; recipe…
menentukan cara membuat file n.o, dengan file lain n.c sebagai prasyaratnya, asalkan n.c ada atau dapat dibuat.
Boleh juga ada prasyarat yang tidak memakai %; prasyarat semacam itu melekat pada setiap file yang dibuat oleh aturan pola ini. Prasyarat tetap seperti ini kadang berguna.
Aturan pola tidak perlu memiliki prasyarat yang mengandung %, bahkan boleh saja sama sekali tidak memiliki prasyarat. Aturan semacam itu pada dasarnya berfungsi sebagai wildcard umum. Aturan itu menyediakan cara untuk membuat file apa pun yang cocok dengan pola target. Lihat Mendefinisikan aturan default sebagai upaya terakhir.
Beberapa aturan pola dapat cocok dengan satu target yang sama. Dalam kasus ini, make memilih aturan yang paling “cocok” (best fit). Lihat Bagaimana pola mencocokkan.
Aturan pola juga dapat memiliki lebih dari satu target. Namun, semua target harus mengandung karakter %. Beberapa pola target dalam aturan pola selalu diperlakukan sebagai target yang dikelompokkan, terlepas dari apakah aturan itu memakai pemisah : atau &: (lihat Banyak target dalam satu aturan).
Namun, ada satu pengecualian. Jika sebuah pola target sudah usang atau tidak ada, tetapi makefile tidak perlu membangunnya, target tersebut tidak akan membuat target lain dianggap usang. Perlu diperhatikan bahwa pengecualian historis ini akan dihapus pada versi GNU make mendatang dan sebaiknya tidak diandalkan. Jika make mendeteksi situasi ini, make akan menampilkan peringatan pattern recipe did not update peer target (resep pola tidak memperbarui target sejawat); namun, make tidak dapat mendeteksi semua situasi semacam ini. Pastikan resep Anda memperbarui semua pola target ketika resep itu dijalankan.
Berikut adalah beberapa contoh aturan pola yang sebenarnya telah didefinisikan sebelumnya di dalam make. Pertama, aturan yang mengompilasi file .c menjadi file .o:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
mendefinisikan aturan yang dapat membuat file x.o mana pun dari x.c. Resep ini memakai variabel otomatis $@ dan $< untuk menggantikan nama file target dan nama file sumber pada setiap kasus tempat aturan ini diterapkan (lihat Variabel otomatis).
Berikut aturan bawaan kedua:
% :: RCS/%,v
$(CO) $(COFLAGS) $<
mendefinisikan aturan yang dapat membuat file x apa pun dari file x,v yang bersesuaian di subdirektori RCS. Karena targetnya adalah %, aturan ini berlaku untuk file apa pun, asalkan file prasyarat yang sesuai ada. Titik dua ganda menjadikan aturan ini terminal, yang berarti prasyaratnya tidak boleh berupa file perantara (lihat Aturan pola yang cocok dengan apa saja).
Aturan pola ini memiliki dua target:
%.tab.c %.tab.h: %.y
bison -d $<
Ini memberi tahu make bahwa resep bison -d x.y akan membuat baik x.tab.c maupun x.tab.h. Jika file foo bergantung pada file parse.tab.o dan scan.o, dan file scan.o bergantung pada file parse.tab.h, ketika parse.y diubah, resep bison -d parse.y hanya akan dijalankan satu kali, dan prasyarat baik parse.tab.o maupun scan.o akan terpenuhi. (Kemungkinan besar, file parse.tab.o akan dikompilasi ulang dari parse.tab.c dan file scan.o dari scan.c, sementara foo ditautkan dari parse.tab.o, scan.o, dan prasyarat lainnya, lalu berjalan lancar selamanya.)
Misalkan Anda sedang menulis aturan pola untuk mengompilasi file .c menjadi file .o: bagaimana Anda menulis perintah cc agar bekerja pada nama file sumber yang tepat? Anda tidak dapat menuliskan nama itu di dalam resep, karena namanya berbeda setiap kali aturan implisit diterapkan.
Yang Anda lakukan adalah memakai fitur khusus make, yaitu variabel otomatis (automatic variable). Variabel-variabel ini memiliki nilai yang dihitung ulang untuk setiap aturan yang dijalankan, berdasarkan target dan prasyarat aturan tersebut. Dalam contoh ini, Anda akan memakai $@ untuk nama file objek dan $< untuk nama file sumber.
Sangat penting untuk menyadari bahwa cakupan ketersediaan nilai variabel otomatis itu terbatas: nilai-nilai itu hanya berlaku di dalam resep. Secara khusus, Anda tidak dapat memakainya di mana pun dalam daftar target suatu aturan; di sana variabel itu tidak memiliki nilai dan akan berekspansi menjadi string kosong. Selain itu, variabel itu juga tidak dapat diakses secara langsung di dalam daftar prasyarat suatu aturan. Kesalahan umum adalah mencoba memakai $@ di dalam daftar prasyarat; ini tidak akan berhasil. Namun, ada fitur khusus GNU make, yaitu ekspansi sekunder (lihat Ekspansi sekunder), yang memungkinkan nilai variabel otomatis dipakai di dalam daftar prasyarat.
Berikut tabel variabel otomatis:
$@Nama file target dari aturan tersebut. Jika target adalah anggota arsip, $@ adalah nama file arsipnya. Dalam aturan pola yang memiliki banyak target (lihat Pengantar aturan pola), $@ adalah nama target mana pun yang menyebabkan resep aturan itu dijalankan.
$%Nama anggota target, ketika target adalah anggota arsip. Lihat Menggunakan make untuk memperbarui file arsip. Misalnya jika target adalah foo.a(bar.o), maka $% adalah bar.o, dan $@ adalah foo.a. Jika target bukan anggota arsip, $% kosong.
$<Nama prasyarat pertama. Jika target mendapatkan resepnya dari aturan implisit, ini adalah prasyarat pertama yang ditambahkan oleh aturan implisit tersebut (lihat Menggunakan aturan implisit).
$?Nama semua prasyarat yang lebih baru daripada target, dipisahkan dengan spasi. Jika target belum ada, semua prasyarat akan disertakan. Untuk prasyarat yang merupakan anggota arsip, hanya anggota yang disebutkan yang dipakai (lihat Menggunakan make untuk memperbarui file arsip).
$? berguna bahkan dalam aturan eksplisit ketika Anda ingin memproses hanya prasyarat yang telah berubah. Misalnya, andaikan sebuah arsip bernama lib seharusnya berisi salinan beberapa file objek. Aturan berikut hanya menyalin file objek yang berubah ke dalam arsip:
lib: foo.o bar.o lose.o win.o
ar r lib $?
$^Nama semua prasyarat, dipisahkan dengan spasi. Untuk prasyarat yang merupakan anggota arsip, hanya anggota yang disebutkan yang dipakai (lihat Menggunakan make untuk memperbarui file arsip). Target hanya memiliki satu prasyarat untuk setiap file lain yang menjadi dependensinya, tidak peduli berapa kali file itu dicantumkan sebagai prasyarat. Jadi, jika Anda mencantumkan sebuah prasyarat lebih dari sekali untuk suatu target, nilai $^ hanya berisi satu salinan nama itu. Daftar ini tidak berisi prasyarat yang bersifat order-only; untuk itu, lihat variabel $| di bawah.
$+Ini serupa dengan $^, tetapi prasyarat yang dicantumkan lebih dari sekali akan digandakan sesuai urutan pencantumannya dalam makefile. Ini terutama berguna untuk perintah penautan, tempat mengulang nama file pustaka dalam urutan tertentu memiliki arti penting.
$|Nama semua prasyarat order-only, dipisahkan dengan spasi.
$*Stem yang dicocokkan oleh aturan implisit (lihat Bagaimana pola mencocokkan). Jika target adalah dir/a.foo.b dan pola targetnya adalah a.%.b, maka stem-nya adalah dir/foo. Stem berguna untuk menyusun nama file-file terkait.
Dalam aturan pola statis, stem adalah bagian dari nama file yang cocok dengan % pada pola target.
Dalam aturan eksplisit, tidak ada stem, sehingga $* tidak dapat ditentukan dengan cara itu. Sebagai gantinya, jika nama target berakhiran sufiks yang dikenali (lihat Aturan sufiks gaya lama), $* diatur menjadi nama target dikurangi sufiks tersebut. Misalnya, jika nama target adalah foo.c, maka $* diatur menjadi foo, karena .c adalah sebuah sufiks. GNU make melakukan hal yang tampak aneh ini hanya demi kompatibilitas dengan implementasi make lain. Sebaiknya Anda umumnya menghindari pemakaian $* kecuali di dalam aturan implisit atau aturan pola statis.
Jika nama target dalam aturan eksplisit tidak berakhiran sufiks yang dikenali, $* diatur menjadi string kosong untuk aturan tersebut.
Dari variabel-variabel yang tercantum di atas, empat variabel bernilai satu nama file, dan tiga variabel bernilai daftar nama file. Ketujuh variabel ini memiliki varian yang hanya mengambil nama direktori file atau hanya nama file di dalam direktori. Nama variabel varian dibentuk dengan menambahkan D atau F di akhir. Fungsi dir dan notdir dapat dipakai untuk mendapatkan efek serupa (lihat Fungsi untuk nama file). Namun perlu diperhatikan bahwa semua varian D menghilangkan garis miring di akhir, yang selalu muncul pada keluaran fungsi dir. Berikut tabel variannya:
Bagian direktori dari nama file target, dengan garis miring di akhir dihilangkan. Jika nilai $@ adalah dir/foo.o, maka $(@D) adalah dir. Nilai ini adalah . jika $@ tidak mengandung garis miring.
Bagian nama file di dalam direktori dari nama file target. Jika nilai $@ adalah dir/foo.o, maka $(@F) adalah foo.o. $(@F) setara dengan $(notdir $@).
Bagian direktori dan bagian nama file di dalam direktori dari stem; dalam contoh ini, dir dan foo.
Bagian direktori dan bagian nama file di dalam direktori dari nama anggota arsip target. Ini hanya berarti untuk target anggota arsip berbentuk archive(member) dan hanya berguna ketika member dapat mengandung nama direktori. (Lihat Anggota arsip sebagai target.)
Bagian direktori dan bagian nama file di dalam direktori dari prasyarat pertama.
Daftar bagian direktori dan daftar bagian nama file di dalam direktori dari semua prasyarat.
Daftar bagian direktori dan daftar bagian nama file di dalam direktori dari semua prasyarat, termasuk beberapa instance dari prasyarat yang berulang.
Daftar bagian direktori dan daftar bagian nama file di dalam direktori dari semua prasyarat yang lebih baru daripada target.
Perhatikan bahwa kami memakai konvensi gaya penulisan khusus ketika membahas variabel otomatis ini; kami menulis “nilai $<”, bukan “variabel <” seperti yang kami tulis untuk variabel biasa seperti objects dan CFLAGS. Menurut kami, konvensi ini terlihat lebih alami untuk kasus khusus ini. Mohon jangan menganggap ini memiliki makna mendalam; $< hanya merujuk ke variabel bernama <, sama seperti $(CFLAGS) merujuk ke variabel bernama CFLAGS. Anda bisa saja menulis $(<) sebagai ganti $<, dengan hasil yang sama persis.
Pola target disusun dari % di antara sebuah prefiks dan sebuah sufiks, dan salah satu atau keduanya boleh kosong. Pola itu cocok dengan sebuah nama file hanya jika nama file itu diawali prefiks dan diakhiri sufiks, tanpa tumpang tindih. Teks di antara prefiks dan sufiks disebut stem. Jadi, ketika pola %.o cocok dengan nama file test.o, stem-nya adalah test. Prasyarat aturan pola diubah menjadi nama file sebenarnya dengan menggantikan karakter % dengan stem tersebut. Jadi, jika pada contoh yang sama salah satu prasyaratnya ditulis sebagai %.c, prasyarat itu berekspansi menjadi test.c.
Ketika pola target tidak mengandung garis miring (dan biasanya memang tidak), nama direktori dalam nama file dihilangkan dari nama file sebelum dibandingkan dengan prefiks dan sufiks target. Setelah perbandingan nama file dengan pola target, nama direktori, berikut garis miring yang mengakhirinya, ditambahkan kembali ke nama file prasyarat yang dihasilkan dari pola prasyarat aturan pola dan nama file tersebut. Direktori diabaikan hanya untuk tujuan mencari aturan implisit yang akan dipakai, bukan dalam penerapan aturan itu sendiri. Jadi, e%t cocok dengan nama file src/eat, dengan src/a sebagai stem. Ketika prasyarat diubah menjadi nama file, direktori dari stem ditambahkan di depan, sementara sisa stem menggantikan %. Stem src/a dengan pola prasyarat c%r menghasilkan nama file src/car.
Aturan pola hanya dapat dipakai untuk membangun sebuah file jika ada pola target yang cocok dengan nama file itu, dan semua prasyarat dalam aturan itu ada atau dapat dibangun. Aturan yang Anda tulis diprioritaskan di atas aturan bawaan. Namun perlu diperhatikan, aturan yang dapat dipenuhi tanpa merantai aturan implisit lain (misalnya, aturan yang tidak memiliki prasyarat, atau prasyaratnya sudah ada atau sudah disebutkan) selalu diprioritaskan di atas aturan yang prasyaratnya harus dibuat dengan merantai aturan implisit lain.
Mungkin saja lebih dari satu aturan pola memenuhi kriteria ini. Dalam kasus ini, make akan memilih aturan dengan stem terpendek (yaitu, pola yang paling spesifik kecocokannya). Jika lebih dari satu aturan pola memiliki stem terpendek yang sama, make akan memilih yang pertama kali ditemukan dalam makefile.
Algoritma ini menghasilkan aturan yang lebih spesifik diprioritaskan di atas aturan yang lebih umum; misalnya:
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
%.o : %.f
$(COMPILE.F) $(OUTPUT_OPTION) $<
lib/%.o: lib/%.c
$(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Dengan aturan-aturan ini, ketika diminta membangun bar.o sementara bar.c dan bar.f sama-sama ada, make akan memilih aturan pertama dan mengompilasi bar.c menjadi bar.o. Pada situasi yang sama ketika bar.c tidak ada, make akan memilih aturan kedua dan mengompilasi bar.f menjadi bar.o.
Jika make diminta membangun lib/bar.o sementara lib/bar.c dan lib/bar.f sama-sama ada, aturan ketiga akan dipilih, karena stem aturan ini (bar) lebih pendek daripada stem aturan pertama (lib/bar). Jika lib/bar.c tidak ada, aturan ketiga tidak lagi memenuhi syarat, dan aturan kedua akan dipakai, meskipun stem-nya lebih panjang.
Ketika target sebuah aturan pola hanya berupa %, aturan itu cocok dengan nama file apa pun. Kami menyebut aturan semacam ini aturan yang cocok dengan apa saja (match-anything). Aturan ini sangat berguna, tetapi make bisa membutuhkan banyak waktu untuk mempertimbangkannya, karena make harus memeriksa setiap aturan semacam itu untuk setiap nama file yang dicantumkan, baik sebagai target maupun sebagai prasyarat.
Andaikan makefile menyebutkan foo.c. Untuk target ini, make harus mempertimbangkan membuatnya dengan menautkan file objek foo.c.o, atau dengan kompilasi-dan-penautan C dalam satu langkah dari foo.c.c, atau dengan kompilasi-dan-penautan Pascal dari foo.c.p, dan banyak kemungkinan lainnya.
Kita tahu kemungkinan-kemungkinan ini konyol karena foo.c adalah file sumber C, bukan file executable. Jika make benar-benar mempertimbangkan kemungkinan-kemungkinan ini, pada akhirnya make akan menolaknya, karena file seperti foo.c.o dan foo.c.p tidak akan ada. Namun kemungkinan-kemungkinan ini sangat banyak jumlahnya, sehingga make akan berjalan sangat lambat jika harus mempertimbangkan semuanya.
Untuk meningkatkan kecepatan, kami menerapkan berbagai batasan pada cara make mempertimbangkan aturan yang cocok dengan apa saja. Ada dua batasan berbeda yang dapat diterapkan, dan setiap kali Anda mendefinisikan aturan yang cocok dengan apa saja, Anda harus memilih salah satunya untuk aturan tersebut.
Salah satu pilihannya adalah menandai aturan yang cocok dengan apa saja itu sebagai terminal dengan mendefinisikannya memakai titik dua ganda. Ketika sebuah aturan bersifat terminal, aturan itu tidak berlaku kecuali prasyaratnya benar-benar ada. Prasyarat yang bisa dibuat memakai aturan implisit lain tidaklah cukup. Dengan kata lain, tidak ada perantaian lebih lanjut yang diizinkan melewati aturan terminal.
Misalnya, aturan implisit bawaan untuk mengekstrak sumber dari file RCS dan SCCS bersifat terminal; akibatnya, jika file foo.c,v tidak ada, make bahkan tidak akan mempertimbangkan untuk membuatnya sebagai file perantara dari foo.c,v.o atau dari RCS/SCCS/s.foo.c,v. File RCS dan SCCS umumnya merupakan file sumber utama (ultimate source files) yang tidak seharusnya dibuat ulang dari file lain mana pun; karena itu, make dapat menghemat waktu dengan tidak mencari cara untuk membuatnya ulang.
Jika Anda tidak menandai aturan yang cocok dengan apa saja itu sebagai terminal, aturan itu menjadi nonterminal. Aturan yang cocok dengan apa saja dan nonterminal tidak dapat diterapkan pada prasyarat suatu aturan implisit, atau pada nama file yang menunjukkan jenis data tertentu. Nama file menunjukkan jenis data tertentu jika ada target dari aturan implisit bukan-cocok-dengan-apa-saja yang cocok dengannya.
Misalnya, nama file foo.c cocok dengan target dari aturan pola %.c : %.y (aturan untuk menjalankan Yacc). Terlepas dari apakah aturan ini benar-benar dapat diterapkan (yang hanya terjadi jika ada file foo.y), fakta bahwa targetnya cocok saja sudah cukup untuk mencegah pertimbangan aturan cocok-dengan-apa-saja nonterminal mana pun untuk file foo.c. Jadi, make bahkan tidak akan mempertimbangkan mencoba membuat foo.c sebagai file executable dari foo.c.o, foo.c.c, foo.c.p, dan sebagainya.
Motivasi di balik batasan ini adalah bahwa aturan cocok-dengan-apa-saja nonterminal dipakai untuk membuat file yang berisi jenis data tertentu (seperti file executable), sedangkan nama file dengan sufiks yang dikenali menunjukkan jenis data spesifik lain (seperti file sumber C).
Aturan pola dummy bawaan khusus disediakan semata-mata untuk mengenali nama file tertentu, agar aturan cocok-dengan-apa-saja nonterminal tidak dipertimbangkan. Aturan dummy ini tidak memiliki prasyarat maupun resep, dan diabaikan untuk semua tujuan lainnya. Misalnya, aturan implisit bawaan
%.p :
ada untuk memastikan bahwa file sumber Pascal seperti foo.p cocok dengan pola target tertentu, sehingga mencegah terbuangnya waktu untuk mencari foo.p.o atau foo.p.c.
Aturan pola dummy seperti yang untuk %.p dibuat untuk setiap sufiks yang tercantum sebagai sufiks yang sah untuk dipakai dalam aturan sufiks (lihat Aturan sufiks gaya lama).
Anda dapat menimpa aturan implisit bawaan (atau aturan yang Anda definisikan sendiri) dengan mendefinisikan aturan pola baru yang memiliki target dan prasyarat yang sama, tetapi resep yang berbeda. Ketika aturan baru didefinisikan, aturan bawaan digantikan. Posisi aturan baru dalam urutan aturan implisit ditentukan oleh tempat Anda menuliskan aturan baru itu.
Anda dapat membatalkan aturan implisit bawaan dengan mendefinisikan aturan pola yang memiliki target dan prasyarat yang sama, tetapi tanpa resep. Misalnya, berikut ini akan membatalkan aturan yang menjalankan assembler:
%.o : %.s
Anda dapat mendefinisikan aturan implisit sebagai upaya terakhir dengan menulis aturan pola terminal yang cocok dengan apa saja dan tidak memiliki prasyarat (lihat Aturan pola yang cocok dengan apa saja). Ini persis seperti aturan pola lainnya; satu-satunya hal khusus adalah bahwa aturan ini cocok dengan target apa pun. Jadi, resep aturan semacam ini dipakai untuk semua target dan prasyarat yang tidak memiliki resepnya sendiri dan yang tidak ada aturan implisit lain yang berlaku.
Misalnya, ketika menguji sebuah makefile, Anda mungkin tidak peduli apakah file sumber berisi data sungguhan, yang penting file itu ada. Maka Anda bisa melakukan ini:
%::
touch $@
untuk membuat semua file sumber yang diperlukan (sebagai prasyarat) secara otomatis.
Sebagai gantinya, Anda dapat mendefinisikan resep yang dipakai untuk target yang sama sekali tidak memiliki aturan, bahkan target yang tidak menentukan resep pun. Anda melakukannya dengan menulis aturan untuk target .DEFAULT. Resep dari aturan semacam ini dipakai untuk semua prasyarat yang tidak muncul sebagai target dalam aturan eksplisit mana pun, dan yang tidak ada aturan implisit yang berlaku. Wajar saja, tidak ada aturan .DEFAULT kecuali Anda menuliskannya sendiri.
Jika Anda memakai .DEFAULT tanpa resep atau prasyarat:
.DEFAULT:
resep yang sebelumnya tersimpan untuk .DEFAULT akan dihapus. Kemudian make akan bertindak seolah-olah Anda tidak pernah mendefinisikan .DEFAULT sama sekali.
Jika Anda tidak ingin sebuah target mendapatkan resep dari aturan pola yang cocok dengan apa saja atau dari .DEFAULT, tetapi Anda juga tidak ingin resep apa pun dijalankan untuk target itu, Anda dapat memberinya resep kosong (lihat Menggunakan resep kosong).
Anda dapat memakai aturan upaya terakhir untuk menimpa sebagian dari makefile lain. Lihat Menimpa sebagian dari makefile lain.
Aturan sufiks adalah cara lama untuk mendefinisikan aturan implisit di make. Aturan sufiks sudah usang karena aturan pola lebih umum dan lebih jelas. Aturan sufiks tetap didukung di GNU make demi kompatibilitas dengan makefile lama. Ada dua jenis aturan sufiks: sufiks ganda (double-suffix) dan sufiks tunggal (single-suffix).
Aturan sufiks ganda didefinisikan oleh sepasang sufiks: sufiks target dan sufiks sumber. Aturan ini cocok dengan file mana pun yang namanya berakhiran sufiks target. Prasyarat implisit yang bersesuaian dibuat dengan menggantikan sufiks target dengan sufiks sumber pada nama file. Aturan sufiks ganda .c.o (dengan sufiks target dan sufiks sumber masing-masing .o dan .c) setara dengan aturan pola %.o : %.c.
Aturan sufiks tunggal didefinisikan oleh satu sufiks, yaitu sufiks sumber. Aturan ini cocok dengan nama file apa pun, dan nama prasyarat implisit yang bersesuaian dibuat dengan menambahkan sufiks sumber di akhir. Aturan sufiks tunggal dengan sufiks sumber .c setara dengan aturan pola % : %.c.
Definisi aturan sufiks dikenali dengan membandingkan target setiap aturan terhadap daftar sufiks yang dikenal yang telah didefinisikan. Ketika make menemukan aturan yang targetnya berupa sufiks yang dikenal, aturan itu dianggap sebagai aturan sufiks tunggal. Ketika make menemukan aturan yang targetnya berupa gabungan dua sufiks yang dikenal, aturan itu dianggap sebagai aturan sufiks ganda.
Misalnya, .c dan .o sama-sama ada dalam daftar sufiks default yang dikenal. Karena itu, jika Anda mendefinisikan aturan yang targetnya .c.o, make akan menganggapnya sebagai aturan sufiks ganda dengan sufiks sumber .c dan sufiks target .o. Berikut cara lama untuk mendefinisikan aturan mengompilasi file sumber C:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
Aturan sufiks tidak boleh memiliki prasyarat sendiri. Jika aturan itu memiliki prasyarat, prasyarat itu akan diperlakukan sebagai file biasa dengan nama yang aneh, bukan sebagai aturan sufiks. Jadi, aturan:
.c.o: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
menjelaskan cara membuat file .c.o dari file prasyarat foo.h, dan sama sekali berbeda dari aturan pola:
%.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
yang menjelaskan cara membuat file .o dari file .c, dan membuat semua file .o yang dibuat memakai aturan pola ini juga bergantung pada foo.h.
Aturan sufiks tanpa resep juga tidak bermakna. Aturan seperti ini tidak menghapus aturan sebelumnya, tidak seperti aturan pola tanpa resep (lihat Membatalkan aturan implisit). Aturan ini hanya memasukkan sufiks, atau pasangan sufiks yang digabungkan, sebagai target ke dalam basis data.
Sufiks yang dikenal sederhananya adalah nama-nama prasyarat dari target khusus .SUFFIXES. Anda dapat menambahkan sufiks Anda sendiri dengan menulis aturan untuk .SUFFIXES yang menambahkan lebih banyak prasyarat, seperti berikut:
.SUFFIXES: .hack .win
yang menambahkan .hack dan .win ke akhir daftar sufiks.
Jika Anda ingin menghilangkan sufiks default yang dikenal alih-alih hanya menambahkannya, tulislah aturan untuk .SUFFIXES tanpa prasyarat. Dengan pengecualian khusus, hal ini menghilangkan semua prasyarat .SUFFIXES yang sudah ada. Anda kemudian dapat menulis aturan lain untuk menambahkan sufiks yang Anda inginkan. Misalnya:
.SUFFIXES: # Hapus sufiks default .SUFFIXES: .c .o .h # Definisikan daftar sufiks kita sendiri
Flag -r atau --no-builtin-rules menyebabkan daftar sufiks default menjadi kosong.
Variabel SUFFIXES didefinisikan menjadi daftar sufiks default sebelum make membaca makefile mana pun. Anda dapat mengubah daftar sufiks dengan aturan untuk target khusus .SUFFIXES, tetapi hal itu tidak mengubah variabel ini.
Berikut adalah prosedur yang dipakai make untuk mencari aturan implisit bagi sebuah target t. Prosedur ini diikuti untuk setiap aturan titik dua ganda tanpa resep, untuk setiap target dari aturan biasa yang tidak satu pun memiliki resep, dan untuk setiap prasyarat yang bukan target dari aturan mana pun. Prosedur ini juga diikuti secara rekursif untuk prasyarat yang berasal dari aturan implisit, dalam pencarian rantai aturan.
Aturan sufiks tidak disebutkan dalam algoritma ini karena aturan sufiks diubah menjadi aturan pola yang setara setelah makefile selesai dibaca.
Untuk target anggota arsip berbentuk archive(member), algoritma berikut dijalankan dua kali: pertama memakai nama target lengkap t, dan jika pencarian pertama tidak menemukan aturan, kedua memakai (member) sebagai target t.
Jika semua prasyarat ada atau seharusnya ada, atau tidak ada prasyarat sama sekali, maka aturan ini berlaku.
.DEFAULT, jika ada, akan berlaku. Dalam hal itu, t diberi resep yang sama dengan resep .DEFAULT. Jika tidak, tidak ada resep untuk t.
Setelah ditemukan aturan yang berlaku, untuk setiap pola target dari aturan itu selain pola yang cocok dengan t atau n, karakter % dalam pola itu digantikan dengan s, dan nama file hasilnya disimpan sampai resep untuk membuat ulang file target t dijalankan. Setelah resep dijalankan, setiap nama file yang disimpan ini dimasukkan ke dalam basis data dan ditandai sebagai telah diperbarui, dengan status pembaruan yang sama dengan file t.
Ketika resep sebuah aturan pola dijalankan untuk t, variabel otomatis diatur sesuai dengan target dan prasyarat aturan tersebut. Lihat Variabel otomatis.