İçeriğe atla
PaketMimari denetim: 5-7 iş günü içinde bağımsız inceleme ve adım adım geçiş planı
Blog

Kurulum: Rustup, Cargo ve İlk Proje

9 dk okuma
  • Rust
  • Node.js
  • TypeScript
Seri: Bölüm 1 · 1/12 bölüm yayındaRust’ı öğreniyorumTüm bölümler
İçindekiler

Önceki yazıda Rust’a neden başladığımı anlatmıştım: 1 GB belleğe sahip bir Orange Pi’de Node.js servisi bellek sızdırıyordu ve ben belirsizliği değil kontrolü seçmek istiyordum. Bu bölüm o kararın ilk somut adımı. Rust’ı bilgisayarıma kuruyorum, ilk projeyi açıyorum ve karşıma çıkan her aracı, yıllardır kullandığım Node.js araçlarının karşısına koyarak öğreniyorum.

Yazının sonunda şunlar elinizde olacak: çalışan bir Rust kurulumu, cargo run ile derlenip koşan ilk program ve kafanızda Node.js ile Rust araçları arasında bir eşleme tablosu. Dilin kendisine, yani değişkenlere, tiplere ve kontrol akışına bir sonraki bölümde giriyorum.

Önce harita: Node.js dünyasından Rust’a

Yeni bir dile başlarken en çok zamanımı alan şey dilin sözdizimi değil, etrafındaki araçlar oluyor. Hangi komut neyi yapıyor, dosyalar nereye gidiyor, bağımlılıklar nerede duruyor. Bu yüzden ilk işim, bildiğim dünyayla bir eşleme çıkarmak oldu:

Node.js tarafıRust tarafıNot
nvmrustupSürüm yöneticisi. Birden fazla araç zinciri kurup aralarında geçiş yaptırır.
noderustcBiri çalıştırır, öteki derler. Bu fark aşağıda önemli olacak.
npmcargoPaket yöneticisi, derleme aracı, test koşucusu ve proje iskeleti tek komutta.
package.jsonCargo.tomlProje tanımı ve bağımlılık listesi.
package-lock.jsonCargo.lockÇözümlenmiş bağımlılık sürümleri.
npm registrycrates.ioPaket deposu. Rust’ta pakete “crate” denir.
node_modulestarget/ ve ~/.cargo/registryDerleme çıktıları projede, indirilen kaynaklar kullanıcı klasöründe durur.
prettierrustfmtBiçimlendirici. Araç zinciriyle birlikte gelir.
eslintclippyLint aracı. O da araç zinciriyle birlikte gelir.
npm install -gcargo installKomut satırı aracı kurar.
ts-nodeyok, cargo runRust’ta “derlemeden çalıştırma” diye bir şey yok; cargo run önce derler, sonra koşturur.

Bu tabloyu okurken dikkatimi çeken ilk şey şuydu: Node.js tarafında her satır ayrı bir proje, ayrı bir kurulum, ayrı bir yapılandırma dosyası. Rust tarafında ise prettier, eslint ve nvm karşılıkları dilin resmi araç zincirinin parçası. Hangi biçimlendiriciyi kullanacağımızı tartışmıyoruz, çünkü tek bir tane var.

Kurulum: rustup

Rust’ı işletim sisteminin paket yöneticisiyle (apt, brew) kurmak mümkün ama önerilen yol bu değil. Tıpkı Node.js’i apt yerine nvm ile kurmanın daha sağlıklı olması gibi, Rust’ı da rustup ile kuruyorum. Böylece sürümü ben yönetiyorum, güncelleme tek komut ve ileride çapraz derleme için gereken hedefleri aynı araçla ekleyebiliyorum.

macOS ve Linux’ta kurulum tek satır:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Betik ne kuracağını gösterip onay istiyor. Varsayılan seçimle devam ettiğinizde stable araç zincirini kuruyor: rustc, cargo, rustfmt, clippy ve standart kütüphanenin belgeleri. Her şey kullanıcı klasörünüzde, ~/.rustup ve ~/.cargo altında duruyor; sistem klasörlerine dokunmuyor, sudo istemiyor. Windows’ta aynı işi rustup.rs adresinden indirilen rustup-init.exe yapıyor; ben Windows’ta çalışırken WSL içinde Linux yolunu tercih ediyorum.

Kurulum bitince terminali yeniden açıp (ya da betiğin söylediği source komutunu çalıştırıp) üç komutla kontrol ediyorum:

