---
title: 'Paket Yönetimi ve Derleme Araçları'
source: 'https://academia.sh/tr/kurslar/cpp-sablonlar/paket-yonetimi-ve-derleme-araclari'
course: 'Şablonlar ve Başarım'
language: tr
updated: '2026-10-21T05:02:46+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir başlık değiştiğinde hangi çeviri birimlerinin yeniden derlendiğini bağımlılık tablosundan okur.'
    - 'Sürüm aralığı ile kilit dosyasının aynı kurulumu nasıl yeniden üretilebilir kıldığını açıklar.'
    - 'Yalnız başlıktan oluşan bir şablon kütüphanesinin derleme bedelini derlenmiş bir kütüphaneyle karşılaştırır.'
---

# Paket Yönetimi ve Derleme Araçları

Bağımlılık tablosu, sürüm sabitleme ve kilit dosyasıyla yeniden üretilebilir kurulum; yalnız başlıktan oluşan şablon kütüphanesinin her birimi yeniden derletmesi.

Önceki ders, bir başlığın görünürlüğünü azaltmanın bedelini nesne başına ayırmaya
taşıdığını gösterdi, ama kazanılan derleme süresini tahminle anlattı. Bu ders o tahmini
bir sayıya çeviriyor: değişen bir başlık kaç birimi yeniden derletiyor? Aynı soru bir
projenin dışarıdan getirdiği kütüphaneler için de sorulur; çünkü bir kütüphane de
sonunda birkaç başlıktır. Süre basılmaz. Ölçülen sayı, bir değişikliğin yeniden derlettiği
**çeviri birimi** sayısıdır. M10/K03'ten bir ayrım: sayı ölçünün kendisi değil, kanıt
aracıdır. Burada da sayı sınıflandırmanın kanıtıdır; ölçü sorusunun yanıtı bir sınıf
adıdır ve bu dersin yanıtı **derleme**dir.

## Bağımlılık Tablosu

Bir **derleme sistemi** işini tek bir tabloya dayandırır: her birim hangi başlıkları
içeriyor? Bir dosya değişince, o dosyayı içeren birimler eskimiş sayılır; ötekilere
dokunulmaz. Sistemin adı ve yapılandırma dili bu dersin konusu değil, tablonun kendisi
konusu. Tabloyu sade C++ ile kurabiliriz: birim adı ve içerdiği başlıkların listesi.

```cpp
// bagimlilik.hpp — birim ve icerdigi basliklar tablosu
#pragma once
#include <string>
#include <vector>

struct Birim {
    std::string ad;
    std::vector<std::string> basliklar;
};

inline int yeniden(const std::vector<Birim>& birimler, const std::string& degisen) {
    int sayi = 0;
    for (const auto& b : birimler) {
        if (b.ad == degisen) {
            ++sayi;
            continue;
        }
        for (const auto& h : b.basliklar) {
            if (h == degisen) {
                ++sayi;
                break;
            }
        }
    }
    return sayi;
}
```

`yeniden` her birime bakar. Birimin kendi kaynağı değiştiyse onu sayar; değilse başlık
listesinde değişen dosyayı arar ve ilk eşleşmede durur. Aynı başlık bir birimde iki kez
geçse bile birim bir kez sayılır, çünkü bir birim bir kez derlenir. Dolaylı içermeler de
tabloya yazıldığı sürece bu sayıma girer; bir başlığın getirdiği başlık, listeye yazılmış
başlıktan farksızdır.

## Sürüm Sabitleme ve Kilit Dosyası

Dışarıdan gelen bir kütüphaneyi bir **paket yöneticisi** getirir. Projenin ona bağımlılığı
bir sürüm aralığıyla yazılır: "1.0.0 dahil, 2.0.0 hariç". Aralık bir söz verir, tek bir
sürümü göstermez. Kayıt yeni bir sürüm yayımladığında aynı aralık başka bir sürüme çözülür.
**Sürüm sabitleme** bu kaymayı keser: çözülen sürüm bir **kilit dosyası**na yazılır ve
sonraki kurulumlar aralığı yeniden çözmek yerine kilitteki sürümü kullanır.

Bir ayrım gerekiyor. Kilit dosyası, bu kursun eşzamanlılık bölümündeki dışlama kilidiyle
yalnızca adı paylaşır.
Dışlama kilidi çalışan iş parçacıklarını sıraya sokar; kilit dosyası ise diskte duran
bir kayıttır ve hiçbir şeyi engellemez, yalnızca hangi sürümün kurulduğunu hatırlar.

