Jak NuGet řeší závislosti balíčků
Kdykoli se balíček nainstaluje nebo přeinstaluje, což zahrnuje instalaci v rámci procesu obnovení , NuGet také nainstaluje všechny další balíčky, na kterých závisí tento první balíček.
Tyto okamžité závislosti pak můžou mít také závislosti na sobě, což může pokračovat libovolnou hloubkou. Výsledkem je graf závislostí , který popisuje vztahy mezi balíčky na všech úrovních.
Pokud má více balíčků stejnou závislost, může se stejné ID balíčku v grafu objevit vícekrát, potenciálně s různými omezeními verze. V projektu se ale dá použít jenom jedna verze daného balíčku, takže NuGet musí zvolit, která verze se použije. Přesný proces závisí na použitém formátu správy balíčků.
Řešení závislostí pomocí PackageReference
Při instalaci balíčků do projektů pomocí formátu PackageReference přidá NuGet odkazy na plochý graf balíčků v příslušném souboru a předem vyřeší konflikty. Tento proces se označuje jako přechodné obnovení. Přeinstalace nebo obnovení balíčků je pak proces stažení balíčků uvedených v grafu, což vede k rychlejším a předvídatelnějším sestavením.
Můžete také využít plovoucí verze, například 2.8.*, abyste zabránili úpravám projektu tak, aby používal nejnovější verzi balíčku. Při použití plovoucích verzí doporučujeme povolit funkci zamknout soubor, aby se zajistila opakovatelnost.
Když se proces obnovení NuGet spustí před sestavením, vyřeší nejprve závislosti v paměti a pak zapíše výsledný graf do souboru volaný project.assets.json
.
Soubor assets se nachází ve MSBuildProjectExtensionsPath
výchozím nastavení složky obj projektu.
Nástroj MSBuild pak tento soubor přečte a přeloží ho do sady složek, kde lze najít potenciální odkazy, a pak je přidá do stromu projektu v paměti.
Soubor project.assets.json
je dočasný a neměl by být přidán do správy zdrojového kódu. Ve výchozím nastavení je uvedena v obou .gitignore
a .tfignore
. Viz Balíčky a správa zdrojového kódu.
Pravidla řešení závislostí
Přechodné obnovení používá čtyři hlavní pravidla k řešení závislostí: nejnižší použitelná verze, plovoucí verze, výhry závislostí s přímým přístupem a závislosti bratrance.
Nejnižší použitelná verze
Nejnižší použitelné pravidlo verze obnoví nejnižší možnou verzi balíčku, jak je definováno jeho závislostmi. Platí také pro závislosti na aplikaci nebo knihovně tříd, pokud nejsou deklarovány jako plovoucí.
Na následujícím obrázku se například verze 1.0-beta považuje za nižší než 1.0, takže NuGet zvolí verzi 1.0:
Na následujícím obrázku není v informačním kanálu dostupná verze 2.1, ale protože omezení verze je >= 2.1 NuGet vybere další nejnižší verzi, která může najít, v tomto případě 2.2:
Pokud aplikace určuje přesné číslo verze, například 1.2, které není dostupné v informačním kanálu, NuGet selže s chybou při pokusu o instalaci nebo obnovení balíčku:
Plovoucí verze
Verze s plovoucí závislostí je určena znakem *. Například 6.0.*
. Tato specifikace verze říká"použití nejnovější verze 6.0.x"; 4.*
znamená "použít nejnovější verzi 4.x". Použití plovoucí verze snižuje změny v souboru projektu a současně udržuje aktuální nejnovější verzi závislosti.
Plovoucí verze lze zadat pouze na úrovni projektu.
Při použití plovoucí verze NuGet vyřeší nejvyšší verzi balíčku, která odpovídá vzoru verze, například 6.0.*
získá nejvyšší verzi balíčku, která začíná na verzi 6.0:
Verze | Verze přítomné na serveru | Rozlišení | Důvod | Notes |
---|---|---|---|---|
* | 1.1.0 1.1.1 1.2.0 1.3.0-alpha |
1.2.0 | Nejvyšší stabilní verze. | |
1.1.* | 1.1.0 1.1.1 1.1.2-alfa 1.2.0-alpha |
1.1.1 | Nejvyšší stabilní verze, která respektuje zadaný vzor. | |
*-* | 1.1.0 1.1.1 1.1.2-alfa 1.3.0-beta |
1.3.0-beta | Nejvyšší verze, včetně nestabilní verze. | K dispozici v sadě Visual Studio verze 16.6, NuGet verze 5.6, .NET Core SDK verze 3.1.300 |
1.1.*-* | 1.1.0 1.1.1 1.1.2-alfa 1.1.2-beta 1.3.0-beta |
1.1.2-beta | Nejvyšší verze, která respektuje vzor a zahrnuje nestabilní verze. | K dispozici v sadě Visual Studio verze 16.6, NuGet verze 5.6, .NET Core SDK verze 3.1.300 |
Poznámka:
Plovoucí rozlišení verze nebere v úvahu, jestli je uveden balíček nebo ne. Rozlišení plovoucí verze bude vyřešeno místně, pokud podmínky mohou být splněny s balíčky ve složce globálního balíčku.
Přímá závislost vyhrává
Pokud graf balíčků pro aplikaci obsahuje různé verze balíčku ve stejném podgrafu a jedna z těchto verzí je přímá závislost v tomto podgrafu, bude tato verze zvolena pro tento podgraf a zbytek bude ignorován. Toto chování umožňuje aplikaci přepsat jakoukoli konkrétní verzi balíčku v grafu závislostí.
V následujícím příkladu aplikace závisí přímo na balíčku B s omezením >verze =2.0.0. Aplikace také závisí na balíčku A, který zase závisí na balíčku B, ale s >omezením =1.0.0. Vzhledem k tomu, že závislost na balíčku B 2.0.0 je přímá závislost na aplikaci v grafu, používá se tato verze:
Upozorňující
Pravidlo výhry přímé závislosti může vést k downgradu verze balíčku, čímž by mohlo dojít k narušení jiných závislostí v grafu. Když je balíček downgradován, NuGet přidá upozornění, které uživatele upozorní.
Výsledkem tohoto pravidla je také větší efektivita s velkým grafem závislostí. Pokud má užší závislost ve stejném podgrafu vyšší verzi než další, NuGet tuto závislost ignoruje a NuGet také ignoruje všechny zbývající závislosti na dané větvi grafu.
Například v následujícím diagramu, protože balíček C 2.0.0 se používá, NuGet ignoruje všechny větve v tomto podgrafu, které odkazují na starší verzi balíčku C:
Prostřednictvím tohoto pravidla se NuGet pokusí respektovat záměr autora balíčku. V následujícím diagramu autor balíčku A explicitně downgradoval na Balíček C 1.0.0 z balíčku C 2.0.0.
Vlastník aplikace se může rozhodnout, že balíček C upgraduje na verzi vyšší než 2.0.0, takže verzi balíčku C nebude dále downgradovat. V tomto případě se nevyvolá žádné upozornění.
Závislosti bratrance
Pokud se různé verze balíčků označují v různých podgrafech v grafu z aplikace, NuGet používá nejnižší verzi, která splňuje všechny požadavky na verzi (stejně jako u nejnižší platné verze a pravidel plovoucích verzí ). Na následujícím obrázku, například verze 2.0.0 balíčku B splňuje ostatní >omezení =1.0.0, a proto se používá:
Mějte na paměti, že balíčky nemusí být na stejné vzdálenosti, aby pravidlo závislostí bratrance bylo možné použít. V následujícím diagramu je balíček D 2.0.0 vybrán v podgrafu Balíček C a balíček D 3.0.0 je vybrán v podgrafu balíčku A. V podgrafu aplikace neexistuje žádná přímá závislost na balíčku D, takže se použije nejnižší použitelné pravidlo verze a zvolí se verze 3.0.0.
V některých případech není možné splnit všechny požadavky na verzi. Jak je znázorněno níže, pokud balíček A vyžaduje přesně balíček B 1.0.0 a balíček C vyžaduje balíček B >=2.0.0, NuGet nemůže vyřešit závislosti a zobrazí chybu.
V těchto situacích by měl příjemce nejvyšší úrovně (aplikace nebo balíček) přidat vlastní přímou závislost na balíčku B, aby pravidlo wins přímé závislosti platilo.
Rozsahy verzí a předběžné verze pomocí PackageReference
Není neobvyklé, že balíček bude mít k dispozici stabilní i předběžné verze.
Při řešení grafu závislostí se NuGet rozhodne, jestli se má zvážit předběžné verze balíčku na základě jednoho pravidla: If the project or any packages within the graph request a prerelease version of a package, then include both prerelease or stable versions, otherwise consider stable versions only.
V praxi platí, že v rámci nejnižšího platného pravidla to znamená:
Rozsah verzí | Dostupné verze | Vybraná verze |
---|---|---|
[1.0.0, 2.0.0) | 1.2.0-beta.1, 1.2.0, | 1.2.0 |
[1.0.0, 2.0.0-0) | 1.2.0-beta.1, 1.2.0, | 1.2.0-beta.1 |
[1.0.0, 2.0.0) | 1.2.0-beta.1, 2.0.0-beta.3 | Žádná, NU1103 je vyvolána. |
[1.0.0, 2.0.0-rc) | 1.2.0-beta.1, 2.0.0-beta.3 | 1.2.0-beta.1 |
Řešení závislostí s využitím packages.config
Se packages.config
závislostmi projektu se zapisují packages.config
jako plochý seznam. Všechny závislosti těchto balíčků se také zapisují do stejného seznamu. Při instalaci balíčků může NuGet také upravit .csproj
soubor, app.config
, web.config
, a další jednotlivé soubory.
Při packages.config
instalaci jednotlivých balíčků se NuGet pokusí vyřešit konflikty závislostí. To znamená, že pokud je balíček A nainstalovaný a závisí na balíčku B a balíček B je již uveden jako packages.config
závislost něčeho jiného, NuGet porovná požadované verze balíčku B a pokusí se najít verzi, která splňuje všechna omezení verzí. NuGet konkrétně vybere nižší hlavní podverzi , která splňuje závislosti.
Ve výchozím nastavení NuGet 2.8 hledá nejnižší verzi opravy (viz poznámky k verzi NuGet 2.8). Toto nastavení můžete řídit prostřednictvím atributu DependencyVersion
a NuGet.Config
přepínače na příkazovém -DependencyVersion
řádku.
Proces packages.config
řešení závislostí je pro větší grafy závislostí složitý. Každá nová instalace balíčku vyžaduje procházení celého grafu a zvyšuje šanci na konflikty verzí. Když dojde ke konfliktu, instalace se zastaví a projekt opustí v nedeterminátu stavu, zejména při potenciálních úpravách samotného souboru projektu. Nejedná se o problém při použití jiných formátů správy balíčků.
Rozsahy verzí a předběžné verze s packages.config
řešení packages.config neumožňuje kombinování stabilní a předběžné závislosti v grafu.
Pokud je závislost vyjádřena s rozsahem, jako [1.0.0, 2.0.0)
je , předběžné verze balíčků nejsou v grafu povoleny.
Správa prostředků závislostí
Při použití formátu PackageReference můžete řídit, které prostředky ze závislostí proudí do projektu nejvyšší úrovně. Podrobnosti najdete v tématu PackageReference.
Pokud je projekt nejvyšší úrovně samotným balíčkem, máte také kontrolu nad tímto tokem pomocí include
atributů se exclude
závislostmi uvedenými v .nuspec
souboru. Viz referenční informace k souboru .nuspec – závislosti.
Vyloučení odkazů
Existují scénáře, ve kterých sestavení se stejným názvem můžou být v projektu odkazována více než jednou, což vytváří chyby v době návrhu a času sestavení. Zvažte projekt, který obsahuje vlastní verzi C.dll
a odkazuje na Balíček C, který obsahuje C.dll
také . Současně projekt také závisí na balíčku B, který také závisí na balíčku C a C.dll
. V důsledku toho NuGet nedokáže určit, které C.dll
použít, ale nemůžete jen odebrat závislost projektu na balíčku C, protože balíček B na něm také závisí.
Pokud chcete tento problém vyřešit, musíte přímo odkazovat na C.dll
požadovaný prostředek (nebo použít jiný balíček, který odkazuje na ten správný) a pak přidat závislost na balíčku C, který vylučuje všechny jeho prostředky. To se provádí následovně v závislosti na používaném formátu správy balíčků:
PackageReference: přidejte
ExcludeAssets="All"
do závislosti:<PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
packages.config
: Odeberte odkaz na PackageC ze.csproj
souboru tak, aby odkazovat pouze na požadovanou verziC.dll
.
Aktualizace závislostí během instalace balíčku
Pokud už je verze závislosti splněná, závislost se během jiných instalací balíčků neaktualizuje. Představte si například balíček A, který závisí na balíčku B a určuje číslo verze 1.0. Zdrojové úložiště obsahuje verze 1.0, 1.1 a 1.2 balíčku B. Pokud je V projektu, který již obsahuje B verze 1.0, A je nainstalován, B 1.0 zůstane používán, protože splňuje omezení verze. Pokud však balíček A požaduje verzi 1.1 nebo vyšší verze B, nainstaluje se B 1.2.
Řešení nekompatibilních chyb balíčku
Během operace obnovení balíčku se může zobrazit chyba "Jeden nebo více balíčků není kompatibilní..." nebo že balíček není kompatibilní s cílovou architekturou projektu.
K této chybě dochází, když jeden nebo více balíčků odkazovaných v projektu neznamená, že podporují cílovou architekturu projektu; to znamená, že balíček neobsahuje vhodnou knihovnu DLL ve složce lib
pro cílovou architekturu, která je kompatibilní s projektem. (Viz Cílové architektury pro seznam.)
Pokud například projekt cílí netstandard1.6
a pokusíte se nainstalovat balíček, který obsahuje knihovny DLL pouze v těchto lib\net20
složkách \lib\net45
, zobrazí se zprávy podobné následujícímu balíčku a pravděpodobně jeho závislé položky:
Restoring packages for myproject.csproj...
Package ContosoUtilities 2.1.2.3 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoUtilities 2.1.2.3 supports:
- net20 (.NETFramework,Version=v2.0)
- net45 (.NETFramework,Version=v4.5)
Package ContosoCore 0.86.0 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoCore 0.86.0 supports:
- 11 (11,Version=v0.0)
- net20 (.NETFramework,Version=v2.0)
- sl3 (Silverlight,Version=v3.0)
- sl4 (Silverlight,Version=v4.0)
One or more packages are incompatible with .NETStandard,Version=v1.6.
Package restore failed. Rolling back package changes for 'MyProject'.
Pokud chcete vyřešit nekompatibilitu, udělejte jednu z těchto věcí:
- Nastavte cílení projektu na architekturu podporovanou balíčky, které chcete použít.
- Obraťte se na autora balíčků a spolupracujte s nimi a přidejte podporu pro vámi zvolenou architekturu. Každá stránka s výpisem balíčku na nuget.org má pro tento účel odkaz Kontaktovat vlastníky.
Tip
Alternativní řešení: NuGetSolver je rozšíření sady Visual Studio vyvinuté Microsoft DevLabs, které je navržené tak, aby pomohlo vyřešit konflikty závislostí. Automatizuje proces identifikace a řešení těchto problémů. Další podrobnosti najdete na stránce NuGetSolver na webu Visual Studio Marketplace a rádi si poslechneme váš názor na vaše prostředí.