check-bin-obj-clash

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Detecting OutputPath and IntermediateOutputPath Clashes

检测 OutputPath 和 IntermediateOutputPath 冲突

Overview

概述

This skill helps identify when multiple MSBuild project evaluations share the same
OutputPath
or
IntermediateOutputPath
. This is a common source of build failures including:
  • File access conflicts during parallel builds
  • Missing or overwritten output files
  • Intermittent build failures
  • "File in use" errors
  • NuGet restore errors like
    Cannot create a file when that file already exists
    - this strongly indicates multiple projects share the same
    IntermediateOutputPath
    where
    project.assets.json
    is written
Clashes can occur between:
  • Different projects sharing the same output directory
  • Multi-targeting builds (e.g.,
    TargetFrameworks=net8.0;net9.0
    ) where the path doesn't include the target framework
  • Multiple solution builds where the same project is built from different solutions in a single build
Note: Project instances with
BuildProjectReferences=false
should be ignored when analyzing clashes - these are P2P reference resolution builds that only query metadata (via
GetTargetPath
) and do not actually write to output directories.
本技能可帮助识别多个 MSBuild 项目评估共享同一个
OutputPath
IntermediateOutputPath
的问题,这是构建失败的常见诱因,包括:
  • 并行构建期间的文件访问冲突
  • 输出文件丢失或被覆盖
  • 偶现的构建失败
  • 「文件被占用」错误
  • 类似
    Cannot create a file when that file already exists
    的 NuGet 还原错误
    ——这强烈说明多个项目共享了同一个写入
    project.assets.json
    IntermediateOutputPath
冲突可能发生在以下场景:
  • 不同项目共享同一个输出目录
  • 多目标构建(例如
    TargetFrameworks=net8.0;net9.0
    )的路径不包含目标框架标识
  • 多解决方案构建中,同一个项目在单次构建流程中被不同的解决方案触发构建
注意: 分析冲突时应忽略
BuildProjectReferences=false
的项目实例——这些是P2P引用解析构建,仅用于查询元数据(通过
GetTargetPath
),不会实际写入输出目录。

When to Use This Skill

何时使用本技能

Invoke this skill immediately when you see:
  • Cannot create a file when that file already exists
    during NuGet restore
  • The process cannot access the file because it is being used by another process
  • Intermittent build failures that succeed on retry
  • Missing output files or unexpected overwriting
当遇到以下情况时请立即调用本技能:
  • NuGet 还原过程中报
    Cannot create a file when that file already exists
  • The process cannot access the file because it is being used by another process
  • 重试后可成功的偶现构建失败
  • 输出文件丢失或出现非预期覆盖

Step 1: Generate a Binary Log

步骤1:生成二进制日志

Use the
binlog-generation
skill to generate a binary log with the correct naming convention.
使用
binlog-generation
技能,按照规范命名生成二进制日志。

Step 2: Replay the Binary Log to Text

步骤2:将二进制日志重放为文本格式

bash
dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log
bash
dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log

Step 3: List All Projects

步骤3:列出所有参与构建的项目

bash
grep -i 'done building project\|Building project' full.log | grep -oP '"[^"]+\.csproj"' | sort -u
This lists all project files that participated in the build.
bash
grep -i 'done building project\|Building project' full.log | grep -oP '"[^"]+\.csproj"' | sort -u
该命令会列出所有参与本次构建的项目文件。

Step 4: Check for Multiple Evaluations per Project

步骤4:检查每个项目的评估次数

Multiple evaluations for the same project indicate multi-targeting or multiple build configurations:
bash
undefined
同一个项目出现多次评估说明存在多目标构建或多构建配置:
bash
undefined

Count how many times each project was evaluated

统计每个项目的评估次数

grep -c 'Evaluation started' full.log grep 'Evaluation started.*.csproj' full.log
undefined
grep -c 'Evaluation started' full.log grep 'Evaluation started.*.csproj' full.log
undefined

Step 5: Check Global Properties for Each Evaluation

步骤5:检查每次评估的全局属性

For each project, query the build properties to understand the build configuration:
bash
undefined
针对每个项目,查询构建属性以了解构建配置:
bash
undefined

Search the diagnostic log for evaluated property values

在诊断日志中搜索评估后的属性值

grep -i 'TargetFramework|Configuration|Platform|RuntimeIdentifier' full.log | head -40

Look for properties like `TargetFramework`, `Configuration`, `Platform`, and `RuntimeIdentifier` that should differentiate output paths.

Also check **solution-related properties** to identify multi-solution builds:
- `SolutionFileName`, `SolutionName`, `SolutionPath`, `SolutionDir`, `SolutionExt` — differ when a project is built from multiple solutions
- `CurrentSolutionConfigurationContents` — the number of project entries reveals which solution an evaluation belongs to (e.g., 1 project vs ~49 projects)

Look for **extra global properties that don't affect output paths** but create distinct MSBuild project instances:
- `PublishReadyToRun` — a publish setting that doesn't change `OutputPath` or `IntermediateOutputPath`, but MSBuild treats it as a distinct project instance, preventing result caching and causing redundant target execution (e.g., `CopyFilesToOutputDirectory` running again)
- Any other global property that differs between evaluations but doesn't contribute to path differentiation
grep -i 'TargetFramework|Configuration|Platform|RuntimeIdentifier' full.log | head -40

重点查找可以区分输出路径的属性,例如`TargetFramework`、`Configuration`、`Platform`、`RuntimeIdentifier`。

同时检查**解决方案相关属性**以识别多解决方案构建:
- `SolutionFileName`、`SolutionName`、`SolutionPath`、`SolutionDir`、`SolutionExt`——当项目从多个解决方案构建时,这些属性值会不同
- `CurrentSolutionConfigurationContents`——其中的项目条目数量可以说明评估属于哪个解决方案(例如1个项目 vs 约49个项目)

查找**不会影响输出路径但会生成独立MSBuild项目实例的额外全局属性**:
- `PublishReadyToRun`——发布设置,不会修改`OutputPath`或`IntermediateOutputPath`,但MSBuild会将其识别为独立的项目实例,导致结果缓存失效、目标重复执行(例如`CopyFilesToOutputDirectory`重复运行)
- 其他不同评估之间存在差异但不会影响路径区分的全局属性

Filter Out Non-Build Evaluations

过滤非构建评估

When analyzing clashes, filter evaluations based on the type of clash you're investigating:
  1. For OutputPath clashes: Exclude restore-phase evaluations (where
    MSBuildRestoreSessionId
    global property is set). These don't write to output directories.
  2. For IntermediateOutputPath clashes: Include restore-phase evaluations, as NuGet restore writes
    project.assets.json
    to the intermediate output path.
  3. Always exclude
    BuildProjectReferences=false
    : These are P2P metadata queries, not actual builds that write files.
分析冲突时,可根据你排查的冲突类型过滤评估:
  1. 排查OutputPath冲突:排除还原阶段的评估(设置了
    MSBuildRestoreSessionId
    全局属性的评估),这类评估不会写入输出目录。
  2. 排查IntermediateOutputPath冲突:包含还原阶段的评估,因为NuGet还原会向中间输出路径写入
    project.assets.json
  3. 始终排除
    BuildProjectReferences=false
    的评估
    :这类是P2P元数据查询,不是实际会写入文件的构建流程。

Step 6: Get Output Paths for Each Project

步骤6:获取每个项目的输出路径

Query each project's output path properties:
bash
undefined
查询每个项目的输出路径属性:
bash
undefined

From the diagnostic log - search for OutputPath assignments

从诊断日志中搜索OutputPath配置

grep -i 'OutputPath\s*=|IntermediateOutputPath\s*=|BaseOutputPath\s*=|BaseIntermediateOutputPath\s*=' full.log | head -40
grep -i 'OutputPath\s*=|IntermediateOutputPath\s*=|BaseOutputPath\s*=|BaseIntermediateOutputPath\s*=' full.log | head -40

Or query a specific project directly

或者直接查询指定项目的配置

dotnet msbuild MyProject.csproj -getProperty:OutputPath dotnet msbuild MyProject.csproj -getProperty:IntermediateOutputPath dotnet msbuild MyProject.csproj -getProperty:BaseOutputPath dotnet msbuild MyProject.csproj -getProperty:BaseIntermediateOutputPath
undefined
dotnet msbuild MyProject.csproj -getProperty:OutputPath dotnet msbuild MyProject.csproj -getProperty:IntermediateOutputPath dotnet msbuild MyProject.csproj -getProperty:BaseOutputPath dotnet msbuild MyProject.csproj -getProperty:BaseIntermediateOutputPath
undefined

Step 7: Identify Clashes

步骤7:识别冲突

Compare the
OutputPath
and
IntermediateOutputPath
values across all evaluations:
  1. Normalize paths - Convert to absolute paths and normalize separators
  2. Group by path - Find evaluations that share the same OutputPath or IntermediateOutputPath
  3. Report clashes - Any group with more than one evaluation indicates a clash
对比所有评估的
OutputPath
IntermediateOutputPath
值:
  1. 路径标准化——转换为绝对路径并统一路径分隔符
  2. 按路径分组——找到共享同一个OutputPath或IntermediateOutputPath的评估
  3. 上报冲突——任何包含超过1个评估的分组都说明存在冲突

Step 8: Verify Clashes via CopyFilesToOutputDirectory (Optional)

步骤8:通过CopyFilesToOutputDirectory验证冲突(可选)

As additional evidence for OutputPath clashes, check if multiple project builds execute the
CopyFilesToOutputDirectory
target to the same path. Note that not all clashes manifest here - compilation outputs and other targets may also conflict.
bash
undefined
作为OutputPath冲突的补充证据,可检查是否有多个项目构建向同一路径执行
CopyFilesToOutputDirectory
目标。注意不是所有冲突都会在这一步体现——编译输出和其他目标也可能出现冲突。
bash
undefined

Search for CopyFilesToOutputDirectory target execution per project

搜索每个项目的CopyFilesToOutputDirectory目标执行记录

grep 'Target "CopyFilesToOutputDirectory"' full.log
grep 'Target "CopyFilesToOutputDirectory"' full.log

Look for Copy task messages showing file destinations

查找显示文件目标路径的Copy任务消息

grep 'Copying file from|SkipUnchangedFiles' full.log | head -30

Look for evidence of clashes in the messages:
- `Copying file from "..." to "..."` - Active file writes
- `Did not copy from file "..." to file "..." because the "SkipUnchangedFiles" parameter was set to "true"` - Indicates a second build attempted to write to the same location

The `SkipUnchangedFiles` skip message often masks clashes - the build succeeds but is vulnerable to race conditions in parallel builds.
grep 'Copying file from|SkipUnchangedFiles' full.log | head -30

在消息中查找冲突证据:
- `Copying file from "..." to "..."`——活跃的文件写入操作
- `Did not copy from file "..." to file "..." because the "SkipUnchangedFiles" parameter was set to "true"`——说明第二次构建尝试写入同一个位置

`SkipUnchangedFiles`跳过消息通常会掩盖冲突——构建会成功,但并行构建时存在竞态条件风险。

Step 9: Check CoreCompile Execution Patterns (Optional)

步骤9:检查CoreCompile执行模式(可选)

To understand which project instance did the actual compilation vs redundant work, check
CoreCompile
:
bash
grep 'Target "CoreCompile"' full.log
Compare the durations:
  • The instance with a long
    CoreCompile
    duration (e.g., seconds) is the primary build that did the actual compilation
  • Instances where
    CoreCompile
    was skipped (duration ~0-10ms) are redundant builds — they didn't recompile but may still run other targets like
    CopyFilesToOutputDirectory
    that write to the same output directory
This helps distinguish the "real" build from redundant instances created by extra global properties or multi-solution builds.
要区分实际执行编译的项目实例和冗余实例,可检查
CoreCompile
bash
grep 'Target "CoreCompile"' full.log
对比执行时长:
  • CoreCompile
    执行时长久(例如数秒)的实例是主构建,执行了实际的编译工作
  • CoreCompile
    被跳过的实例(时长约0-10ms)是冗余构建——它们没有重新编译,但仍可能执行其他会写入同一输出目录的目标,例如
    CopyFilesToOutputDirectory
