К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

directory-build-organization — скилл для MSBuild в Claude Code

Скилл решает, что вынести в Directory.Build.props, .targets и .rsp: несколько проектов перестают дублировать одну и ту же политику MSBuild.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add dotnet/skills --skill directory-build-organization -a claude-code
Открыть на GitHub

Что делает directory-build-organization

Скилл разбирает build-инфраструктуру .NET-репозитория: что положено в Directory.Build.props, что в Directory.Build.targets, а что в Directory.Packages.props. Логика простая. Microsoft.Common.props подтягивает ближайший Directory.Build.props до тела проекта, поэтому общие значения проект ещё может переопределить. .targets приходят позже через Microsoft.Common.targets, и переопределить их из проекта уже нельзя.

Внутри — правила и разборы: централизованные версии через ManagePackageVersionsCentrally, GlobalPackageReference для анализаторов на все проекты, многоуровневая иерархия с явным импортом родителя через GetPathOfFileAbove. Отдельная ловушка: условие на $(TargetFramework) в .props молча не срабатывает в проектах с одной целью — такое свойство переносят в .targets.

Границы жёсткие. Репозиторий с одним проектом без готового Directory.Build файла скилл не загружают. Миграцию со старого формата на SDK-style он не трогает, семантику значений свойств отдаёт соседнему property-patterns. На вопрос «как нам это организовать» он смотрит реальные файлы проекта и отдаёт предложенную раскладку, ничего не правя без прямой просьбы.

Какие задачи решает

  • свести повторяющиеся настройки MSBuild из нескольких проектов в один Directory.Build.props
  • разложить версии пакетов по Directory.Packages.props
  • найти, почему условие на $(TargetFramework) не срабатывает в .props
  • собрать многоуровневую иерархию с импортом родительского файла
  • вынести общие аргументы командной строки MSBuild в Directory.Build.rsp

Примеры запросов агенту

  • У нас три проекта, настройки MSBuild копируются из файла в файл. Предложи раскладку `Directory.Build.props` и `.targets`, файлы пока не меняй.
  • Проверь нашу иерархию `Directory.Build.props`: импорт родителя, порядок слоёв, что где лежит.
  • Условие на `$(TargetFramework)` в `Directory.Build.props` ничего не делает. Объясни почему и скажи, куда это перенести.

Как установить directory-build-organization

1Через Skills CLI (Vercel)

npx skills add dotnet/skills --skill directory-build-organization -a claude-code

2Вручную: положить файлы

~/.claude/skills/directory-build-organization/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/directory-build-organization/

Из того же набора5

Весь набор →

Похожие

assuredworkloads-environment-assessor официальный google Оценивает ресурсы Google Cloud на соответствие нормам суверенитета данных и стандартам compliance. Помогает подобрать фреймворк Assured Workloads до развёртывания. Claude Code Gemini CLI CX Codex 475установок gke-ai-troubleshooting-tpu-slice-mig-stuck-updating официальный google Диагностирует сбои создания TPU Dynamic Slice и зависшие JobSet, когда MIG находится в нестабильном состоянии. Подходит для разбора проблем GKE. Claude Code Gemini CLI CX Codex 440установок asc-submission-health rorkai Скилл для Claude Code поверх CLI asc: проверяет готовность версии к отправке, называет блокеры и говорит, что чинить. Claude Code CX Codex Cursor +1 8 000установок gke-ai-troubleshooting-tpu-vm-repair-stuck официальный google Диагностирует TPU VM в GKE, которые застряли в состоянии REPAIRING после ошибок хоста. Нужен, когда TPU-срез нельзя запланировать из-за VM в ремонте. Claude Code Gemini CLI CX Codex 431установок asc-metadata-sync rorkai Скилл для CLI asc: тянет метаданные App Store Connect в локальные JSON, проверяет их и заливает назад. Пригодится при правке локализаций, ключевых слов и ассетов. Claude Code CX Codex Cursor +1 7 800установок asc-xcode-build rorkai Скилл учит агента собирать Xcode-проект, делать архив и IPA через CLI asc, а ещё править номера версии и сборки. Пригодится перед загрузкой в App Store Connect или TestFlight. Claude Code CX Codex Cursor +1 7 600установок wizard Matt Pocock Скилл создаёт интерактивный bash-скрипт для ручных шагов: настройки сервисов, секретов CI и разовых миграций. Claude Code 553 369установок hyperframes-cli heygen-com Управляет проектами HyperFrames через терминал: собирает таймлайн, проверяет контраст кадров, запускает предпросмотр и рендерит видео локально или в облаке. Claude Code CX Codex Cursor +1 1 200 000установок

Вопросы о directory-build-organization

Как установить directory-build-organization в Claude Code?

Выполните npx skills add dotnet/skills --skill directory-build-organization -a claude-code. Файл скилла окажется по пути ~/.claude/skills/directory-build-organization/SKILL.md.