rustup --version
rustc --version
cargo --version

Üçü de bir sürüm numarası yazdırıyorsa kurulum tamam. İleride güncellemek için tek komut yetiyor:

rustup update

Rust altı haftada bir yeni kararlı sürüm çıkarıyor. Bu ritim Node.js’in yılda bir büyük sürümünden çok farklı ama geriye dönük uyumluluk konusunda dil çok tutucu; bugün yazdığım kod bir sonraki sürümde de derleniyor. Bu yüzden rustup update demekten çekinmiyorum.

İlk proje: cargo new

Node.js’te yeni projeye npm init ile başlıyoruz ve elimizde bir package.json oluyor; gerisi bize kalıyor. Rust’ta cargo new hem proje dosyasını hem ilk kaynak dosyayı hem de git deposunu birlikte açıyor:

cargo new merhaba
cd merhaba

Oluşan yapı şu:

merhaba/
├── .git/
├── .gitignore
├── Cargo.toml
└── src/
    └── main.rs

Cargo.toml dosyası, package.json’ın karşılığı:

[package]
name = "merhaba"
version = "0.1.0"
edition = "2024"

[dependencies]

Buradaki edition satırı TypeScript’ten gelen biri için yeni bir kavram. Rust, dilde geriye dönük uyumsuz değişiklik yapmak istediğinde bunu “edition” adıyla, birkaç yılda bir topluca yapıyor; 2015, 2018, 2021 ve 2024 edition’ları var. Projeniz hangi edition’ı seçtiyse derleyici o kurallarla derliyor ve farklı edition’lardaki crate’ler aynı projede sorunsuz bir arada çalışıyor. TypeScript’teki target ve strict ayarlarının tek bir bayrakta toplanmış hâli gibi düşünüyorum. Yeni projelerde cargo en günceli seçiyor, bana bir şey düşmüyor.

src/main.rs dosyasında ise ilk programımız hazır geliyor:

fn main() {
    println!("Hello, world!");
}

İki şey hemen göze çarpıyor. fn ile fonksiyon tanımlanıyor ve main programın giriş noktası; Node.js’te dosyanın en üstünden akan kod yerine burada açık bir başlangıç var. İkincisi, println! sonundaki ünlem. Bu bir fonksiyon değil, bir makro. Makrolar derleme sırasında koda açılan yapılar; şimdilik “ünlemli çağrılar makrodur” diye bir kenara yazıyorum, ileride ayrıntısına gireceğim.

Çalıştırmak: cargo run, build ve check

Node.js’ten gelen biri için en büyük zihinsel değişiklik burada. node index.js dediğimizde kod anında çalışır. Rust’ta önce derleme var:

cargo run

Cargo projeyi derliyor, çalıştırılabilir dosyayı target/debug/ altına koyuyor ve hemen koşturuyor. Ekranda derleme satırları ve ardından Hello, world! görünüyor. Kodu değiştirip tekrar cargo run dediğimde yalnızca değişen kısım derleniyor.

Günlük çalışmada üç komut arasında geçiş yapıyorum:

cargo check   # yalnızca derler mi diye bakar, çıktı üretmez; en hızlısı
cargo build   # target/debug altına derler
cargo run     # derler ve çalıştırır

cargo check en çok kullandığım komut oldu. TypeScript’te tsc --noEmit ile tip kontrolü yapmaya benziyor: kod üretmediği için hızlı ve derleyicinin bütün uyarılarını gösteriyor. Rust’ta derleyici hataları dilin en güçlü yanı; hatanın nerede olduğunu, neden olduğunu ve çoğu zaman nasıl düzeltileceğini açık bir dille yazıyor. Serinin ilerleyen bölümlerinde sahiplik kurallarına girdiğimizde bu mesajlar en iyi öğretmenimiz olacak.

Üretime çıkacak dosya için ayrıca --release bayrağı var:

cargo build --release

Bu derleme optimizasyon açık yapılıyor, çıktı target/release/ altına gidiyor ve debug sürümünden belirgin biçimde hızlı çalışıyor. Önceki yazıda andığım ölçümlerin hepsi bu modda alınmış derlemelere ait. Orange Pi’ye gidecek dosya da bu olacak.

target/ klasörü kısa sürede büyüyor; cargo new bunu .gitignore dosyasına kendisi eklediği için commit’e girmiyor. node_modules için bunu yıllarca elle yaptık.

Bir bağımlılık eklemek: cargo add

Projeye paket eklemek npm install kadar tanıdık:

