Emacs ile CMake ve LLDB kullanmak
Düzenlendi · Kapsam: GNU Emacs 29+ üzerinde Eglot, project.el, compile ve dape ile modern C++ ve lldb-dap hata ayıklama.
Emacs üzerinde C++ geliştirme deneyimi, son yıllarda yerleşik LSP istemcisi eglot,
proje yöneticisi project.el ve Debug Adapter Protocol (DAP) istemcisi dape sayesinde
büyük bir dönüşüm geçirdi. Artık onlarca harici eklenti (lsp-mode, treemacs, hydra,
dap-mode) kurmadan, hafif ve yerleşik kütüphanelerle modern bir IDE deneyimi elde etmek mümkündür.
Bu kılavuzda CMake tabanlı bir C++ projesini Emacs içinde yapılandırmayı, derlemeyi ve
LLVM 18+ ile gelen lldb-dap aracılığıyla görsel olarak hata ayıklamayı (debugging)
ele alacağız.
1. Neden dape ve lldb-dap?
Geçmişte Emacs’te hata ayıklama için iki temel yol bulunuyordu:
- GUD (
gud-lldb/gud-gdb): Emacs’in 30 yıllık terminal tabanlı arayüzüdür. LLDB çıktısını düzenli ifadelerle (regex) ayrıştırmaya çalıştığı için kararsızdır; modern nesne ağaçlarını, değişken izlemeyi ve karmaşık yığınları desteklemez. dap-mode: VS Code hata ayıklama protokolünü Emacs’e getirdi ancaklsp-modeekosistemine sıkı sıkıya bağlıdır ve oldukça ağırdır.
dape (Debug Adapter Protocol for Emacs):
- Emacs 29+ ile gelen yerleşik
eglotveproject.elile tam uyumludur; harici bir LSP paketine ihtiyaç duymaz. - GDB-MI tarzı temiz, çok pencereli bir bilgi paneli (
*dape-info*) açar: İş parçacıkları (threads), çağrı yığını (stack trace), yerel değişkenler, izleme listesi (watch) ve breakpoint listesi. - Kaynak kodun içine doğrudan satır içi değişken değerlerini yazar (
inlay hints). repeat-modedesteğiyle tek bir tuşla (n,s,c,o) hızlı adımlama sağlar.
[!NOTE] LLVM 18 sürümüyle birlikte
lldb-vscodearacının adı protokolün evrenselliğini vurgulamak için resmenlldb-dapolarak değiştirilmiştir.
2. Emacs yapılandırması (init.el)
Aşağıdaki yapılandırmayı ~/.emacs.d/init.el veya ~/.config/emacs/init.el dosyanıza ekleyin:
;;; init.el --- Modern C++, CMake ve LLDB Yapılandırması
(require 'use-package)
(setq use-package-always-ensure t)
;; -------------------------------------------------------------
;; 1. Dil Sunucusu (Yerleşik Eglot + Clangd)
;; -------------------------------------------------------------
(use-package eglot
:ensure nil ; Emacs 29 ile yerleşiktir
:hook
((c-mode c++-mode c-ts-mode c++-ts-mode) . eglot-ensure)
:config
(add-to-list 'eglot-server-programs
'((c-mode c++-mode c-ts-mode c++-ts-mode)
. ("clangd"
"--background-index"
"--clang-tidy"
"--completion-style=detailed"
"--header-insertion=iwyu"))))
;; -------------------------------------------------------------
;; 2. Proje ve Derleme (Yerleşik project.el & compile)
;; -------------------------------------------------------------
(use-package project
:ensure nil
:config
;; Git deposu olmasa dahi CMakeLists.txt bulunan dizini proje kökü say
(add-to-list 'project-vc-extra-root-markers "CMakeLists.txt"))
(use-package compile
:ensure nil
:custom
;; Her defasında sormadan doğrudan son derleme komutunu çalıştır
;; Komutu değiştirmek istediğinizde C-u M-x compile yapabilirsiniz
(compilation-read-command nil)
(compilation-scroll-output 'first-error)
(compilation-always-kill t)
:bind
(("C-c c" . compile)
("C-c r" . recompile)))
;; -------------------------------------------------------------
;; 3. Modern Hata Ayıklama (dape + lldb-dap)
;; -------------------------------------------------------------
(use-package dape
:preface
(setq dape-buffer-window-arrangement 'gdb)
:config
;; Adımlama sırasında tek tuş kullanımını etkinleştir (n, s, c, o)
(repeat-mode 1)
;; Kod içinde değişken değerlerini satır sonunda göster
(setq dape-inlay-hints t)
;; lldb-dap yapılandırmasını özelleştir
(with-eval-after-load 'dape
(add-to-list 'dape-configs
`(lldb-cpp
modes (c-mode c++-mode c-ts-mode c++-ts-mode)
command "lldb-dap"
:type "executable"
:request "launch"
:cwd dape-cwd-fn
:program (lambda ()
(read-file-name "İkili dosya seçin: "
(expand-file-name "build/" (dape-cwd))))
:args []
:stopOnEntry nil)))
:bind
(("C-x C-a d" . dape)
("C-x C-a b" . dape-breakpoint-toggle)
("C-x C-a c" . dape-breakpoint-expression)
("C-x C-a r" . dape-repl)
("C-x C-a i" . dape-info)))
3. Proje düzeyinde CMake ve Clangd ayarları
Clangd dil sunucusunun ve Emacs derleme komutunun projeyi tanıması için proje köküne
.dir-locals.el ekleyebilirsiniz:
((nil . ((compile-command . "cmake --build build -j")
(project-compilation-buffer-name-function . project-prefixed-buffer-name)))
(c++-mode . ((eglot-workspace-configuration
. (:clangd (:compilationDatabasePath "build"))))))
CMake yapılandırmanızda derleme veritabanını (compile_commands.json) üretmeyi unutmayın:
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
4. Hata ayıklama iş akışı
Örnek bir C++ programında adım adım hata ayıklama süreci:
1. Adım: Derleme
Kaynak dosya açıkken C-c c (compile) veya C-x p c (project-compile) tuşlayın.
Derleme çıktısı *compilation* penceresinde akar. Hata varsa C-x \ (next-error`) ile
hatalı satıra atlayabilirsiniz.
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build -j
[!IMPORTANT] Hata ayıklama sembollerinin tam görünmesi için projenin Debug veya RelWithDebInfo modunda derlenmiş olması gerekir.
2. Adım: Breakpoint (Kesme Noktası) Koyma
Kaynak kodda duraklamak istediğiniz satıra gelin:
C-x C-a b(dape-breakpoint-toggle): O satıra kesme noktası koyar. Satır başında kırmızı bir gösterge belirir.C-x C-a c(dape-breakpoint-expression): Koşullu kesme noktası ekler (örneğin döngü sayacıi == 100olduğunda dur).
3. Adım: Dape Oturumunu Başlatma
C-x C-a d(dape) tuşlayın.- Minibuffer’da
lldb-cppyapılandırmasını seçin. - İkili dosya yolu sorulduğunda
build/uygulamadosyasını onaylayın.
Emacs otomatik olarak pencereleri yeniden düzenler (gdb düzeni):
- Sol üstte kaynak kodunuz.
- Sağ üstte çağrı yığını (Stack) ve iş parçacıkları (Threads).
- Sağ altta yerel değişkenlerin anlık değerleri (Locals).
- Alt kısımda etkileşimli LLDB komut satırı (
*dape-repl*).
4. Adım: Değişkenleri İnceleme ve Adımlama
Program breakpoint satırında durduğunda:
- Satır İçi Değerler: Değişkenlerin güncel değerleri doğrudan kodun sağında silik metin olarak görünür.
- İzleme (Watch):
*dape-info*penceresindeituşuna basarak özel bir ifadeyi (örneğindizi.size()) sürekli izlemeye alabilirsiniz. - Tek Tuşla Adımlama (
repeat-mode): İlk adımdan sonra ön ek tuşuna basmadan sadece tek harflere basarak ilerleyin:n: Sonraki satıra geç (Step Over / Next)s: Fonksiyonun içine gir (Step Into)o: Fonksiyondan çık (Step Out)c: Bir sonraki kesme noktasına kadar devam et (Continue)r: Programı baştan başlat (Restart)q: Hata ayıklama oturumunu kapat (Quit)
5. Adım: LLDB REPL Kullanımı
Özel bir bellek adresini dökmek veya C++ ifadesi çalıştırmak istediğinizde *dape-repl*
penceresine geçin:
p my_vector.size()
expr my_vector.push_back(42)
x/16xb pointer_address
Kaynaklar ve doğrulama ortamı
Bu kılavuz, macOS Sonoma 14 ve Ubuntu 24.04 üzerinde GNU Emacs 29.4, Clang 18 (lldb-dap),
Eglot ve dape 0.19 ile test edilerek doğrulanmıştır.