Что делает directory-build-organization?

Показывает, какие свойства, цели и версии пакетов вынести в Directory.Build.props, .targets, .rsp и Directory.Packages.props, опираясь на реальные файлы проекта, а не на имена соседних папок.

Подойдёт для репозитория с одним проектом?

Нет, если готового Directory.Build файла там нет — такой случай вне области скилла. Он рассчитан на два и более проекта с повторяющейся политикой MSBuild или на существующую иерархию с дефектом импорта или слоёв.

Исходный текст

SKILL.md · MIT
---
name: directory-build-organization
description: "USE ONLY for (1) two or more projects with repeated MSBuild policy, targets, or package versions, or (2) an existing Directory.Build.props/targets/rsp hierarchy with an import, placement, or layering defect. A one-project repo without an existing Directory.Build file is outside scope; do not load this skill. Covers centralizing shared policy and targets, Directory.Packages.props across projects, parent hierarchy/import structure, props-versus-targets placement, and folder/project exceptions. An existing hierarchy defect remains in scope when only one project is affected. For property value or condition semantics use property-patterns. Exclude legacy-to-SDK migration and non-MSBuild systems."
license: MIT
---

# Organizing Build Infrastructure with Directory.Build Files

## Intent control

- For "should we", "how should we organize", "recommend", "advise", or review
  requests, inspect the actual project files and return a proposed layout only.
  Do not create or edit files unless the user explicitly asks to apply, move,
  centralize, or clean up the configuration.
- Before summarizing, verify which project retains each project-specific
  property, item, or target. Name the actual file; do not infer it from sibling
  names.
- Recommend a verification command only after discovering a real `.sln`,
  `.slnx`, `.proj`, or project file at that path. If no repo-root entry point
  exists, give commands for the discovered projects or state that the entry
  point was not found.
- Every advice response must explain that `Microsoft.Common.props` searches
  upward from each project and automatically imports the nearest
  `Directory.Build.props` early; project values can then override shared
  defaults. Explain the equivalent late `Microsoft.Common.targets` import when
  recommending `Directory.Build.targets`.

## Directory.Build.props vs Directory.Build.targets

Understanding which file to use is critical. They differ in **when** they are imported during evaluation:

**Evaluation order:**

```
Microsoft.Common.props imports Directory.Build.props early
→ project body and package/project imports evaluate
→ Microsoft.Common.targets imports Directory.Build.targets late
```

| Use `.props` for | Use `.targets` for |
|---|---|
| Setting property defaults | Custom build targets |
| Common item definitions | Late-bound property overrides |
| Properties projects can override | Post-build steps |
| Assembly/package metadata | Conditional logic on final values |
| Analyzer PackageReferences | Targets that depend on SDK-defined properties |

**Rule of thumb:** Properties and items go in `.props`. Custom targets and late-bound logic go in `.targets`.

Because `.props` is imported before the project file, the project can override any value set there. Because `.targets` is imported after everything, it gets the final say—but projects cannot override `.targets` values.

### ⚠️ Critical: TargetFramework Availability in .props vs .targets

**Property conditions on `$(TargetFramework)` in `.props` files silently fail for single-targeting projects** — the property is empty during `.props` evaluation. Move TFM-conditional properties to `.targets` instead. ItemGroup and Target conditions are not affected.

See [targetframework-props-pitfall.md](references/targetframework-props-pitfall.md) for the full explanation.

## Directory.Build.props

Good candidates: language settings, assembly/package metadata, build warnings, code analysis, common analyzers.

```xml
<Project>
  <PropertyGroup>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
    <Company>Contoso</Company>
    <Authors>Contoso Engineering</Authors>
  </PropertyGroup>
</Project>
```

**Do NOT put here:** project-specific TFMs, project-specific PackageReferences, targets/build logic, or properties depending on SDK-defined values (not available during `.props` evaluation).

## Directory.Build.targets

Good candidates: custom build targets, late-bound property overrides (values depending on SDK properties), post-build validation.

```xml
<Project>
  <Target Name="ValidateProjectSettings" BeforeTargets="Build">
    <Error Text="All libraries must target netstandard2.0 or higher"
           Condition="'$(OutputType)' == 'Library' AND '$(TargetFramework)' == 'net472'" />
  </Target>

  <PropertyGroup>
    <!-- DocumentationFile depends on OutputPath, which is set by the SDK -->
    <DocumentationFile Condition="'$(IsPackable)' == 'true'">$(OutputPath)$(AssemblyName).xml</DocumentationFile>
  </PropertyGroup>
</Project>
```

## Directory.Packages.props (Central Package Management)

Central Package Management (CPM) provides a single source of truth for all NuGet package versions. See [https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management](https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management) for details.

**Enable CPM in `Directory.Packages.props` at the repo root:**

