Paket yöneticisi ne işe yarar?
Sezer Koçer
8 dk okuma
Güncellendi:
Özet
Paket yöneticisi, npm, pip ve NuGet üzerinden paketi bulur, kurar ve projenin bağımlılıklarını kayıt altında tutar.
Paket yöneticisi ne işe yarar?
Bir yazılım projesi büyüdükçe ihtiyaç duyduğu kod da başka insanların yazdığı paketlere dayanır. Paket yöneticisi, bu paketleri bulmayı, indirmeyi, kurmayı ve projenin hangi sürümlere bağlı olduğunu kayıt altında tutmayı üstlenen araçtır. npm Node.js ortamında, pip Python ortamında, NuGet ise .NET ortamında bu işi görür. Üçü de aynı cümleyle anlatılamaz. Her biri kendi paket biçimini ve kendi kurulum yolunu tanımlar.
Paket, modül ve bağımlılık
npm belgesi, kayıt defterindeki pek çok kaydın aynı zamanda Node modülü olduğunu, fakat paket ile modülün aynı şey olmadığını söyler. Paket, bir package.json dosyasının tarif ettiği dosya ya da klasördür. Kayıt defterine yayımlanacak paketin içinde bu dosya bulunmalıdır. Paket biçimleri arasında klasör, bu klasörün gzip ile sıkıştırılmış arşivi, o arşive çözülen bir adres, kayıt defterindeki ad ve sürüm, bir etiketin gösterdiği sürüm ve klonlandığında yine package.json içeren bir klasör veren git adresi sayılır.
Modül, node_modules içinde duran ve Node.js require() ya da import sözdizimiyle yüklenebilen dosya veya klasördür. require() ile yüklenecek modül, package.json içinde main alanı bulunan bir klasör ya da bir JavaScript dosyası olabilir. import kullanılıyorsa package.json içinde "type": "module" alanı da beklenir. Belgede altı çizilen ayrım şudur: her modülün package.json dosyası olmak zorunda değildir, bu yüzden her modül paket değildir. Yalnızca bu dosyaya sahip modüller aynı zamanda pakettir. Yüklenen dosyanın kendisi de, programın içinde modül diye anılır. require('request') çağrısının döndürdüğü değer, o dosyadan yüklenen modüldür.
Bağımlılık, bir paketin çalışmak için başka paketlere ihtiyaç duymasıdır. npm paketinde bu ilişki package.json ile tarif edilir. Python tarafında proje, ihtiyaç duyduğu paketleri install_requires veya requirements.txt üzerinden değiştirebilir. NuGet ise projenin doğrudan kullandığı paketlerin altındaki paketleri de izler ve buna bağımlılık ağacı der.
Neden elle kurmak yetmez?
Python’un kurulum rehberi, başkalarının açık lisansla paylaştığı çözümleri kullanmanın işbirliğini kolaylaştırdığını anlatır. PyPA özeti ise birden fazla dosyadan oluşan paketi tek tek aktarmanın zor olduğunu söyler. Çoğu aktarım yolu bir seferde tek dosya taşır. Eksik kopya riski artar. Bu yüzden saf Python kodu, kaynak dağıtım paketi denen sıkıştırılmış .tar.gz arşivine konur. Arşiv bir veya daha fazla paket ya da modül içerir.
NuGet belgesi aynı ihtiyacı .NET için tarif eder. Paylaşılacak kod çoğu zaman derlenmiş DLL dosyaları ve o kodun ihtiyaç duyduğu başka dosyalarla birlikte bir pakette toplanır. Paketi hazırlayan kişi onu bir hosta yayımlar. Kullanan kişi paketi hosttan alır, projesine ekler ve paket içindeki işlevi kendi kodundan çağırır. Ara adımları NuGet yürütür.
npm nerede durur?
npm, Node.js paketlerinin kayıt defteridir ve paket ile modül ilişkisini yukarıdaki gibi ayırır. Paketler kullanıcı veya kuruluşa bağlanan bir kapsama alınabilir. Kapsamlı paketler özel ya da herkese açık olabilir. Bu ayrım, aynı ada sahip paketlerin kime görüneceğini belirler. Belge, ayrıntıyı kapsam ve özel paket sayfalarına bırakır. Burada yeterli olan nokta şudur: npm’de yayımlamak ile bir dosyayı node_modules içine koymak aynı işlem değildir. Yayımlanan şey pakettir. Yüklenen şey modüldür ve ikisi yalnızca package.json varsa çakışır.
Git adresi de bir paket biçimidir. Klonlanan depo, package.json içeren klasörü veriyorsa npm onu paket olarak ele alır. Doğrudan git üzerinden kurulum, alt modülleri ve çalışma alanlarını kurmaz. Bu sınır, npm’in kendi paket sayfasında yazar. Başka bir JavaScript aracının adını bu tanıma eklemek, bu sayfanın anlattığı şey değildir.
pip, PyPI ve wheel
Python kurulum rehberi, pip’i tercih edilen kurulum programı olarak tanımlar. pip, Python’un ikili kurucularıyla birlikte gelir. PyPI, açık lisanslı paketlerin herkese açık deposudur. Python Packaging Authority, paketleme araçlarının ve ilgili üst veri biçimlerinin bakımını üstlenen topluluktur.
PyPA özeti, geliştiricilere dağıtılan kod için PyPI, setup.py ve wheel dosyalarını birlikte anar. Wheel, içine derlenmiş parçalar konabilen paket biçimidir. C, C++ veya başka dillerde yazılmış kütüphaneleri her kullanıcının kendi makinesinde derlemesi gerekmesin diye tasarlanmıştır. pip, kurulumu daha hızlı olduğu için wheel dosyasını tercih eder. Saf Python paketleri de wheel ile daha rahat kurulur. Kaynak dağıtımı ile wheel birlikte yayımlanırsa, wheel bulunmayan bir platform kendi arşivinden derleme yapabilir. Özet, ikisini birden yayımlamayı varsayılan yol olarak gösterir.
Aynı içe aktarma adını birden fazla dağıtım sağlayabilir. Özet, bunun örneği olarak PIL ve Pillow’u verir. Projenin install_requires veya requirements.txt kaydı değiştirilerek biri diğerinin yerine geçebilir.
Kurulum rehberi, bir modülün ve bağımlılıklarının PyPI’den kurulmasını şu komutla gösterir. Sürüm karşılaştırması kabukta özel karakter sayıldığı için sürüm ifadesi çift tırnak içine alınır.
python -m pip install SomePackage
python -m pip install SomePackage==1.0.4
python -m pip install "SomePackage>=1.0.4"
python -m pip install --upgrade SomePackage
Uygun bir kopya zaten kuruluysa aynı komutun yeniden çalıştırılması, rehbere göre ek bir iş yapmaz. Yükseltme ayrıca --upgrade ister. Sanal ortam açıkken aynı komutlar o ortamın içine kurar.
Sanal ortam, paketlerin tüm sisteme değil belirli bir uygulamanın kullanımına kurulduğu yarı yalıtılmış bir Python ortamıdır. venv, sanal ortam oluşturan standart araçtır ve oluşturduğu ortamlara pip kurar. virtualenv, onun üçüncü taraf alternatifidir ve ondan önce gelmiştir. Rehber, 3.5 sürümünden itibaren sanal ortam için venv kullanılmasını önerir. Linux’ta sistemle gelen Python’a pip ile kurulum yapmak kök yetkisi ister ve sistemin kendi paketlerini beklenmedik biçimde değiştirebilir. Bu yüzden rehber, sanal ortamı veya yalnızca geçerli kullanıcıya kurmayı önerir. Geçerli kullanıcı kurulumu python -m pip install komutuna --user eklenerek yapılır.
pip her kurulumda hazır gelmeyebilir. Rehber, bu durumda python -m ensurepip --default-pip komutunu olası bir çözüm olarak yazar. Birden fazla Python yanyanayken python3 -m pip gibi sürümü belli bir yorumlayıcı seçilir. Windows’ta aynı iş py başlatıcısı ile yapılır.
NuGet .NET paketini nasıl taşır?
NuGet, .NET ve .NET Core için Microsoft’un desteklediği paylaşım yoludur. Paketin kendisi .nupkg uzantılı tek bir ZIP dosyasıdır. İçinde derlenmiş DLL dosyaları, o koda bağlı başka dosyalar ve sürüm numarasını da içeren bir manifesto bulunur. Paket, paylaşılabilen bir kod birimidir. Belge, bunun belirli bir paylaşım biçimini zorunlu kılmadığını da söyler.
Host, paketi hazırlayan ile kullanan arasındaki bağlantı noktasıdır. Herkese açık host nuget.org’dur. NuGet, bunun yanında özel hostu da destekler. Özel host bulutta, özel bir ağda veya yalnızca yerel dosya sisteminde durabilir. Böyle bir hosttaki paketleri yalnızca o hosta erişen kişiler alır. Yapılandırma, bir bilgisayarın hangi hostlara bakacağını sınırlayabilir. Amaç, paketlerin herkese açık depo yerine seçilen kaynaktan gelmesidir.
Kurulan paket, tüketen projenin hedef çerçevesiyle uyumlu en az bir derleme içermelidir. Uyumu genişletmek için geliştiriciler .NET Standard hedefler. .NET Standard dışındaki API’ler gerekiyorsa aynı pakete birden fazla hedef çerçevenin derlemeleri konur. Buna çoklu hedefleme denir. Kurulum sırasında NuGet, projenin ihtiyaç duyduğu derlemeleri ayıklar. Bu, son uygulamada paketin kapladığı yeri küçültür. Çoklu hedefleme, paketi hazırlayan için bakımı zorlaştırır. Bu cümle, genel bir hız iddiası değildir. Belge, ayıklanan derlemenin son çıktıdaki yerini anlatır.
Bağımlılık konusunda NuGet’in tarifi açıktır. Projede doğrudan kullandığınız paketleri seçersiniz. O paketler başka paketlere dayanıyorsa alt katmanları NuGet izler. Aynı paket ağaçta birkaç kez görünebilir ve her kullanan farklı bir sürüm isteyebilir. NuGet, bütün isteyenleri karşılayan sürümü seçmeye çalışır. Ayrıntı, belgenin bağımlılık çözümleme sayfasına bırakılmıştır.
İkili dosyaları projenin içine gömmek, depoyu şişirir ve her kopyada sürümü ayrı ayrı güncellemeyi gerektirir. NuGet bunun yerine bir başvuru listesi tutar. Liste, paket kimliği ile sürüm numarasını kaydeder. Kaldırılan paket listeden de çıkar. Daha sonra aynı paketler, herkese açık veya özel hosttan yeniden kurulabilir. Buna geri yükleme denir. Kaynak denetimine ikili dosyalar değil, bu liste konur. Depoyu klonlayan geliştirici veya derleme sunucusu nuget restore, dotnet restore ya da Paket Yöneticisi Konsolu’ndaki Install-Package ile paketleri yeniden alır. Visual Studio, otomatik geri yükleme açıksa derleme sırasında bu işi yapabilir.
Başvuru listesinin iki biçimi vardır. PackageReference, NuGet 4.0 ile gelen yoldur ve doğrudan bağımlılıkları proje dosyasının içinde tutar. Ayrı bir liste dosyası gerekmez. Bağımlılık ağacının tamamı obj/project.assets.json dosyasında üretilir. .NET Core projeleri PackageReference kullanır. packages.config daha eski yoldur. Projedeki bağımlılıkların düz bir XML listesidir ve kurulan paketler bir packages klasöründe durur. Belge, seçim varsa PackageReference önerir. nuget install listeyi kendiliğinden güncellemez. Liste, Visual Studio paket yöneticisi veya dotnet komut satırı ile kurulunca güncellenir. Paketi üretmek için belge nuget pack komutunu, yapılandırma için nuget config komutunu anar.
Hangi araç seçilir?
Seçim, projenin diline ve paketlerin nereden geleceğine bağlıdır. Node.js require() veya import ile modül yüklüyorsa npm’in paket ve modül ayrımı geçerlidir. Python ile yazılmış bir kütüphane veya araç, geliştiriciler arasında paylaşılacaksa pip, PyPI, wheel ve sanal ortam bu rehberlerin anlattığı yoldur. PyPA özeti, paketlemeye kod yazmadan önce bakılmasını önerir. Sorular şunlardır: yazılımı kim kuracak, sunucuda mı masaüstünde mi çalışacak, kurulum tek tek mi yoksa toplu mu yapılacak. Yerel Python paketleme araçları, Python kurulu bir geliştirici kitlesini varsayar. Uygulamayı Python bilmeyen bir kullanıcıya dağıtmak başka bir paketleme konusudur ve bu dört sayfanın anlattığı pip yolunun dışındadır.
.NET projesinde paylaşılacak derlenmiş kod varsa NuGet’in .nupkg paketi, hostu ve başvuru listesi devreye girer. Herkese açık nuget.org ile yalnızca ekibin eriştiği özel host farklı kayıtlardır. İkisi de NuGet paketidir. Fark, paketi kimin görebileceğidir.
Dikkat edilecek yerler de araca göre değişir. npm tarafında bir JavaScript dosyası modül olabilir ama package.json yoksa paket sayılmaz. Python tarafında Linux sistem Python’una gelişigüzel kurulum, sistem paketleriyle çakışabilir. Sanal ortam veya --user bu rehberin önerdiği ayrımdır. NuGet tarafında uyumluluk, paket derlemesinin projenin hedef çerçevesine uymasıdır. Ağaçtaki sürüm seçimini NuGet yapar. Bu, her sürüm aralığının kendiliğinden doğru olduğu anlamına gelmez. Belge, seçimin tüketicilerin istedikleri sürümleri birlikte karşılayacak şekilde yapıldığını anlatır.
Sonuç
Paket yöneticisi, hazır kodu projeye bağlamanın yoludur. npm bu bağı paket ile modül ayrımı üzerinden kurar. pip, PyPI’deki dağıtımı wheel veya kaynak arşiv olarak kurar ve sanal ortam sayesinde bu kurulumu sistem genelinden ayırır. NuGet, .nupkg paketini bir hostta tutar, projenin başvuru listesini saklar ve ihtiyaç duyulunca paketleri yeniden yükler. Araç seçimi, kullanılan çalışma ortamının bu üç yoldan hangisine ait olduğu sorusuyla başlar.