cargo add rand

Bu komut crates.io’dan rand crate’inin güncel sürümünü bulup Cargo.toml dosyasındaki [dependencies] altına yazıyor. Sürüm belirtimi npm’deki gibi semver kurallarıyla çalışıyor; rand = "0.9" yazmak, npm’deki ^0.9 ile aynı anlama geliyor.

İlk cargo build ile birlikte Cargo.lock dosyası oluşuyor. Burada package-lock.json’dan bir fark var: Rust topluluğunun kuralı net. Çalıştırılabilir bir program yazıyorsanız Cargo.lock commit edilir; başkalarının kullanacağı bir kütüphane yazıyorsanız commit edilmesi tercihe bağlıdır. İndirilen kaynak kodlar projenin içine değil, ~/.cargo/registry altına iniyor ve bütün projeler arasında paylaşılıyor. Yani her projede yeniden şişen bir node_modules yok.

Editör ve yardımcı araçlar

Editörde bana tipleri, hataları ve tamamlamaları gösteren araç rust-analyzer. VS Code’da aynı adlı eklentiyi kuruyorum; TypeScript’te editörün arkasında çalışan dil sunucusunun karşılığı bu. Kod yazarken derleyicinin göreceği hataları ben daha kaydetmeden görüyorum.

Biçimlendirme ve lint için ayrı bir şey kurmam gerekmedi, ikisi de rustup ile gelmişti:

cargo fmt      # bütün projeyi resmi stile göre biçimlendirir
cargo clippy   # derleyicinin ötesinde, deyimsel Rust için öneriler verir

cargo fmt için bir yapılandırma dosyası yazmadım. Tek bir resmi stil var ve topluluk ona uyuyor; prettier’ın tırnak ve noktalı virgül tartışmalarını geride bırakmak iyi geldi. Clippy ise eslint’ten bir adım ileride: yalnızca hata yakalamıyor, “bunu Rust’ta şöyle yazarız” diyerek dili öğretiyor. Yeni başlayan biri için çok değerli bir geri bildirim.

Bir de çevrimdışı belgeler var. rustup doc komutu, standart kütüphanenin belgelerini ve dilin resmi kitabını tarayıcıda yerel olarak açıyor. İnternetin güvenilir olmadığı sahada çalışırken bunun kıymetini bildiğim için not ediyorum.

Orange Pi tarafında şimdilik ne yapıyorum

Hedefim Orange Pi PC Plus. Kartın işlemcisi Allwinner H3, yani 32 bit ARM Cortex-A7. Rust bu hedefi armv7-unknown-linux-gnueabihf adıyla tanıyor; rustup target list komutuyla görebiliyorsunuz. Ama şu an bunu kurmuyorum. Önce dili bilgisayarımda öğreniyorum; çapraz derleme ve cihazda systemd ile çalıştırma serinin son bölümünün konusu. Burada yalnızca şunu bilmek yetiyor: rustup bu işi de üstlenecek, ayrı bir araç zinciri derlememe gerek kalmayacak.

TypeScript’ten gelen biri olarak ilk izlenimim

Kurulum ve ilk projeden sonra elimde kalan izlenimler şunlar:

  • Araçlar tek yerden geliyor. Sürüm yöneticisi, derleyici, paket yöneticisi, biçimlendirici, lint ve belgeler aynı kurulumla. Node.js’te bunları tek tek seçip bir arada çalıştırmak başlı başına bir işti.
  • Derleme adımı bir engel değil, bir denetim. cargo check ile kodun derlenmediğini birkaç saniyede görüyorum. Çalışma anında patlayacak bir hatayı önceden yakalamak, önceki yazıdaki bellek sorununu yaşayan biri için tam da aradığım şey.
  • Çıktı tek bir dosya. target/release/merhaba kendi başına çalışan bir program. Yanında bir çalışma ortamı, bir node_modules, bir kurulum adımı yok. Uç cihaza kopyalanacak şey bu kadar.

Sonraki bölümde dilin kendisine giriyorum: değişkenler, tipler ve kontrol akışı. Oradaki her kavramı TypeScript’teki karşılığının yanına koyarak anlatacağım, çünkü benzerlikler kadar farklar da öğretici.

Kaynaklar

Yeni Yazılar E-postanıza Gelsin

Yeni bir yazı yayımladığımda kısa bir e-posta alırsınız. İstediğiniz zaman tek tıkla çıkabilirsiniz. Gizlilik

İlgili Yazılar