Haberler:

Foruma üye olmak ÜCRETSİZDİR!

Ana Menü

GCC ve Kodun Derlenme Süreci

Başlatan hamza, Ağu 04, 2026, 03:54 ÖS

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

hamza

Uzun süredir C dilleri ile haşır neşirim. Programlama serüvenim ilk olarak Basic ile başlasa da zamanla C diline evrildi.

C ailesine aşık olmamı sağlayan en büyük olgulardan birisi, dillerin donanıma doğrudan erişim imkanı vermesi. Peki, yazdığımız o yalın C kodlarının işlemcinin anlayacağı sıfırlara ve birlere dönüşmesini sağlayan, bu donanım erişimini bize yüksek başarım ve performansla sunan şey ne? Doğru, derleyiciler :)

Bir C kodunun işletim sistemi (OS) ve donanım mimarisiyle buluşma serüveni kullanılan derleyicinin zekası kadardır. İyi bir derleyicin varsa kodun bir o kadar optimize olarak derlenir ve verim de bu ölçüde artar.

Peki derleyici arkaplanda ne iş yapar?
  • Preprocessing
  • Compilation
  • Assembly
  • Linking

Preprocessing yani ön işleme kısmında yazılan makrolar çözümlenir. (Bknz. #include, #define gibi) Ayrıca yazılan yorum satırları da trimleniyor ki alandan tasarruf kazanalım. GCC kullanıyorsak -E flag'i ile preprocessing işleminin çıktısını .i uzantılı bir dosya ile alabiliriz:
gcc -E main.c -o preprocessing.i
Tamam trimledik, temizledik. Şimdi? Derleme aşamasına geçiyoruz burada yazılan kodlar hedef işlemci mimarisinin assembly diline çevriliyor. Yine assembly çıktısı için:
gcc -S main.c -o compilation.s
Şimdi assembly kodunun ikili nesne koduna dönüşüm işlemi var. Bu adım assembly adımı. .o uzantılı dosyalarla bu adımda tanışıyoruz. Çıktı için:
gcc -c main.c -o obj.o
Son adımda bu .o dosyaları link edilerek yani bağlanarak tek bir .exe çıktısı üretiliyor ve derleme işlemi bitiyor.

Tabii bir de bu işin compilation flags kısmı var. Bayraklar yani. Bu bayraklarla kodun derlendiği makineye özgü ya da hedef makinenin işlemcisine göre bazı optimizasyonlar yaptırabiliyoruz. Ne gibi?

  • -O0: Hiçbir optimizasyon yapılmaz. Kod yazdığınız sırayla birebir makine diline dönüştürülür. Hata ayıklama (debugging / GDB) aşaması için idealdir. Satır satır koda müdahale edebilirsiniz.
  • -O2: Kod production'a çıkacaksa genelde en sık tercih edilen flag. Kod boyutunu devasa boyutlara çıkarmadan güvenli tüm optimizasyonları uygular.
  • -O3 ve en sevdiğim.. : Agresif optimizasyon seviyesi. Döngüleri açar (Loop Unrolling), fonksiyonları yerine gömer (Inlining) ve SIMD/Vektörizasyon talimatlarını sonuna kadar zorlar. Kod boyutu büyüyebilir ancak execution (çalışma) hızı hissedilir derecede artar. Satranç motorum için bu flag hayati bir önem taşıyor.
  • -Os: Kodu performans yerine dosya boyutunu küçültmek için optimize eder. Kısıtlı hafızaya sahip gömülü sistemlerde kullanılır.
  • -Ofast: -O3'ün üzerine -ffast-math ekliyor. Bunun yaptığı şey hız kazandırıyor ama hassas matematik hesaplarının yapıldığı bir kod varsa sapmalara sebep veriyor. Çok önermiyorum.
  • -march=native: Derlenen makinenin işlemcisinin desteklediği tüm mimarileri kullan diyoruz GCC'ye. AVX2, FMA, SSE gibi.
  • -flto: Bu da link time optimization flag'i. Kullanmakta fayda var.

GCC ile örnek derleme:
# Sıfır optimizasyon + debug
gcc -O0 -g main.c -o debug

# Agresif optimizasyon + işlemcinin desteklediği her şeyi kullan + link-time optimizasyon
gcc -O3 -march=native -flto main.c -o prod-release

GCC dışında başka C derleyicileri de mevcut ama Linux camiasının tartışmasız en sağlam derleyicisi GCC'dir. Bu hem kişisel yorumdur hem de değildir, bence öyledir, öyle olmak da zorundadır :)