Varsayılan Cargo Özellik Çözücüsü
Özet
Cargo.tomliçindekiedition = "2021"ayarı,resolver = "2"anlamına gelir.
Ayrıntılar
Rust 1.51.0’dan beri Cargo, Cargo.toml içinde resolver = "2" ile etkinleştirilen
yeni bir özellik çözücüsünü isteğe bağlı olarak destekliyor.
Rust 2021 ile birlikte bu varsayılan hale geldi. Yani Cargo.toml dosyasına
edition = "2021" yazmak, resolver = "2" demek olur.
Çözücü, bir çalışma alanı için geçerli olan genel bir ayardır ve bağımlılıkların
içinde yazıldığında dikkate alınmaz. Bu ayar yalnızca çalışma alanının en üst
düzey paketinde geçerlidir. Eğer bir sanal çalışma alanı kullanıyorsanız,
yeni çözücüyü etkinleştirmek için [workspace] tanımında [resolver alanını]
ayrıca açıkça ayarlamanız gerekir.
Yeni özellik çözücüsü, birden fazla yolla bağımlı olunan crate’ler için istenen tüm özellikleri artık tek bir yerde birleştirmez. Ayrıntılar için Rust 1.51 duyurusuna bakabilirsiniz.
Taşıma
Yeni çözücüye geçiş için otomatik bir taşıma aracı yoktur. Çoğu projede bu güncellemenin etkisi ya çok az olur ya da hiç olmaz.
cargo fix --edition ile güncelleme yaparken, yeni çözücü bağımlılıkları farklı
özelliklerle derleyecekse Cargo bir rapor gösterir. Bu rapor şu şekilde görünebilir:
not: Edition 2021’e geçmek, Cargo içinde 2. sürüm özellik çözücüsünün kullanımını etkinleştirir. Bu durum, bazı bağımlılıkların eskisine göre daha az özellikle derlenmesine yol açabilir. Çözücü değişiklikleri hakkında daha fazla bilgi için: https://doc.rust-lang.org/nightly/edition-guide/rust-2021/default-cargo-resolver.html
Aşağıdaki bağımlılıklar derlenirken, belirtilen özellikler artık kullanılmayacaktır:bstr v0.2.16: default, lazy_static, regex-automata, unicode libz-sys v1.1.3 (as host dependency): libc
Bu rapor, bazı bağımlılıkların artık belirtilen özelliklerle derlenmeyeceğini bildirir.
Derleme hataları
Bazı durumlarda bu değişiklikten sonra projeniz doğru şekilde derlenmeyebilir. Bir paketteki bağımlılık bildirimi, başka bir yerde bazı özelliklerin etkin olduğunu varsayıyorsa ve bu özellikler artık kapalıysa, derleme başarısız olabilir.
Örneğin şöyle bir bağımlılığımız olduğunu düşünelim:
# Cargo.toml
[dependencies]
bstr = { version = "0.2.16", default-features = false }
# ...
Bağımlılık ağacımızın başka bir yerinde de başka bir paket şuna sahip olsun:
# Another package's Cargo.toml
[build-dependencies]
bstr = "0.2.16"
Biz de paketimizde bstr içindeki
words_with_breaks
metodunu kullanıyor olalım. Bu metodun çalışması için bstr crate’inin
unicode özelliğinin etkin olması gerekir. Tarihsel olarak bu çalışıyordu;
çünkü Cargo iki paket arasında bstr özelliklerini birleştiriyordu. Ancak
Rust 2021’e geçtikten sonra yeni çözücü bstryi iki kez derler: biri varsayılan
özelliklerle build-dependency olarak, diğeri ise normal bağımlılığımız olarak
özelliksiz biçimde. Böylece bstr, unicode özelliği olmadan derlenmiş olur
ve words_with_breaks metodu ortada olmadığı için derleme eksik metod hatasıyla
başarısız olur.
Buradaki çözüm, bağımlılığı gerçekten kullandığınız özelliklerle birlikte bildirdiğinizden emin olmaktır. Örneğin:
[dependencies]
bstr = { version = "0.2.16", default-features = false, features = ["unicode"] }
Bazı durumlarda sorun, doğrudan kontrolünüzün olmadığı bir üçüncü taraf
bağımlılıktan kaynaklanabilir. Böyle bir durumda, sorunlu bağımlılık için doğru
özellik kümesini bildirmesi amacıyla ilgili projeye bir yama göndermeyi
düşünebilirsiniz. Alternatif olarak, kendi Cargo.toml dosyanızdan da herhangi
bir bağımlılığa özellik ekleyebilirsiniz. Örneğin yukarıdaki bstr bildirimi
üçüncü taraf bir bağımlılıkta yer alıyorsa, doğru bağımlılık bildirimini kendi
projenize kopyalamanız yeterlidir. Özellikler, yeni çözücünün birleştirme
kurallarıyla uyumlu oldukları sürece birleştirilir. Bu kurallar şunlardır:
- O anda derlenmeyen hedefler için platforma özgü bağımlılıklarda etkin olan özellikler yok sayılır.
- Build-dependencies ve proc-macro’lar, normal bağımlılıklarla özellik paylaşmaz.
- Dev-dependencies, onlara ihtiyaç duyan bir hedef derlenmedikçe özellik etkinleştirmez; örneğin testler ya da örnekler gibi.
Gerçek dünyadan bir örnek olarak
diesel ile
diesel_migrations
kullanımını düşünebiliriz. Bu paketler veritabanı desteği sağlar ve hangi
veritabanının kullanılacağı bir özellik ile seçilir:
[dependencies]
diesel = { version = "1.4.7", features = ["postgres"] }
diesel_migrations = "1.4.0"
Sorun şu ki diesel_migrations içinde, kendisi de diesele bağlı olan bir iç
proc-macro bulunur. Bu proc-macro, kendi diesel kopyasında bağımlılık ağacının
geri kalanıyla aynı özelliklerin etkin olduğunu varsayar. Yeni çözücüye
geçtikten sonra bu varsayım bozulur; çünkü artık iki ayrı diesel kopyası
vardır ve proc-macro için derlenen kopyada postgres özelliği eksiktir.
Buradaki çözüm, dieseli gerekli özelliklerle bir build-dependency olarak
eklemektir. Örneğin:
[build-dependencies]
diesel = { version = "1.4.7", features = ["postgres"] }
Bu sayede Cargo, host bağımlılıkları için postgres özelliğini de ekler;
yani proc-macro’lar ve build-dependencies tarafında da bu özellik etkin olur.
Böylece diesel_migrations proc-macro’su postgres özelliğini alır ve doğru
şekilde derlenir.
dieselin 2.0 sürümünde, bu bağımlılık gereksinimi ortadan kaldırılacak şekilde
yeniden yapılandırma yapıldığı için bu sorun bulunmaz.
Özellikleri incelemek
cargo tree komutu, yeni çözücüye geçişi kolaylaştırmak için önemli ölçüde
iyileştirildi. cargo tree, bağımlılık ağacını incelemek ve hangi özelliklerin
etkin olduğunu, daha da önemlisi neden etkin olduğunu görmek için kullanılabilir.
Bunun bir yolu --duplicates bayrağını kullanmaktır; kısa hali -ddir.
Bu bayrak size bir paketin birden fazla kez derlendiğini gösterir. Az önceki
bstr örneğinde şöyle bir çıktı görebiliriz:
> cargo tree -d
bstr v0.2.16
└── foo v0.1.0 (/MyProjects/foo)
bstr v0.2.16
[build-dependencies]
└── bar v0.1.0
└── foo v0.1.0 (/MyProjects/foo)
Bu çıktı, bstrnin iki kez derlendiğini ve her iki durumda da bu bağımlılığın
hangi zincir üzerinden geldiğini gösterir.
Her paketin hangi özellikleri kullandığını -f bayrağıyla da yazdırabilirsiniz:
cargo tree -f '{p} {f}'
Bu, Cargo’ya çıktının “biçimini” değiştirmesini söyler; böylece hem paketi hem de etkin özellikleri yazdırır.
Hangi “kenarların” gösterileceğini belirtmek için -e bayrağını da
kullanabilirsiniz. Örneğin cargo tree -e features, her bağımlılığın araya
hangi özellikleri eklediğini gösterir. Bu seçenek, ağacı “ters çevirmek” için
kullanılan -i bayrağıyla birlikte daha da yararlı hale gelir. Böylece
özelliklerin belirli bir bağımlılığa nasıl aktığını görebilirsiniz.
Örneğin bağımlılık ağacı büyükse ve bstrye tam olarak kimin bağımlı olduğunu
bilmiyorsanız, aşağıdaki komut bunu gösterir:
> cargo tree -e features -i bstr
bstr v0.2.16
├── bstr feature "default"
│ [build-dependencies]
│ └── bar v0.1.0
│ └── bar feature "default"
│ └── foo v0.1.0 (/MyProjects/foo)
├── bstr feature "lazy_static"
│ └── bstr feature "unicode"
│ └── bstr feature "default" (*)
├── bstr feature "regex-automata"
│ └── bstr feature "unicode" (*)
├── bstr feature "std"
│ └── bstr feature "default" (*)
└── bstr feature "unicode" (*)
Bu çıktı parçası, foo projesinin bara default özelliğiyle bağımlı olduğunu
gösterir. Ardından bar, bstrye build-dependency olarak yine default
özelliğiyle bağımlıdır. Buradan ayrıca bstrnin default özelliğinin,
başka özelliklerin yanında unicode özelliğini de etkinleştirdiğini görebiliriz.