```xml
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageVersion Include="xunit" Version="2.9.0" />
    <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
  </ItemGroup>

  <ItemGroup>
    <!-- GlobalPackageReference applies to ALL projects — great for analyzers -->
    <GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
    <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" />
  </ItemGroup>
</Project>
```

## Directory.Build.rsp

Contains default MSBuild CLI arguments applied to all builds under the directory tree.

**Example `Directory.Build.rsp`:**

```
/maxcpucount
/nodeReuse:false
/consoleLoggerParameters:Summary;ForceNoAlign
/warnAsMessage:MSB3277
```

- Works with both `msbuild` and `dotnet` CLI in modern .NET versions
- Great for enforcing consistent CI and local build flags
- Each argument goes on its own line

## Multi-level Directory.Build Files

MSBuild only auto-imports the **first** `Directory.Build.props` (or `.targets`) it finds walking up from the project directory. To chain multiple levels, explicitly import the parent at the **top** of the inner file. See [multi-level-examples](references/multi-level-examples.md) for full file examples.

```xml
<Project>
  <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"
         Condition="Exists('$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))')" />

  <!-- Inner-level overrides go here -->
</Project>
```

**Example layout:**

```
repo/
  Directory.Build.props          ← repo-wide (lang version, company info, analyzers)
  Directory.Build.targets        ← repo-wide targets
  Directory.Packages.props       ← central package versions
  src/
    Directory.Build.props        ← src-specific (imports repo-level, sets IsPackable=true)
  test/
    Directory.Build.props        ← test-specific (imports repo-level, sets IsPackable=false, adds test packages)
```

## Artifact Output Layout (.NET 8+)

Set `<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>` in `Directory.Build.props` to automatically produce project-name-separated `bin/`, `obj/`, and `publish/` directories under a single `artifacts/` folder, avoiding bin/obj clashes by default. See [common-patterns](references/common-patterns.md) for the directory layout and additional patterns (conditional settings by project type, post-pack validation).

## Workflow: Organizing Build Infrastructure

1. **Audit all `.csproj` files** — Catalog every `<PropertyGroup>`, `<ItemGroup>`, and custom `<Target>` across the solution. Note which settings repeat and which are project-specific.
2. **Create root `Directory.Build.props`** — Move shared property defaults (LangVersion, Nullable, TreatWarningsAsErrors, metadata) here. These are imported before the project file so projects can override them.
3. **Create root `Directory.Build.targets`** — Move custom build targets, post-build validation, and any properties that depend on SDK-defined values (e.g., `OutputPath`, `TargetFramework` for single-targeting projects) here. These are imported after the SDK so all properties are available.
4. **Create `Directory.Packages.props`** — Enable Central Package Management (`ManagePackageVersionsCentrally`), list all `PackageVersion` entries, and remove `Version=` from `PackageReference` items in `.csproj` files.
5. **Set up multi-level hierarchy** — Create inner `Directory.Build.props` files for `src/` and `test/` folders with distinct settings. Use `GetPathOfFileAbove` to chain to the parent.
6. **Simplify `.csproj` files** — Remove all centralized properties, version attributes, and duplicated targets. Each project should only contain what is unique to it.
7. **Validate** — Run restore/build against the discovered `.sln`, `.slnx`,
   `.proj`, or project path, for example
   `dotnet restore <entrypoint> && dotnet build <entrypoint>`. If no root
   entrypoint exists, validate each discovered project explicitly instead of
   claiming a repo-root build. Use
   `dotnet msbuild <project> -pp:output.xml` to inspect the final merged view.

## Troubleshooting

| Problem | Cause | Fix |
|---|---|---|
| `Directory.Build.props` isn't picked up | File name casing wrong (exact match required on Linux/macOS) | Verify exact casing: `Directory.Build.props` (capital D, B) |
| Properties from `.props` are ignored by projects | Project sets the same property after the import | Move the property to `Directory.Build.targets` to set it after the project |
| Multi-level import doesn't work | Missing `GetPathOfFileAbove` import in inner file | Add the `<Import>` element at the top of the inner file (see Multi-level section) |
| Properties using SDK values are empty in `.props` | SDK properties aren't defined yet during `.props` evaluation | Move to `.targets` which is imported after the SDK |
| `Directory.Packages.props` not found | File not at repo root or not named exactly | Must be named `Directory.Packages.props` and at or above the project directory |
| Property condition on `$(TargetFramework)` doesn't match in `.props` | `TargetFramework` isn't set yet for single-targeting projects during `.props` evaluation | Move property to `.targets`, or use ItemGroup/Target conditions instead (which evaluate late) |

**Diagnosis:** Use the preprocessed project output to see all imports and final property values:

```bash
dotnet msbuild -pp:output.xml MyProject.csproj
```

This expands all imports inline so you can see exactly where each property is set and what the final evaluated value is.

© dotnet · MIT · dotnet/skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой