Direktif kondisional membuat sebagian makefile dipatuhi atau diabaikan, tergantung pada nilai variabel. Kondisional dapat membandingkan nilai suatu variabel dengan variabel lain, atau nilai suatu variabel dengan string konstan. Yang dikendalikan oleh kondisional adalah apa yang benar-benar “dilihat” oleh make di dalam makefile, sehingga kondisional tidak dapat digunakan untuk mengendalikan resep (recipe) pada saat resep tersebut dijalankan.
Contoh kondisional berikut memberi tahu make agar menggunakan satu kumpulan pustaka (library) jika variabel CC bernilai ‘gcc’, dan kumpulan pustaka lain jika tidak. Ini dicapai dengan mengendalikan baris resep mana, dari dua baris resep pada aturan tersebut, yang akan digunakan. Hasilnya, memberikan ‘CC=gcc’ sebagai argumen kepada make tidak hanya mengubah kompiler yang digunakan, tetapi juga pustaka yang ditautkan.
libs_for_gcc = -lgnu
normal_libs =
foo: $(objects)
ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
Kondisional ini menggunakan tiga direktif: satu ifeq, satu else, dan satu endif.
Direktif ifeq memulai kondisional dan menentukan kondisinya. Direktif ini mengambil dua argumen, dipisahkan oleh koma dan diapit tanda kurung. Substitusi variabel dilakukan pada kedua argumen, lalu keduanya dibandingkan. Baris-baris makefile setelah ifeq dipatuhi jika kedua argumen cocok; jika tidak, baris-baris tersebut diabaikan.
Direktif else membuat baris-baris berikutnya dipatuhi jika kondisi sebelumnya tidak terpenuhi. Pada contoh di atas, ini berarti perintah penautan alternatif kedua selalu digunakan setiap kali perintah alternatif pertama tidak digunakan. Menyertakan else dalam sebuah kondisional bersifat opsional.
Direktif endif mengakhiri kondisional. Setiap kondisional harus diakhiri dengan endif. Setelahnya dapat diikuti oleh teks makefile yang tidak bersyarat.
Seperti yang ditunjukkan oleh contoh ini, kondisional bekerja pada level tekstual: baris-baris dalam kondisional diperlakukan sebagai bagian dari makefile, atau diabaikan, sesuai dengan kondisinya. Inilah sebabnya mengapa unit sintaksis makefile yang lebih besar, seperti aturan, boleh membentang melewati awal atau akhir kondisional.
Ketika variabel CC bernilai ‘gcc’, contoh di atas memiliki efek berikut:
foo: $(objects)
$(CC) -o foo $(objects) $(libs_for_gcc)
Ketika variabel CC memiliki nilai lain apa pun, efeknya adalah sebagai berikut:
foo: $(objects)
$(CC) -o foo $(objects) $(normal_libs)
Hasil yang setara dapat diperoleh dengan cara lain, yaitu dengan menjadikan penetapan variabel sebagai kondisional, lalu menggunakan variabel tersebut tanpa syarat:
libs_for_gcc = -lgnu
normal_libs =
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
foo: $(objects)
$(CC) -o foo $(objects) $(libs)
Sintaksis kondisional sederhana tanpa else adalah sebagai berikut:
conditional-directive text-if-true endif
text-if-true dapat berupa baris teks apa pun, yang akan dianggap sebagai bagian dari makefile jika kondisinya benar. Jika kondisinya salah, tidak ada teks yang digunakan sebagai gantinya.
Sintaksis kondisional kompleks adalah sebagai berikut:
conditional-directive text-if-true else text-if-false endif
Atau:
conditional-directive-one text-if-one-is-true else conditional-directive-two text-if-two-is-true else text-if-one-and-two-are-false endif
Klausa ‘else conditional-directive’ dapat ditulis sebanyak yang diperlukan. Begitu suatu kondisi terpenuhi, text-if-true-nya yang digunakan dan tidak ada klausa lain yang digunakan; jika tidak ada kondisi yang terpenuhi, text-if-false yang digunakan. text-if-true dan text-if-false dapat terdiri dari berapa pun banyaknya baris teks.
Sintaksis conditional-directive sama saja, baik kondisionalnya sederhana maupun kompleks, dan baik setelah else maupun tidak. Ada empat direktif berbeda yang menguji kondisi yang berbeda-beda. Berikut adalah tabelnya:
ifeq (arg1, arg2)ifeq 'arg1' 'arg2'ifeq ‘arg1’ ‘arg2’ifeq ‘arg1’ 'arg2'ifeq 'arg1' ‘arg2’Lakukan ekspansi pada semua referensi variabel dalam arg1 dan arg2, lalu bandingkan keduanya. Jika keduanya identik, text-if-true yang berlaku; jika tidak, text-if-false (jika ada) yang berlaku.
Sering kali Anda ingin menguji apakah suatu variabel memiliki nilai yang tidak kosong. Ketika nilainya berasal dari ekspansi variabel dan fungsi yang kompleks, hasil ekspansi yang menurut Anda kosong sebenarnya bisa saja mengandung karakter whitespace sehingga tidak dianggap kosong. Namun, Anda dapat menggunakan fungsi strip (lihat Fungsi untuk substitusi dan analisis string) untuk menghindari penafsiran whitespace sebagai nilai yang tidak kosong. Misalnya, Anda dapat menulis:
ifeq ($(strip $(foo)),) text-if-empty endif
Dengan cara ini, text-if-empty akan dievaluasi meskipun hasil ekspansi $(foo) mengandung karakter whitespace.
ifneq (arg1, arg2)ifneq 'arg1' 'arg2'ifneq ‘arg1’ ‘arg2’ifneq ‘arg1’ 'arg2'ifneq 'arg1' ‘arg2’Lakukan ekspansi pada semua referensi variabel dalam arg1 dan arg2, lalu bandingkan keduanya. Jika keduanya berbeda, text-if-true yang berlaku; jika tidak, text-if-false (jika ada) yang berlaku.
ifdef variable-name
Bentuk ifdef mengambil nama suatu variabel sebagai argumennya, bukan referensi ke variabel. Jika nilai variabel tersebut tidak kosong, text-if-true yang berlaku; jika tidak, text-if-false (jika ada) yang berlaku. Variabel yang belum pernah didefinisikan memiliki nilai kosong. Teks variable-name diekspansi, sehingga bisa saja berupa variabel atau fungsi yang diekspansi menjadi nama suatu variabel. Misalnya:
bar = true foo = bar ifdef $(foo) frobozz = yes endif
Referensi variabel $(foo) diekspansi sehingga menghasilkan bar, yang dianggap sebagai nama suatu variabel. Variabel bar sendiri tidak diekspansi, tetapi nilainya diperiksa untuk menentukan apakah tidak kosong.
Perhatikan bahwa ifdef hanya menguji apakah suatu variabel memiliki nilai. Direktif ini tidak mengekspansi variabel untuk melihat apakah nilai tersebut tidak kosong. Akibatnya, pengujian dengan ifdef menghasilkan benar untuk semua definisi kecuali definisi seperti foo =. Untuk menguji nilai kosong, gunakan ifeq ($(foo),). Misalnya, jika Anda menulis:
bar = foo = $(bar) ifdef foo frobozz = yes else frobozz = no endif
‘frobozz’ akan ditetapkan menjadi ‘yes’. Sementara itu, jika Anda menulis:
foo = ifdef foo frobozz = yes else frobozz = no endif
‘frobozz’ akan ditetapkan menjadi ‘no’.
ifndef variable-name
Jika variabel variable-name memiliki nilai kosong, text-if-true yang berlaku; jika tidak, text-if-false (jika ada) yang berlaku. Aturan ekspansi dan pengujian untuk variable-name sama persis dengan direktif ifdef.
Spasi tambahan diperbolehkan dan diabaikan di awal baris direktif kondisional, tetapi tab tidak diperbolehkan. (Jika baris dimulai dengan tab, baris tersebut akan dianggap sebagai bagian dari resep suatu aturan.) Selain itu, spasi atau tab tambahan dapat disisipkan tanpa efek apa pun di mana saja, kecuali di dalam nama direktif atau di dalam argumen. Komentar yang dimulai dengan ‘#’ boleh muncul di akhir baris.
Dua direktif lain yang berperan dalam kondisional adalah else dan endif. Keduanya ditulis sebagai satu kata saja, tanpa argumen. Spasi tambahan diperbolehkan dan diabaikan di awal baris, dan spasi atau tab juga boleh diletakkan di akhir baris. Komentar yang dimulai dengan ‘#’ boleh muncul di akhir baris.
Kondisional memengaruhi baris makefile mana yang digunakan oleh make. Jika kondisinya benar, make akan membaca baris-baris text-if-true sebagai bagian dari makefile; jika kondisinya salah, make akan mengabaikan baris-baris tersebut sepenuhnya. Dari sini dapat disimpulkan bahwa unit sintaksis makefile, seperti aturan, dapat dengan aman dipecah melewati awal atau akhir kondisional.
make mengevaluasi kondisional saat membaca makefile. Oleh karena itu, Anda tidak dapat menggunakan variabel otomatis dalam pengujian kondisional, karena variabel otomatis baru didefinisikan setelah resep dijalankan (lihat Variabel otomatis).
Untuk mencegah kebingungan yang tak tertanggulangi, tidak diperbolehkan memulai suatu kondisional pada satu makefile dan mengakhirinya pada makefile lain. Namun, Anda boleh menulis direktif include di dalam suatu kondisional, asalkan Anda tidak mencoba mengakhiri kondisional tersebut di dalam file yang disertakan.
Anda dapat menulis kondisional yang menguji flag perintah make seperti ‘-t’ dengan menggunakan variabel MAKEFLAGS bersama fungsi findstring (lihat Fungsi untuk substitusi dan analisis string). Ini berguna ketika touch saja tidak cukup untuk membuat file tampak mutakhir.
Perlu diingat bahwa MAKEFLAGS akan menggabungkan semua opsi satu huruf (seperti ‘-t’) ke dalam kata pertama, dan kata tersebut akan kosong jika tidak ada opsi satu huruf yang diberikan. Untuk mengatasi hal ini, akan membantu jika Anda menambahkan suatu nilai di awal agar selalu ada kata yang tersedia, misalnya ‘-$(MAKEFLAGS)’.
Fungsi findstring menentukan apakah suatu string muncul sebagai bagian dari string lain. Jika Anda ingin menguji flag ‘-t’, gunakan ‘t’ sebagai string pertama dan kata pertama dari MAKEFLAGS sebagai string yang lain.
Misalnya, berikut ini cara mengatur agar ‘ranlib -t’ digunakan untuk menyelesaikan penandaan sebuah file arsip (archive) sebagai mutakhir:
archive.a: …
ifneq (,$(findstring t,$(firstword -$(MAKEFLAGS))))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
Awalan ‘+’ menandai baris-baris resep tersebut sebagai “rekursif”, sehingga baris-baris tersebut akan tetap dijalankan meskipun flag ‘-t’ digunakan. Lihat Penggunaan rekursif make.