```cpp
// surum.hpp — surum araligi ve kilit dosyasi modeli
#pragma once
#include <map>
#include <string>
#include <vector>

// Surum 130, 1.3.0 olarak kodlanir; kayit yayimlanmis surumlerin listesidir.
inline int coz(const std::vector<int>& kayit, int alt, int ust) {
    int secilen = -1;
    for (int s : kayit) {
        if (s >= alt && s < ust && s > secilen) secilen = s;
    }
    return secilen;
}

using KilitDosyasi = std::map<std::string, int>;

inline int kur(const KilitDosyasi& kilit, const std::string& paket,
               const std::vector<int>& kayit, int alt, int ust) {
    auto it = kilit.find(paket);
    if (it != kilit.end()) return it->second;
    return coz(kayit, alt, ust);
}
```

`coz` aralıktaki en yüksek sürümü seçer. `kur` önce kilide bakar; paket kilitteyse
aralığı hiç çözmez. Kilit boşsa kurulum aralığa güvenir ve sonucu kaydın o anki haline
bağlar. **Yeniden üretilebilir kurulum** bu farka dayanır: kilitteki sürüm kayıtta durduğu
sürece, aynı kilit dosyası kayıt değişse de aynı sürümü verir.

## Yalnız Başlıktan Oluşan Kütüphane

Bir şablon kütüphanesi çoğu zaman **yalnız başlıktan oluşan kütüphane**dir (header-only
library). Sebebi kursun ilk dersinde görüldü: derleyici şablonu her kullanım yerinde tipi
yerine
koyarak üretir, bu yüzden gövde kullanan her birimde görünür olmak zorundadır. Her tip
için ayrı gövde üretilir ve bu üretim, o başlığı içeren her birimin derleme süresine
yazılır. Gövde başlıkta durduğu için kütüphanenin içindeki bir değişiklik, başlığı
içeren birimlerin hepsini eskitir.

Derlenmiş bir kütüphane başka bir düzen kurar. Başlık yalnızca arayüzü bildirir; gövde
tek bir `.cpp` dosyasında durur. Gövdedeki değişiklik tek birimi yeniden derletir.
Ancak bu düzen, önceki dersin açık somutlaştırmasındaki gibi yalnızca önceden seçilmiş
tipler için çalışır. Her tipe açık bir kütüphane, şablon olmaktan çıkar.

```cpp
// olcum.cpp — degisen baslik kac birimi yeniden derletiyor
#include <iostream>

#include "bagimlilik.hpp"
#include "surum.hpp"

int main() {
    std::vector<Birim> birimler = {
        {"giris.cpp", {"ortak.hpp"}},
        {"hesap.cpp", {"ortak.hpp"}},
        {"rapor.cpp", {"ortak.hpp", "ozel.hpp"}},
    };
    std::cout << "degisen baslik derleme ortak=" << yeniden(birimler, "ortak.hpp")
              << " ozel=" << yeniden(birimler, "ozel.hpp") << "\n";

    std::vector<int> kayit = {100, 110, 130};
    KilitDosyasi kilit;
    int ilk = kur(kilit, "sayac", kayit, 100, 200);
    kilit["sayac"] = ilk;
    kayit.push_back(140);
    kayit.push_back(210);
    int kilitsiz = kur(KilitDosyasi{}, "sayac", kayit, 100, 200);
    int kilitli = kur(kilit, "sayac", kayit, 100, 200);
    std::cout << "surum sabitleme ilk=" << ilk << " kilitsiz=" << kilitsiz
              << " kilitli=" << kilitli << "\n";

    std::vector<Birim> yalniz = {
        {"giris.cpp", {"ortak.hpp", "kutuphane.hpp"}},
        {"hesap.cpp", {"ortak.hpp", "kutuphane.hpp"}},
        {"rapor.cpp", {"ortak.hpp", "ozel.hpp", "kutuphane.hpp"}},
        {"cizim.cpp", {"kutuphane.hpp"}},
    };
    std::vector<Birim> derlenmis = {
        {"giris.cpp", {"ortak.hpp", "arayuz.hpp"}},
        {"hesap.cpp", {"ortak.hpp", "arayuz.hpp"}},
        {"rapor.cpp", {"ortak.hpp", "ozel.hpp", "arayuz.hpp"}},
        {"cizim.cpp", {"arayuz.hpp"}},
        {"kutuphane.cpp", {"arayuz.hpp"}},
    };
    std::cout << "yalniz baslik govde=" << yeniden(yalniz, "kutuphane.hpp")
              << " derlenmis govde=" << yeniden(derlenmis, "kutuphane.cpp")
              << " arayuz=" << yeniden(derlenmis, "arayuz.hpp") << "\n";
    return 0;
}
```

