Makefile ile Proje Otomasyonu
Terminalde her gün aynı üç dört komutu yazıyorsan, o komutlar aslında projenin dokümantasyonudur. Ama kafanda tuttuğun dokümantasyon kimseye yaramaz. Makefile tam burada devreye girer: proje kökünde duran tek bir dosya, "bu projede ne yapılır" sorusunun cevabını verir.
Make eski bir araç. Tam da bu yüzden her yerde var. Node, Python, Go, Rust, PHP — dili ne olursa olsun make build yazan biri ne olacağını bilir. Yeni bir görev koşucusu öğrenmek zorunda kalmaz.
Temelleri Doğru Kurmak
Makefile'ın mantığı üç parçadan oluşur: hedef (target), bağımlılıklar (prerequisites) ve tarif (recipe). Hedef iki nokta üst üste ile yazılır, bağımlılıklar aynı satırda listelenir, komutlar bir alt satıra TAB ile girintili yazılır.
İlk kuralı hemen not et: girinti boşluk olamaz. Sekme karakteri olmak zorunda. VS Code kullanıyorsan Makefile için sekme ayarını sabitle, yoksa "missing separator" hatasıyla yarım saat kaybedersin.
İlk Makefile'ını Yazmak
Dosya adı büyük M ile Makefile. Proje kökünde durur. Başlangıç için tipik hedefler:
| Hedef | Ne yapar |
|---|---|
| install | Bağımlılıkları kurar |
| build | Derleme veya bundle çıkarır |
| test | Test süitini koşar |
| lint | Statik analiz ve format kontrolü |
| run | Uygulamayı lokalde ayağa kaldırır |
| clean | Üretilen dosyaları siler |
Bir hedefin tarifinde birden çok komut varsa her satır ayrı bir kabukta çalışır. Yani cd klasor yazıp alt satırda komut vermek işe yaramaz. Ya iki komutu && ile aynı satıra al, ya da satır sonuna ters eğik çizgi koyup birleştir.
.PHONY, Değişkenler ve Varsayılan Hedef
Make aslında dosya üretmek için tasarlandı. build adında bir hedef varsa ve klasörde build diye bir dizin de varsa, Make "bu zaten güncel" der ve hiçbir şey yapmaz. Çözüm: bu tür hedefleri .PHONY listesine ekle. Dosya üretmeyen her hedefi oraya yaz — install, test, lint, run, clean, deploy.
Değişkenler tekrarı bitirir. Docker imaj adı, Python yorumlayıcısı, port numarası, sürüm etiketi — hepsini üstte tanımla, aşağıda süslü parantezle çağır. Değişkeni ?= ile tanımlarsan ortam değişkeniyle dışarıdan ezilebilir hale gelir. Bu, CI ortamında çok işine yarar.
Dosyadaki ilk hedef varsayılandır. Sadece make yazınca ne olacağını sen seç. En iyi tercih genelde bir yardım hedefi: mevcut komutları listeleyen bir çıktı. Böylece projeye yeni katılan biri dosyayı açmadan ne yapabileceğini görür.
Sık Yapılan Üç Hata
- Sessiz olmayan komutlar. Make her komutu ekrana basar. İstemediğin satırın başına @ koy. Yardım metinlerinde şart.
- Hata yutmak. Bir komut hata verirse Make durur, bu iyidir. Durmasını istemediğin nadir durumda satır başına - koy — ama bunu bilinçli yap.
- Aşırı soyutlama. Makefile bir programlama dili değil. İç içe koşullar ve döngüler yığmaya başladıysan o mantığı ayrı bir bash script'e taşı, Makefile o script'i çağırsın.
Gerçek Bir İş Akışı Kurmak
Temel hedefler oturduktan sonra sıra zinciri kurmaya gelir. Amacın şu: yeni gelen biri depoyu klonlasın, make yazsın, çalışan bir ortama kavuşsun.
Bağımlı Hedeflerle Zincir
Hedefler birbirini bağımlılık olarak alabilir. test hedefi install'a bağlı olsun, deploy hedefi test ve build'e bağlı olsun. Böylece test geçmeden deploy edilemez. Bu kural bir insanın hatırlamasına bırakılmaz, dosyaya yazılır.
Bağımlılık sırası önemli değildir, hepsi hedeften önce koşar. Paralel çalıştırmak istersen make -j4 kullanabilirsin, ama hedefler birbirinin dosyalarına dokunuyorsa buna girme.
Docker ve Ortam Değişkenleriyle Birleştirme
Container kullanan projelerde Makefile en çok işe yaradığı yerdir. Uzun docker komutlarını kimse ezberlemek istemez. İmaj adı ve etiketi değişken yap, up, down, logs, shell gibi kısa hedefler tanımla. Veritabanına bağlanmak için make db yeterli olsun.
Gizli bilgileri Makefile'a yazma. Bunun yerine .env dosyasını dahil et ve dosyayı sürüm kontrolünün dışında tut. Örnek olarak .env.example bırak, make setup hedefi onu kopyalasın.
CI ile Aynı Komutları Paylaşmak
En büyük kazanç burada. CI yapılandırmasına uzun komut listeleri yazmak yerine sadece hedefleri çağır: lint, test, build. Böylece lokalde geçen şey CI'da da geçer. Bir komut değişince tek bir dosyayı güncellersin, iki yeri değil.
Deploy hedefinde küçük bir güvenlik önlemi al: hangi ortama gidileceğini değişkenden oku ve varsayılanı staging yap. Prod için ayrı, açıkça yazılması gereken bir hedef bırak.
Hızlı Kontrol Listesi
- Makefile proje kökünde mi?
- Girintiler sekme mi?
- Dosya üretmeyen hedefler .PHONY'de mi?
- Varsayılan hedef yardım çıktısı veriyor mu?
© 2026 Yazılım Atölyesi