这有助于区分「真实」构建和由额外全局属性、多解决方案构建生成的冗余实例。

Caveat: Multi-Solution Builds

注意:多解决方案构建

When analyzing multi-solution builds, note that the diagnostic log interleaves output from all projects. To determine which solution a project instance belongs to, search for
SolutionFileName
property assignments in the diagnostic log:
bash
grep -i "SolutionFileName\|CurrentSolutionConfigurationContents" full.log | head -20
分析多解决方案构建时,请注意诊断日志会交错显示所有项目的输出。要确定项目实例属于哪个解决方案,可在诊断日志中搜索
SolutionFileName
属性配置:
bash
grep -i "SolutionFileName\|CurrentSolutionConfigurationContents" full.log | head -20

Expected Output Structure

预期输出结构

For each evaluation, collect:
  • Project file path
  • Evaluation ID
  • TargetFramework (if multi-targeting)
  • Configuration
  • OutputPath
  • IntermediateOutputPath
为每个评估收集以下信息:
  • 项目文件路径
  • 评估ID
  • TargetFramework(如果是多目标构建)
  • Configuration
  • OutputPath
  • IntermediateOutputPath

Clash Detection Logic

冲突检测逻辑

For each unique OutputPath:
  - If multiple evaluations share it → CLASH
  
For each unique IntermediateOutputPath:
  - If multiple evaluations share it → CLASH
对于每个唯一的OutputPath:
  - 如果多个评估共享该路径 → 存在冲突
  
对于每个唯一的IntermediateOutputPath:
  - 如果多个评估共享该路径 → 存在冲突

Common Causes and Fixes

常见原因与修复方案

Multi-targeting without TargetFramework in path

多目标构建的路径未包含TargetFramework

Problem: Project uses
TargetFrameworks
but OutputPath doesn't vary by framework.
xml
<!-- BAD: Same path for all frameworks -->
<OutputPath>bin\$(Configuration)\</OutputPath>
Fix: Include TargetFramework in the path:
xml
<!-- GOOD: Path varies by framework -->
<OutputPath>bin\$(Configuration)\$(TargetFramework)\</OutputPath>
Or rely on SDK defaults which handle this automatically:
xml
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<AppendTargetFrameworkToIntermediateOutputPath>true</AppendTargetFrameworkToIntermediateOutputPath>
问题: 项目使用了
TargetFrameworks
但OutputPath没有按框架区分。
xml
<!-- 错误:所有框架使用相同路径 -->
<OutputPath>bin\$(Configuration)\</OutputPath>
修复: 在路径中加入TargetFramework:
xml
<!-- 正确:路径按框架区分 -->
<OutputPath>bin\$(Configuration)\$(TargetFramework)\</OutputPath>
或者直接使用SDK默认配置,会自动处理该问题:
xml
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<AppendTargetFrameworkToIntermediateOutputPath>true</AppendTargetFrameworkToIntermediateOutputPath>

Shared output directory across projects (CANNOT be fixed with AppendTargetFramework)

跨项目共享输出目录(无法通过AppendTargetFramework修复)

Problem: Multiple projects explicitly set the same
BaseOutputPath
or
BaseIntermediateOutputPath
.
xml
<!-- Project A - Directory.Build.props -->
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>

<!-- Project B - Directory.Build.props -->
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>
IMPORTANT: Even with
AppendTargetFrameworkToOutputPath=true
, this will still clash! .NET writes certain files directly to the
IntermediateOutputPath
without the TargetFramework suffix, including:
  • project.assets.json
    (NuGet restore output)
  • Other NuGet-related files
This causes errors like
Cannot create a file when that file already exists
during parallel restore.
Fix: Each project MUST have a unique
BaseIntermediateOutputPath
. Do not share intermediate output directories across projects:
xml
<!-- Project A -->
<BaseIntermediateOutputPath>..\obj\ProjectA\</BaseIntermediateOutputPath>

<!-- Project B -->
<BaseIntermediateOutputPath>..\obj\ProjectB\</BaseIntermediateOutputPath>
Or simply use the SDK defaults which place
obj
inside each project's directory.
问题: 多个项目显式设置了相同的
BaseOutputPath
BaseIntermediateOutputPath
xml
<!-- 项目A的Directory.Build.props -->
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>

