Skip to content

Fix Windows CI by scoping IntermediateOutputPath per framework - #396

Merged
thejambi merged 2 commits into
masterfrom
fix/tfm-scoped-intermediate-output
Aug 14, 2026
Merged

Fix Windows CI by scoping IntermediateOutputPath per framework#396
thejambi merged 2 commits into
masterfrom
fix/tfm-scoped-intermediate-output

Conversation

@thejambi

@thejambi thejambi commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Directory.Build.props sets AppendTargetFrameworkToOutputPath=false so that OutputPath can place output under artifacts/$(Configuration)/$(TargetFramework) itself. That flag also strips $(TargetFramework) from IntermediateOutputPath, so all three target frameworks of a multi-targeted project shared a single obj folder - including the reference assembly under obj/ref. Whichever framework built last owned it.

ProjectReference resolution reads that reference assembly, so the netstandard2.0 compile of SIL.LCModel could be handed the net8.0 build of SIL.LCModel.Core:

CSC : error CS1705: Assembly 'SIL.LCModel.Core' ... uses
'System.Drawing.Primitives, Version=8.0.0.0' which has a higher version than
referenced assembly 'System.Drawing.Primitives, Version=4.0.2.0'
[SIL.LCModel.csproj::TargetFramework=netstandard2.0]

Build ordering decided whether this hit, which is why Windows failed while Linux stayed green. #394 removed the OutDir override in SIL.LCModel and fixed the bin side of the same problem; the intermediate side kept sharing one path.

Set IntermediateOutputPath to obj/$(Configuration)/$(TargetFramework)/ in Directory.Build.props, and drop the obj/x86/$(Configuration)/ override in SIL.LCModel.Core.csproj that predates multi-targeting and now conflicts with it - Platform is Any CPU repo-wide, so the x86 segment bought nothing. OutputPath and the artifacts layout are unchanged.


This change is Reviewable

Directory.Build.props sets AppendTargetFrameworkToOutputPath=false so that
OutputPath can place output under artifacts/$(Configuration)/$(TargetFramework)
itself. That flag also strips $(TargetFramework) from IntermediateOutputPath,
so all three target frameworks of a multi-targeted project shared a single obj
folder - including the reference assembly under obj/ref. Whichever framework
built last owned it.

ProjectReference resolution reads that reference assembly, so the
netstandard2.0 compile of SIL.LCModel could be handed the net8.0 build of
SIL.LCModel.Core:

  CSC : error CS1705: Assembly 'SIL.LCModel.Core' ... uses
  'System.Drawing.Primitives, Version=8.0.0.0' which has a higher version than
  referenced assembly 'System.Drawing.Primitives, Version=4.0.2.0'
  [SIL.LCModel.csproj::TargetFramework=netstandard2.0]

Build ordering decided whether this hit, which is why Windows failed while
Linux stayed green. #394 removed the OutDir override in SIL.LCModel and fixed
the bin side of the same problem; the intermediate side kept sharing one path.

Set IntermediateOutputPath to obj/$(Configuration)/$(TargetFramework)/ in
Directory.Build.props, and drop the obj/x86/$(Configuration)/ override in
SIL.LCModel.Core.csproj that predates multi-targeting and now conflicts with
it - Platform is Any CPU repo-wide, so the x86 segment bought nothing.
OutputPath and the artifacts layout are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

LCM Tests

    16 files  +    8      16 suites  +8   2m 9s ⏱️ + 1m 6s
 2 875 tests ±    0   2 855 ✅ +   14   20 💤  - 14  0 ❌ ±0 
11 448 runs  +5 724  11 280 ✅ +5 638  168 💤 +86  0 ❌ ±0 

Results for commit a8af51e. ± Comparison against base commit 6e97da6.

♻️ This comment has been updated with latest results.

@thejambi
thejambi marked this pull request as ready for review August 14, 2026 17:21
@jasonleenaylor

Copy link
Copy Markdown
Contributor

src/SIL.LCModel.Core/SIL.LCModel.Core.csproj line 89 at r1 (raw file):

  <PropertyGroup>
    <!-- IntermediateOutputPath comes from Directory.Build.props, which scopes it per target

This comment is unnecessary, no one will come to this file and go 'huh, why is this property that I don't know about mssing?'

@thejambi

Copy link
Copy Markdown
Contributor Author

src/SIL.LCModel.Core/SIL.LCModel.Core.csproj line 89 at r1 (raw file):

Previously, jasonleenaylor (Jason Naylor) wrote…

This comment is unnecessary, no one will come to this file and go 'huh, why is this property that I don't know about mssing?'

Comments have been removed.

@jasonleenaylor jasonleenaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@jasonleenaylor reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on thejambi).

@thejambi
thejambi merged commit 9fdb060 into master Aug 14, 2026
5 checks passed
@thejambi
thejambi deleted the fix/tfm-scoped-intermediate-output branch August 14, 2026 18:51
thejambi added a commit that referenced this pull request Aug 14, 2026
* Fix Windows CI by scoping IntermediateOutputPath per framework

Directory.Build.props sets AppendTargetFrameworkToOutputPath=false so that
OutputPath can place output under artifacts/$(Configuration)/$(TargetFramework)
itself. That flag also strips $(TargetFramework) from IntermediateOutputPath,
so all three target frameworks of a multi-targeted project shared a single obj
folder - including the reference assembly under obj/ref. Whichever framework
built last owned it.

ProjectReference resolution reads that reference assembly, so the
netstandard2.0 compile of SIL.LCModel could be handed the net8.0 build of
SIL.LCModel.Core:

  CSC : error CS1705: Assembly 'SIL.LCModel.Core' ... uses
  'System.Drawing.Primitives, Version=8.0.0.0' which has a higher version than
  referenced assembly 'System.Drawing.Primitives, Version=4.0.2.0'
  [SIL.LCModel.csproj::TargetFramework=netstandard2.0]

Build ordering decided whether this hit, which is why Windows failed while
Linux stayed green. #394 removed the OutDir override in SIL.LCModel and fixed
the bin side of the same problem; the intermediate side kept sharing one path.

Set IntermediateOutputPath to obj/$(Configuration)/$(TargetFramework)/ in
Directory.Build.props, and drop the obj/x86/$(Configuration)/ override in
SIL.LCModel.Core.csproj that predates multi-targeting and now conflicts with
it - Platform is Any CPU repo-wide, so the x86 segment bought nothing.
OutputPath and the artifacts layout are unchanged.

* Remove comments

Co-Authored-By: Zachary Burnham <zachary_burnham@sil.org>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants