Directory.Build.props учитывается только при создании файла .sln

Когда я создаю свои проекты с целью MyConfig, я хочу, чтобы код был оптимизирован, и мне не нужны файлы .pdb.

Для этого я создал такой файл Directory.Build.props в корне моего проекта.

<Project>
  <PropertyGroup>
    <Configurations>Debug;Release;MyConfig</Configurations>
  </PropertyGroup>

  <PropertyGroup Condition = "'$(Configuration)|$(Platform)' == 'MyConfig|AnyCPU'">
    <DebugType>none</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
  </PropertyGroup>

</Project>

Теперь, если я запущу эту команду, я получу ожидаемый результат:

dotnet build .\BuildPoc.sln -c MyConfig

Однако при непосредственном построении проекта:

dotnet build .\src\MyProject\MyProject.csproj -c MyConfig

Затем создаются файлы .pdb.

Я не понимаю, почему такая разница?

Следует ли dotnet build не уважать Directory.Build.props несмотря ни на что?

Я создал здесь образец репозитория с простым проектом, демонстрирующим такое поведение: https://github.com/mortenbock/BuildPoc

Обновлено:

Кроме того, я только что обнаружил, что если я запущу эти две команды:

dotnet build .\BuildPoc.sln -c MyConfig
dotnet publish .\src\MyProject\MyProject.csproj -c MyConfig --no-build

Затем я получаю эту ошибку: кажется, dotnet publish предполагает, что должен быть файл .pdb?

C:\Program Files\dotnet\sdk\8.0.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(351,5): error MSB3030:
 Could not copy the file "obj\MyConfig\net8.0\MyProject.pdb" because it was not found. [D:\Projects\BuildPoc\sr
c\MyProject\MyProject.csproj]
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблемы со сборкой и публикацией решаются путем передачи явного аргумента платформы через -p:Platform=AnyCPU.

  • Сборка проекта:
dotnet build .\src\MyProject\MyProject.csproj -c MyConfig -p:Platform=AnyCPU
  • Публикация проекта:
dotnet publish .\src\MyProject\MyProject.csproj -c MyConfig --no-build -p:Platform=AnyCPU

Либо удалите флажок $(Platform) из условия, поскольку во всех ваших командных строках есть -c MyConfig.

 <PropertyGroup Condition = "'$(Configuration)' == 'MyConfig'">

Официального объяснения пока не нашел.


Другой альтернативой является использование файла Directory.Build.targets, который импортируется позже.
Судя по вашему комментарию, порядок импорта и оценок имеет значение.

Вы можете переименовать этот Directory.Build.props файл в Directory.Build.targets.
. При этом ваша первоначальная попытка создания проекта увенчается успехом.

dotnet build .\src\MyProject\MyProject.csproj -c MyConfig

Чтобы опубликовать проект, вам необходимо собрать и опубликовать его за один раз, поэтому удалите --no-build (или воспользуйтесь предыдущим/вышеуказанным предложением публикации).

dotnet publish .\src\MyProject\MyProject.csproj -c MyConfig

Я выбрал вариант изменения своих условий. Хотя это очень странно. Я попробовал вывести $(Platform) во время сборки, и в обоих случаях это было AnyCPU, но, может быть, дело в том, в какой момент сборки устанавливается это значение? Возможно, иногда он не устанавливается до тех пор, пока не будут оценены условия.

mortenbock 06.07.2024 00:12

Я следовал тем же шагам, о которых вы упомянули, даже --verbosity detailed не сделал меня намного мудрее.

pfx 06.07.2024 12:01
Directory.Build.props импортируется очень рано и до «общей» поддержки проекта. Если нет явной необходимости, избегайте использования Directory.Build.props и отдавайте предпочтение Directory.Build.targets. (Имена произвольные. Оба файла являются «полными» файлами MSBuild без ограничений, т. е. свойства не обязательно должны быть в .props.)
Jonathan Dodds 06.07.2024 15:43

Предположение в заголовке «Directory.Build.props учитывается только при создании файла .sln» неверно и не является тем, что происходит.

Directory.Build.props импортируется очень рано и до «общей» поддержки проекта. Свойства $(Configuration) и $(Platform) определяются в «общей» поддержке проекта после содержимого Directory.Build.props.

Определение Configuration и/или Platform в командной строке меняет это. Свойства в командной строке будут определены как глобальные свойства до импорта Directory.Build.props.

Используя файл решения, MSBuild сначала «переводит» решение в «метапроект». Метапроект строит каждый проект в решении, передавая Configuration и Platform из решения.

Значение по умолчанию для ConfigurationDebug.

Во всех проектах в решении BuildPoc.sln в качестве Platform указано «Любой ЦП». Поскольку используется только один Platform, он будет использоваться по умолчанию.

(Метапроект sln сопоставит «Любой ЦП» в решении с «Любым ЦП» для проектов.)

Почему dotnet build .\BuildPoc.sln -c MyConfig работает? Потому что sln предоставляет проекту значения Configuration и Platform.

Почему dotnet build .\src\MyProject\MyProject.csproj -c MyConfig не работает? Потому что в проекте общие свойства, включая Configuration и Platform, определяются после импорта Directory.Build.props. С переключателем -c. Значение $(Configuration)|$(Platform) равно MyConfig|, когда PropertyGroupCondition оценивается и свойства DebugType, Optimize и DefineConstants не изменяются. (Это также является причиной ошибки MSB3030 при запуске publish для проекта.)

Вы можете подтвердить это, добавив к Directory.Build.props следующее:

  <PropertyGroup>
    <TraceConfiguration Condition = "'$(Configuration)' == ''">Configuration has no value.</TraceConfiguration>
    <TraceConfiguration Condition = "'$(Configuration)' != ''">Configuration has the value '$(Configuration)'.</TraceConfiguration>
    <TracePlatform Condition = "'$(Platform)' == ''">Platform has no value.</TracePlatform>
    <TracePlatform Condition = "'$(Platform)' != ''">Platform has the value '$(Platform)'.</TracePlatform>
  </PropertyGroup>

  <Target Name = "ShowPropsTrace" BeforeTargets = "BeforeBuild">
    <Message Text = "*** $(TraceConfiguration)"/>
    <Message Text = "*** $(TracePlatform)"/>
  </Target>

Как правило, избегайте использования Directory.Build.props и отдавайте предпочтение Directory.Build.targets. Реальная необходимость в очень раннем импорте Directory.Build.props возникает редко и необычно.

Имена Directory.Build.props и Directory.Build.targets произвольны. Оба файла являются «полными» файлами MSBuild без ограничений, т. е. свойства не обязательно должны быть в формате .props.

См. раздел «Как MSBuild создает проекты» и обратите внимание на этапы оценки и выполнения.

Простое исправление решения и проекта — переименовать файл Directory.Build.props в Directory.Build.targets.

Поскольку свойства компилятора связаны только с Configuration, было бы неплохо протестировать только Configuration.

Другие вопросы по теме