<!-- 项目B的Directory.Build.props -->
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>
重要提示: 即使设置了
AppendTargetFrameworkToOutputPath=true
,仍然会出现冲突!.NET会直接向
IntermediateOutputPath
写入某些不带TargetFramework后缀的文件,包括:
  • project.assets.json
    (NuGet还原输出)
  • 其他NuGet相关文件
这会导致并行还原过程中出现
Cannot create a file when that file already exists
这类错误。
修复: 每个项目必须有独立的
BaseIntermediateOutputPath
,不要跨项目共享中间输出目录:
xml
<!-- 项目A -->
<BaseIntermediateOutputPath>..\obj\ProjectA\</BaseIntermediateOutputPath>

<!-- 项目B -->
<BaseIntermediateOutputPath>..\obj\ProjectB\</BaseIntermediateOutputPath>
或者直接使用SDK默认配置,将
obj
目录放在每个项目的目录下。

RuntimeIdentifier builds clashing

RuntimeIdentifier构建冲突

Problem: Building for multiple RIDs without RID in path.
Fix: Ensure RuntimeIdentifier is in the path:
xml
<AppendRuntimeIdentifierToOutputPath>true</AppendRuntimeIdentifierToOutputPath>
问题: 为多个RID构建但路径中未包含RID。
修复: 确保路径中包含RuntimeIdentifier:
xml
<AppendRuntimeIdentifierToOutputPath>true</AppendRuntimeIdentifierToOutputPath>

Multiple solutions building the same project

多个解决方案构建同一个项目

Problem: A single build invokes multiple solutions (e.g., via MSBuild task or command line) that include the same project. Each solution build evaluates and builds the project independently, with different
Solution*
global properties that don't affect the output path.
How to detect: Compare
SolutionFileName
and
CurrentSolutionConfigurationContents
across evaluations for the same project. Different values indicate multi-solution builds. For example:
PropertyEval from Solution AEval from Solution B
SolutionFileName
BuildAnalyzers.sln
Main.slnx
CurrentSolutionConfigurationContents
1 project entry~49 project entries
OutputPath
bin\Release\netstandard2.0\
bin\Release\netstandard2.0\
clash
Example: A repo build script builds
BuildAnalyzers.sln
then
Main.slnx
, and both solutions include
SharedAnalyzers.csproj
. Both builds write to
bin\Release\netstandard2.0\
. The first build compiles; the second skips compilation but still runs
CopyFilesToOutputDirectory
.
Fix: Options include:
  1. Consolidate solutions - Ensure each project is only built from one solution in a single build
  2. Use different configurations - Build solutions with different
    Configuration
    values that result in different output paths
  3. Exclude duplicate projects - Use solution filters or conditional project inclusion to avoid building the same project twice
问题: 单次构建流程调用了多个解决方案(例如通过MSBuild任务或命令行),这些解决方案包含同一个项目。每个解决方案构建会独立评估和构建该项目,使用不同的
Solution*
全局属性,而这些属性不会影响输出路径。
检测方式: 对比同一个项目不同评估的
SolutionFileName
CurrentSolutionConfigurationContents
,值不同说明存在多解决方案构建。例如:
属性从解决方案A评估从解决方案B评估
SolutionFileName
BuildAnalyzers.sln
Main.slnx
CurrentSolutionConfigurationContents
1个项目条目约49个项目条目
OutputPath
bin\Release\netstandard2.0\
bin\Release\netstandard2.0\
冲突
示例: 代码库构建脚本先构建
BuildAnalyzers.sln
再构建
Main.slnx
,两个解决方案都包含
SharedAnalyzers.csproj
,两次构建都写入
bin\Release\netstandard2.0\
。第一次构建完成编译,第二次构建跳过编译但仍会执行
CopyFilesToOutputDirectory
修复: 可选方案包括:
  1. 合并解决方案——确保单次构建流程中每个项目仅被一个解决方案构建
  2. 使用不同配置——为不同解决方案构建使用不同的
    Configuration
    值,生成不同的输出路径
  3. 排除重复项目——使用解决方案过滤器或条件项目引入逻辑,避免重复构建同一个项目

