Skip to content

Fix DefaultItemExcludes handling in XSharp.SDK.Props - #2075

Open
hpetriffer wants to merge 2 commits into
X-Sharp:devfrom
hpetriffer:fix/sdk-props-default-item-excludes
Open

Fix DefaultItemExcludes handling in XSharp.SDK.Props#2075
hpetriffer wants to merge 2 commits into
X-Sharp:devfrom
hpetriffer:fix/sdk-props-default-item-excludes

Conversation

@hpetriffer

Copy link
Copy Markdown
Contributor

Two independent defects in XSharp.SDK.Props

Both were found while tracking down sporadic XS9014 / XS9019 errors in a solution where a classic and an SDK-style project share one directory. Each commit stands on its own.

1. DefaultItemExcludes is assigned, not appended

<DefaultItemExcludes>$(VOBinaryFiles);$(AppXamlFiles);$(HeaderFiles);...</DefaultItemExcludes>

Microsoft.NET.Sdk.DefaultItems.props always writes $(DefaultItemExcludes);…. Here the inherited value is dropped, so anything a user sets in Directory.Build.props is silently ignored for .xsproj while it works as documented for .csproj. That is a surprising difference to debug — nothing fails, the setting just has no effect.

Evaluation order confirms the fix is narrow: with -v:diag on a real project, the final value contains the X# list followed by $(BaseOutputPath)/**, $(BaseIntermediateOutputPath)/**, publish/**, **/*.user. Those come from the .NET SDK, which is imported after this file, so the prefix picks up user values only.

2. The X# item globs have no Exclude

<EmbeddedResource Include="**/*.resx" KeepDuplicates="false">
<Compile Include="**/*.designer.prg" KeepDuplicates="false">
<NativeResource Include="**/*.rc">

These reach into obj\ and bin\. Any generated file left there from an earlier configuration becomes a project item, which shows up as XS0579 / CS0579 Duplicate attribute. It is easy to hit whenever IntermediateOutputPath changes and the old directory stays on disk.

Exclude="$(XSharpDefaultItemExcludes)" is added to all seven globs. Two details worth reviewing:

  • The property is computed before the item types owned by X# are appended to DefaultItemExcludes. Using the appended value would exclude exactly the files these globs are meant to collect.
  • The output directories are listed explicitly, because the .NET SDK appends them to DefaultItemExcludes only after this file is imported — too late for these globs. Condition="'$(BaseOutputPath)' != ''" guards keep a bare /** from being formed.

$(DefaultExcludesInProjectFolder) is referenced although it is still empty at this point, so the value is picked up should the import order ever change.

Verification

The file was evaluated standalone against a directory tree with decoys in obj\Debug\ and bin\Debug\:

EXCL=[;;bin\/**;obj\/**]
EmbeddedResource=[a.resx]        obj\Debug\stale.resx, bin\Debug\old.resx not collected
Compile=[foo.designer.prg]       obj\Debug\gen.designer.prg not collected
NativeResource=[r.rc]            bin\Debug\old.rc not collected
VOBinary=[x.xsfrm]  None=[a.vh]  ApplicationDefinition=[App.xaml]

-p:DefaultItemExcludes=meins\**  ->  EXCL=[meins\**;;bin\/**;obj\/**]

Not verified inside a full SDK build — that needs the file deployed to C:\Program Files (x86)\XSharp\MSBuild\. The import-order assumptions above are taken from a -v:diag evaluation of a real .xsproj.

Not included

The same ItemGroup also ignores $(EnableDefaultItems) and the per-type switches (EnableDefaultCompileItems, EnableDefaultEmbeddedResourceItems, …); the .NET SDK guards every default item group with them. Fixing that removes items from projects that set EnableDefaultItems=false and rely on the current behaviour, so it is left out here and is worth its own discussion.

hpetriffer and others added 2 commits September 2, 2026 08:28
XSharp.SDK.Props assigned DefaultItemExcludes instead of appending to it,
so any value the user had set in Directory.Build.props was silently
discarded for .xsproj projects. Microsoft.NET.Sdk.DefaultItems.props always
appends, so DefaultItemExcludes works as documented for C# and VB but not
for X#.

Prepend $(DefaultItemExcludes) to the assignment. The .NET SDK adds its own
entries (BaseOutputPath, BaseIntermediateOutputPath, publish, **/*.user)
after this file is imported, so the only values picked up by the prefix are
the ones the user set explicitly.

Co-Authored-By: Claude Opus 5 <[email protected]>
The item globs owned by the X# SDK (VOBinary, NativeResource, Compile for
*.designer.prg and *.xaml.prg, EmbeddedResource, None, ApplicationDefinition)
carried no Exclude attribute, so they reached into obj\ and bin\ as well.
Stale generated files there are picked up as project items, which surfaces as
XS0579/CS0579 "Duplicate attribute" whenever an intermediate directory from an
earlier configuration is still on disk.

Add Exclude="$(XSharpDefaultItemExcludes)" to those globs. The property is
computed before the item types owned by X# are appended to DefaultItemExcludes,
because the appended value would exclude exactly the files these globs are
meant to collect. The output directories are listed explicitly: the .NET SDK
adds them to DefaultItemExcludes only after this file is imported, which is too
late for these globs. Empty-value guards keep a bare "/**" pattern from being
formed.

Co-Authored-By: Claude Opus 5 <[email protected]>
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.

1 participant