```text
degisen baslik derleme ortak=3 ozel=1
surum sabitleme ilk=130 kilitsiz=140 kilitli=130
yalniz baslik govde=4 derlenmis govde=1 arayuz=5
```

**EB30.** İlk satır bağımlılık tablosunun sonucudur: `ortak.hpp` değişince üç birimin üçü
de yeniden derlenir (`ortak=3`), `ozel.hpp` değişince yalnızca `rapor.cpp` (`ozel=1`).
Aynı kod tabanında iki başlığın bedeli üçe bir farkla ayrışır; fark başlığın büyüklüğünden
değil, kaç birimin onu içerdiğinden gelir.

**EB31.** İkinci satırda `ilk=130`: kayıt henüz `100`, `110` ve `130` sürümlerini taşırken
aralık `130`'a çözüldü ve sonuç kilide yazıldı. Kayda `140` ve aralığın dışında kalan
`210` eklendi. Kilitsiz kurulum `140`'ı seçti (`kilitsiz=140`), çünkü `210` aralıkta
değil; kilitli kurulum hâlâ `130` verdi (`kilitli=130`).

**EB32.** Yukarıdaki iki kurulum aynı projenin iki koşumudur ve arada tek fark kaydın
değişmesidir. Kilitli olan değişmedi, kilitsiz olan kaydı. Bu çıktı sürüm numarasının
kendisini değil, aralığın kaymasını gösterir; `130` ve `140` yalnızca modelin
kodlamasıdır.

**EB33.** Üçüncü satırda yalnız başlıktan oluşan kütüphanenin gövdesi değişince dört
birimin dördü yeniden derlenir (`govde=4`). Derlenmiş kütüphanede aynı gövde değişikliği
tek birimi, `kutuphane.cpp`'yi eskitir (`govde=1`).

**EB34.** `arayuz=5`: derlenmiş kütüphanenin yalnızca bildirimleri taşıyan başlığı
değişirse, onu içeren dört birimin yanında `kutuphane.cpp` de yeniden derlenir. Derlenmiş
düzen gövde değişikliğini tek birime indirir, arayüz değişikliğini indirmez.

**EB35.** Dört ve beş birimlik tablolar kurulumdan çıkar, ölçülen bir derleme değildir.
Sayı, tabloya yazdığımız içermelere bağlıdır; gerçek bir projede dolaylı içermeler eksik
yazılırsa sayı olduğundan küçük çıkar. Model bu yüzden bir sayım örneğidir, derleme süresi
hakkında bir şey söylemez.

## Sınırlayıcı Ölçüm

Bu dersin ölçtüğü düzenek, değişen bir başlığın yeniden derlettiği birim sayısıdır. Sınır,
yalnız başlıktan oluşan şablon kütüphanesindedir. Kütüphane bir şablon taşıdığında gövdesi
başlıkta durmak zorundadır ve onu içeren **her** birim gövdeyi kendi içinde yeniden
üretir. Kütüphanenin gövdesinde yapılan en küçük değişiklik de bu yüzden dört birimin
dördünü eskitir: `govde=4`. Derlenmiş kütüphanede aynı değişiklik `govde=1` verir.

Yani şablonun bedeli, kursun başında görülen gövdenin her birimde görünmesi, derlemeye
geri döner. Şablon kullanıcıya her tip için çalışma özgürlüğü verir; karşılığında gövde
başlıkta kalır ve her değişiklik içeren birimlerin sayısıyla çarpılır. Her kütüphaneyi
derlenmiş hâle getirmek genel bir çözüm değildir, çünkü derlenmiş düzen şablonun tipten
bağımsızlığını yalnızca açık somutlaştırılan tiplerle sınırlar. Seçim, bir ödünleşimdir:
gövde sık değişiyor ve başlık çok birime görünüyorsa derlenmiş düzen kazandırır; gövde
nadiren değişiyorsa yalnız başlıktan oluşan düzenin sadeliği yeter.

