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 OutputPathobrazcem .

Jeden projekt, jeden targetFramework

Představte si řešení, které obsahuje jeden projekt, který cílí na jeden TargetFrameworknet7.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 TargetFrameworksnet6.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 OutputPathobjektem , 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.

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.