Extra global properties creating redundant project instances

额外全局属性生成冗余项目实例

Problem: A project is built multiple times within the same solution due to extra global properties (e.g.,
PublishReadyToRun=false
) that create distinct MSBuild project instances. These properties don't affect output paths but prevent MSBuild from caching results across instances, causing redundant target execution.
How to detect: Compare global properties across evaluations for the same project within the same solution (same
SolutionFileName
). Look for properties that differ but don't contribute to path differentiation:
PropertyEval A (from Razor.slnx)Eval B (from Razor.slnx)
PublishReadyToRun
(not set)
false
OutputPath
bin\Release\netstandard2.0\
bin\Release\netstandard2.0\
clash
This is particularly wasteful for projects where the extra property has no effect (e.g.,
PublishReadyToRun
on a
netstandard2.0
class library that doesn't use ReadyToRun compilation).
Fix: Options include:
  1. Remove the extra global property - Investigate which parent target/task is injecting the property and prevent it from being passed to projects that don't need it
  2. Use
    RemoveGlobalProperties
    metadata
    - On
    ProjectReference
    items, use
    RemoveGlobalProperties="PublishReadyToRun"
    to strip the property before building the referenced project
  3. Condition the property - Only set the property on projects that actually use it (e.g., only for executable projects, not class libraries)
问题: 同一个解决方案内的项目被多次构建,原因是额外的全局属性(例如
PublishReadyToRun=false
)生成了独立的MSBuild项目实例。这些属性不会影响输出路径,但会阻止MSBuild跨实例缓存结果,导致目标重复执行。
检测方式: 对比同一个解决方案内(
SolutionFileName
相同)同一个项目的不同评估的全局属性,查找存在差异但不会影响路径区分的属性:
属性评估A(来自Razor.slnx)评估B(来自Razor.slnx)
PublishReadyToRun
(未设置)
false
OutputPath
bin\Release\netstandard2.0\
bin\Release\netstandard2.0\
冲突
对于额外属性没有实际作用的项目,这种问题尤其浪费资源(例如
netstandard2.0
类库不需要ReadyToRun编译,设置
PublishReadyToRun
没有作用)。
修复: 可选方案包括:
  1. 移除额外全局属性——排查是哪个父目标/任务注入了该属性,避免将其传递给不需要的项目
  2. 使用
    RemoveGlobalProperties
    元数据
    ——在
    ProjectReference
    项上配置
    RemoveGlobalProperties="PublishReadyToRun"
    ,在构建引用项目前剥离该属性
  3. 为属性添加条件——仅在实际需要的项目上设置该属性(例如仅对可执行项目设置,不对类库设置)

Example Workflow

示例工作流

bash
undefined
bash
undefined

1. Replay the binlog

1. 重放binlog

dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log
dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log

2. List projects

2. 列出项目

grep 'done building project' full.log | grep -oP '"[^"]+.csproj"' | sort -u
grep 'done building project' full.log | grep -oP '"[^"]+.csproj"' | sort -u

3. Check OutputPath for each evaluation

3. 检查每次评估的OutputPath

grep -i 'OutputPath\s*=' full.log | sort -u
grep -i 'OutputPath\s*=' full.log | sort -u

e.g. OutputPath = bin\Debug\net8.0\

示例输出: OutputPath = bin\Debug\net8.0\

OutputPath = bin\Debug\net9.0\

OutputPath = bin\Debug\net9.0\

4. Check IntermediateOutputPath

4. 检查IntermediateOutputPath

grep -i 'IntermediateOutputPath\s*=' full.log | sort -u
grep -i 'IntermediateOutputPath\s*=' full.log | sort -u

e.g. IntermediateOutputPath = obj\Debug\net8.0\

示例输出: IntermediateOutputPath = obj\Debug\net8.0\

IntermediateOutputPath = obj\Debug\net9.0\

IntermediateOutputPath = obj\Debug\net9.0\

5. Compare paths → No clash (paths differ by TargetFramework)

5. 对比路径 → 无冲突(路径按TargetFramework区分)

undefined
undefined

Tips

提示

  • Use
    grep -i 'OutputPath\s*=' full.log | sort -u
    to quickly find all OutputPath property assignments
  • Check
    BaseOutputPath
    and
    BaseIntermediateOutputPath
    as they form the root of output paths
  • The SDK default paths include
    $(TargetFramework)
    - clashes often occur when projects override these defaults
  • Remember that paths may be relative - normalize to absolute paths before comparing
  • Cross-project IntermediateOutputPath clashes cannot be fixed with
    AppendTargetFrameworkToOutputPath
    - files like
    project.assets.json
    are written directly to the intermediate path
  • For multi-targeting clashes within the same project,
    AppendTargetFrameworkToOutputPath=true
    is the correct fix
  • Common error messages indicating path clashes:
    • Cannot create a file when that file already exists
      (NuGet restore)
    • The process cannot access the file because it is being used by another process
    • Intermittent build failures that succeed on retry
  • 使用
    grep -i 'OutputPath\s*=' full.log | sort -u
    可快速查找所有OutputPath属性配置
  • 检查
    BaseOutputPath
    BaseIntermediateOutputPath
    ,因为它们是输出路径的根路径
  • SDK默认路径包含
    $(TargetFramework)
    ——项目覆盖这些默认配置时通常会出现冲突
  • 注意路径可能是相对路径——对比前请先标准化为绝对路径
  • 跨项目的IntermediateOutputPath冲突无法通过
    AppendTargetFrameworkToOutputPath
    修复
    ——
    project.assets.json
    这类文件会直接写入中间路径
  • 同一个项目内的多目标冲突,正确修复方案是设置
    AppendTargetFrameworkToOutputPath=true
  • 提示路径冲突的常见错误信息:
    • Cannot create a file when that file already exists
      (NuGet还原阶段)
    • The process cannot access the file because it is being used by another process
    • 重试后可成功的偶现构建失败

Global Properties to Check When Comparing Evaluations

对比评估时需要检查的全局属性

When multiple evaluations share an output path, compare these global properties to understand why:
PropertyAffects OutputPath?Notes
TargetFramework
YesDifferent TFMs should have different paths
RuntimeIdentifier
YesDifferent RIDs should have different paths
Configuration
YesDebug vs Release
Platform
YesAnyCPU vs x64 etc.
SolutionFileName
NoIdentifies which solution built the project — different values indicate multi-solution clash
SolutionName
NoSolution name without extension
SolutionPath
NoFull path to the solution file
SolutionDir
NoDirectory containing the solution file
CurrentSolutionConfigurationContents
NoXML with project entries — count of entries reveals which solution
BuildProjectReferences
No
false
= P2P query, not a real build - ignore these
MSBuildRestoreSessionId
NoPresent = restore phase evaluation
PublishReadyToRun
NoPublish setting, doesn't change build output path but creates distinct project instances
当多个评估共享同一个输出路径时,对比以下全局属性可定位原因:
属性是否影响OutputPath?说明
TargetFramework
不同TFM应该有不同路径
RuntimeIdentifier
不同RID应该有不同路径
Configuration
Debug与Release的区别
Platform
AnyCPU与x64等的区别
SolutionFileName
标识构建项目的解决方案——值不同说明是多解决方案冲突
SolutionName
不带后缀的解决方案名称
SolutionPath
解决方案文件的完整路径
SolutionDir
解决方案文件所在目录
CurrentSolutionConfigurationContents
包含项目条目的XML——条目数量可识别对应的解决方案
BuildProjectReferences
false
= P2P查询,不是真实构建——忽略这类评估
MSBuildRestoreSessionId
存在该属性说明是还原阶段评估
PublishReadyToRun
发布设置,不会修改构建输出路径但会生成独立的项目实例

Testing Fixes

测试修复效果

After making changes to fix path clashes, clean and rebuild to verify. See the
binlog-generation
skill's "Cleaning the Repository" section on how to clean the repository while preserving binlog files.
修改配置修复路径冲突后,请清理并重新构建验证效果。清理代码库同时保留binlog文件的方法可参考
binlog-generation
技能的「清理代码库」章节。