Sayının yeri de önemlidir. `govde=4` bir ölçünün yanıtı değildir; yanıt, düzeneğin
**derleme** sınıfına girdiğidir. Sayı bu sınıflandırmanın kanıtıdır: bedel çalışan
programda değil, programı kurmadan önce ödeniyor. Bu dersin düzenekleri koşum, bellek ya
da bekleme sınıfında satır doğurmaz; hepsi derleme sınıfındadır.

## Özet

- Bu dersin ölçtüğü düzenek bedeli **derleme** sınıfına taşır: değişen bir başlık, onu
  içeren her birimi yeniden derletir.
- Bağımlılık tablosu `ortak=3 ozel=1` verdi: aynı projede iki başlığın bedeli, kaç birim
  tarafından içerildiğine göre ayrışır.
- Sürüm aralığı bir söz verir, kilit dosyası bir sürüm hatırlar: `kilitsiz=140` iken
  `kilitli=130`, yani yeniden üretilebilir kurulum kilide bağlıdır. Kilit dosyası dışlama
  kilidinden ayrıdır.
- Yalnız başlıktan oluşan kütüphane gövde değişince `govde=4` birimi eskitir; derlenmiş
  kütüphane `govde=1` eskitir, ama arayüz değişince `arayuz=5`.
- Şablonun bedeli, gövdenin her birimde görünmesi, derlemeye geri döner; derlenmiş düzen
  bunu ancak önceden seçilmiş tiplerle azaltabilir.

## Kurs Kapanışı

Bu kurs boyunca on iki düzeneği aynı soruyla ölçtük: bedel nereye ödeniyor? Aşağıdaki
tablo her dersin ölçtüğü düzeneği, bedelin gittiği yeri ve o dersin sınırlayıcı ölçümünü
özetliyor.

| Ders | Ölçülen düzenek | Bedel nereye | Sınırlayıcı ölçüm |
| --- | --- | --- | --- |
| Fonksiyon ve Sınıf Şablonları | Şablon somutlaştırma | **derleme** | `const int` argümanı yeni gövde doğurmaz |
| Şablon Özelleştirme | `bool` özelleştirmesi | **bellek** | Okuma başına iki adım: bedel koşuma döner |
| Değişken Sayıda Şablon Parametresi | Özyinelemeli paket açma | **derleme** | Yeni tip listesi yeni gövde doğurur |
| Tip Özellikleri | `if constexpr` ile seçim | **derleme** | `volatile` argümanla hesap koşuma geçer: `adim=10` |
| Aşırı Yükleme Çözümlemesi ve SFINAE | `void_t` ile algılama | **derleme** | Gövdedeki hata elenmez, derlemeyi durdurur |
| Statik Çok Biçimlilik | CRTP ile gönderim | **derleme** | Karışık koleksiyon `std::variant` ister |
| İş Parçacıkları ve Kilitler | Kilitli sayaç | **bekleme** | Yerel toplam kilit alımını 4'e indirir |
| Bellek Modeli | `release`/`acquire` yayını | **bekleme** | Her eleman atomik olursa eşgüdüm 1000 olur |
| Önbellek Dostu Veri Düzeni | Yalnız `x` alanı | **bellek** | Üç alan birlikte okununca tablo tersine döner: `aos=0/11` |
| Profilleme ve Karşılaştırmalı Ölçüm | Araçlı profil | **koşum** | Tembel tabloda ilk çağrı 110, ikinci 10 adım |
| Derleme Süresi Yönetimi | Gizleme deyimi | **koşum** | Taşıma 0, kopya 1 ayırma |
| Paket Yönetimi ve Derleme Araçları | Değişen başlık | **derleme** | Yalnız başlıktan oluşan kütüphane her birimi eskitir |

**6 derleme · 2 koşum · 2 bellek · 2 bekleme; derlemede ödenen 6, koşumda ödenen 6.** Bu
dağılım kursun başında kurulan çekirdeğin dağılımıyla birebir aynıdır: altı düzenek bedeli
derlemeye yazar, altısı programı çalıştırırken tahsil eder. Gövdenin her birimde
görünmesi, kursun ilk dersinde şablonun bedeliydi; bu derste aynı bedel değişen başlık
başına birim sayısı olarak geri geldi.

Bu ders M11'in son dersidir; M11 burada kapanır.
