Možnost na úrovni --output
řešení už neplatí pro příkazy související s sestavením.
V sadě SDK verze 7.0.200 došlo ke změně , která už nepřijme --output
/-o
možnost při použití souboru řešení s následujícími příkazy:
build
clean
pack
publish
store
test
vstest
Důvodem je to, že sémantika OutputPath
vlastnosti, která je řízena --output
/-o
možností, nejsou dobře definovány pro řešení. Projekty vytvořené tímto způsobem budou mít výstup umístěný ve stejném adresáři, což je nekonzistentní a vedlo k řadě problémů hlášených uživatelem.
Tato změna se snížila na úroveň závažnosti upozornění v sadě SDK 7.0.201 a pack
byla odebrána ze seznamu ovlivněných příkazů.
Zavedená verze
Sada .NET 7.0.200 SDK se snížila na upozornění pouze v sadě SDK verze 7.0.201.
Předchozí chování
Pokud jste dříve zadali --output
/-o
při použití souboru řešení, výstup pro všechny sestavené projekty by byl umístěn v zadaném adresáři v nedefinovaném a nekonzistentním pořadí.
Nové chování
Pokud dotnet
se tato možnost použije se souborem řešení, rozhraní příkazového --output
/-o
řádku se zobrazí chyba. Počínaje sadou SDK 7.0.201 se místo toho vygeneruje upozornění a v případě žádného dotnet pack
upozornění nebo chyby se vygeneruje.
Typ zásadní změny
Tato změna způsobující chybu může vyžadovat úpravy skriptů sestavení a kanálů kontinuální integrace. V důsledku toho ovlivňuje binární i zdrojovou kompatibilitu.
Důvod změny
Tato změna byla provedena, protože sémantika OutputPath
vlastnosti, která je řízena --output
/-o
možností, nejsou dobře definovány pro řešení. Projekty vytvořené tímto způsobem budou mít výstup umístěný ve stejném adresáři, což je nekonzistentní a vedlo k řadě problémů hlášených uživatelem.
Při sestavení řešení s --output
možností OutputPath
je vlastnost nastavena na stejnou hodnotu pro všechny projekty, což znamená, že všechny projekty budou mít svůj výstup umístěný ve stejném adresáři. V závislosti na složitosti projektů v řešení může dojít k různým a nekonzistentním výsledkům. Pojďme se podívat na některé příklady různých obrazců řešení a na to, jak jsou ovlivněny sdíleným OutputPath
obrazcem .
Jeden projekt, jeden targetFramework
Představte si řešení, které obsahuje jeden projekt, který cílí na jeden TargetFramework
net7.0
, . V tomto případě je poskytnutí --output
možnosti ekvivalentní nastavení OutputPath
vlastnosti v souboru projektu. Během sestavení (nebo jiných příkazů, ale pojďme teď nastavit rozsah diskuze na sestavení), všechny výstupy projektu budou umístěny v zadaném adresáři.
Jeden projekt, více targetFrameworks
Nyní si představte řešení, které obsahuje jeden projekt s více TargetFrameworks
net6.0
a net7.0
. Z důvodu cílení na více verzí se projekt sestaví dvakrát, jednou pro každý TargetFramework
. Pro každou z těchto "vnitřních" sestavení OutputPath
bude nastavena na stejnou hodnotu, takže výstupy pro každé vnitřní sestavení budou umístěny ve stejném adresáři. To znamená, že podle toho, které sestavení se dokončí, přepíše výstupy druhého sestavení a v systému paralelního sestavení, jako je MSBuild, ve výchozím nastavení je "poslední" neurčitý.
Library = Console =>> Test, single TargetFramework
Teď si představte řešení, které obsahuje projekt knihovny, projekt konzoly, který odkazuje na projekt knihovny, a testovací projekt, který odkazuje na projekt konzoly. Všechny tyto projekty cílí na jeden TargetFramework
, net7.0
. V tomto případě se projekt knihovny sestaví jako první a pak se projekt konzoly sestaví. Testovací projekt bude sestaven jako poslední a bude odkazovat na projekt konzoly. Pro každý sestavený projekt se výstupy každého sestavení zkopírují do adresáře určeného OutputPath
objektem , takže konečný adresář bude obsahovat prostředky ze všech tří projektů. To funguje pro testování, ale při publikování může dojít k odeslání testovacích prostředků do produkčního prostředí.
Library = Console =>> Test, multiple TargetFrameworks
Teď vezměte stejný řetězec projektů a přidejte net6.0
TargetFramework
do nich kromě net7.0
sestavení také sestavení. K tomuto problému dochází stejně jako u sestavení s jedním projektem s více cíli – nekonzistentní kopírování prostředků specifických pro TFM do zadaného adresáře.
Více aplikací
Zatím jsme se dívali na scénáře s lineárním grafem závislostí , ale mnoho řešení může obsahovat více souvisejících aplikací. To znamená, že více aplikací může být souběžně sestaveno do stejné výstupní složky. Pokud aplikace obsahují soubor závislostí se stejným názvem, může sestavení občas selhat, když se více projektů pokusí do daného souboru zapisovat současně ve výstupní cestě.
Pokud několik aplikací závisí na různých verzích souboru, může být i v případě úspěšného sestavení, která verze souboru se zkopíruje do výstupní cesty, ne deterministické. K tomu může dojít v případě, že projekty závisí (pravděpodobně tranzitivně) na různých verzích balíčku NuGet. V rámci jednoho projektu nuGet pomáhá zajistit, aby jeho závislosti (včetně jakýchkoli tranzitivních závislostí prostřednictvím balíčků NuGet a/nebo odkazů na projekty) byly sjednocené se stejnou verzí. Vzhledem k tomu, že sjednocení se provádí v kontextu jednoho projektu a jeho závislých projektů, znamená to, že při vytváření dvou samostatných projektů nejvyšší úrovně je možné přeložit různé verze balíčku. Pokud projekt, který závisí na vyšší verzi, zkopíruje závislost jako poslední, aplikace se často úspěšně spustí. Pokud je však nižší verze zkopírována jako poslední, aplikace, která byla zkompilována proti vyšší verzi, se nepodaří načíst sestavení za běhu. Vzhledem k tomu, že kopírovaná verze může být nedeterministická, může to vést k občasným nespolehlivým buildům, kde je velmi obtížné diagnostikovat problém.
Další příklady
Další příklady, jak tato základní chyba představuje v praxi, najdete v diskuzi o dotnet/sdk#15607.
Doporučená akce
Obecným doporučením je provést akci, kterou jste předtím provedli bez/ --output
-o
možnosti, a po dokončení příkazu přesunout výstup do požadovaného umístění. Je také možné provést akci v konkrétním projektu a přesto tuto možnost použít --output
/-o
, protože má dobře definovanou sémantiku.
Pokud chcete zachovat stávající chování přesně, můžete pomocí --property
příznaku nastavit vlastnost MSBuild na požadovaný adresář. Vlastnost, která se má použít, se liší podle příkazu:
Příkaz | Vlastnost | Příklad |
---|---|---|
build |
OutputPath |
dotnet build --property:OutputPath=DESIRED_PATH |
clean |
OutputPath |
dotnet clean --property:OutputPath=DESIRED_PATH |
pack |
PackageOutputPath |
dotnet pack --property:PackageOutputPath=DESIRED_PATH |
publish |
PublishDir |
dotnet publish --property:PublishDir=DESIRED_PATH |
store |
OutputPath |
dotnet store --property:OutputPath=DESIRED_PATH |
test |
TestResultsDirectory |
dotnet test --property:OutputPath=DESIRED_PATH |
POZNÁMKA: Pro nejlepší výsledky by DESIRED_PATH měla být absolutní cesta. Relativní cesty budou ukotvené (tj. absolutní) způsoby, které neočekáváte, a nemusí fungovat stejně se všemi příkazy.