Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project file hygiene #67532

Closed
wants to merge 4 commits into from
Closed

Conversation

ViktorHofer
Copy link
Member

@ViktorHofer ViktorHofer commented Apr 4, 2022

Commit 1 - Infrastructure changes

  1. The generators.targets file had a bug that complained when a project
    uses the default targeting pack references because the
    ArrayMarshaller.cs file was not imported.
    I also cleaned the generators.targets file by simplifying
    conditions.
  2. Enable "default items" via the <EnableDefaultItems /> SDK switch
    for any project except tests (for now).
  3. Remove outdated infrastructure that isn't needed anymore based on
    project file changes.

Commit 2 - Delete dead code

Commit 3 - Ref/Src/Gen-Project file hygiene

  1. Use the SDK's default items feature so that compile items in the
    project directory are imported automatically. Disable that feature
    in few projects which heavily depend on manually including compile
    items based on the TargetPlatformIdentifier.

    Changes made mimic the usage in the Microsoft.Extensions.* projects
    which already used the default items feature.

    I made sure that the numer of comile items included before the change
    and after the change is identical.

    In a follow-up change it would make sense to clean-up all the
    BCL files to use the same set of suffixes, i.e.

    • .NETFramework only files: .netframework.cs instead of
      • .net46.cs
      • .netfx.cs
      • .netframework.cs
      • .net48.cs
      • etc.

    That would allow to define central glob
    exclusion patterns for i.e. .NETFramework builds:

    • TFI .NETFramework: *\**.netcoreapp.cs
    • TFI .NETCoreApp: *\**.netframework.cs
    • ...
  2. Remove the unnecessary declaration of <Reference /> and
    <ProjectReference /> items in out-of-band projects as they already
    build on top of the shared framework (targeting pack) and make that
    the default behavior for anything that is out-of-band.

  3. Clean-up Reference and ProjectReference items that weren't used by
    the compiler anymore, i.e. System.Runtime.ComilerServices.Unsafe and
    System.Runtime.Extensions (as those are now facades).

  4. Add empty lines to separate property and item groups from each other
    so that project files are easier to read and look the same as
    project files that "dotnet new" produces.

Commit 4 - React to analyzer warnings/errors

Projects which previously didn't auto-reference System.Memory,
do so now (projects which are out-of-band and sit on top of the
shared framework). Analyzers which are conditioned on the reference
being available now kick in and hence these two files needed to be
updated.

@ViktorHofer ViktorHofer added this to the 7.0.0 milestone Apr 4, 2022
@ViktorHofer ViktorHofer self-assigned this Apr 4, 2022
@ViktorHofer ViktorHofer requested a review from ericstj April 4, 2022 12:10
@ghost
Copy link

ghost commented Apr 4, 2022

Tagging subscribers to this area: @dotnet/area-meta
See info in area-owners.md if you want to be subscribed.

Issue Details

Commit 1 - Infrastructure changes

  1. The generators.targets file had a bug that complained when a project
    uses the default targeting pack references because the
    ArrayMarshaller.cs file was not imported.
    I also cleaned the generators.targets file by simplifying
    conditions.
  2. Enable "default items" via the "" SDK switch
    for both ref and source projects.
  3. Remove outdated infrastructure that isn't needed anymore based on
    project file changes.

Commit 2 - Delete dead code that dates back to mono BCL build

Commit 3 - Ref/Src/Gen-Project file hygiene

  1. Use the SDK's default items feature so that compile items in the
    project directory are imported automatically. Disable that feature
    in few projects which heavily depend on manually including compile
    items based on the TargetPlatformIdentifier.

    Changes made mimic the usage in the Microsoft.Extensions.* projects
    which already used the default items feature.

    I made sure that the numer of comile items included before the change
    and after the change is identical.

    In a follow-up change it would make sense to clean-up all the
    BCL files to use the same set of suffixes, i.e.

    • .NETFramework only files: .netframework.cs instead of
      • .net46.cs
      • .netfx.cs
      • .netframework.cs
      • .net48.cs
      • etc.

    That would allow to define central glob
    exclusion patterns for i.e. .NETFramework builds:

    • TFI .NETFramework: "*.netcoreapp.cs"
    • TFI .NETCoreApp: "*.netframework.cs"
    • ...
  2. Remove the unnecessary declaration of "" and
    "" items in out-of-band projects as they already
    build on top of the shared framework (targeting pack) and make that
    the default behavior for anything that is out-of-band.

  3. Clean-up Reference and ProjectReference items that weren't used by
    the compiler anymore, i.e. System.Runtime.ComilerServices.Unsafe and
    System.Runtime.Extensions (as those are now facades).

  4. Add empty lines to separate property and item groups from each other
    so that project files are easier to read and look the same as
    project files that "dotnet new" produces.

Commit 4 - React to analyzer warnings/errors

Projects which previously didn't auto-reference System.Memory,
do so now (projects which are out-of-band and sit on top of the
shared framework). Analyzers which are conditioned on the reference
being available now kick in and hence these two files needed to be
updated.

Author: ViktorHofer
Assignees: ViktorHofer
Labels:

area-Meta

Milestone: 7.0.0

@stephentoub
Copy link
Member

Use the SDK's default items feature so that compile items in the project directory are imported automatically.

Did you confirm that there are zero changes in what code's actually being included? e.g. that the size of the binaries built before and after the changes are identical?

@ViktorHofer
Copy link
Member Author

I did verify that the compile items passed to CSC/VBC are identical before and after but I think it's a good idea to also compare the produced assemblies. Let me do that.

@@ -84,7 +84,10 @@
<StrongNameKeyId Condition="$(MSBuildProjectName.StartsWith('Microsoft.Extensions.'))">MicrosoftAspNetCore</StrongNameKeyId>
<!-- We can't generate an apphost without restoring the targeting pack. -->
<UseAppHost>false</UseAppHost>
<EnableDefaultItems>false</EnableDefaultItems>
<!-- TODO: Enable default items in test projects. -->
<EnableDefaultItems Condition="'$(IsTestProject)' == 'true' or
Copy link
Member

Choose a reason for hiding this comment

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

hmm, I thought we were pretty selective about source inclusions dependent on platforms (say with *.Unix.cs files and all), say with System.Private.Corelib. Are we sure this currently works? Or is there also some massaging in this PR to do that.

Copy link
Member Author

Choose a reason for hiding this comment

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

The third commit handles updating all projects to work with that setting. Less than 50% of our projects multi-target based on the OS, the majority doesn't. For the projects that don't multi-target based on the OS, this settings work nicely.

For the ones that multi-target based on the OS, this setting still works fine but a bit more work was required to make sure that nothing unexpected is included which previously wasn't. I recommend to look into the third commit yourself as the diff mostly speaks for itself.

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, I really, really, really (insert a string of "really"s until your ears bleed) do not want us to use EnableDefaultItems.

I don't even want the SDK to support it.

It's bad engineering practice that's only good for bootstrapping CS101 students.

Copy link
Member

@stephentoub stephentoub Apr 6, 2022

Choose a reason for hiding this comment

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

I agree with Jeremy (at least on the first part... I think EnableDefaultItems is reasonable for simple, small projects and is an ok default for the SDK to help bootstrap in general). If the overwhelming majority of others disagree, I'll acquiesce, but understanding exactly what's being included and what's not being included is really helpful. And with the variations in our builds and our need to include some files in some configurations and not in others, we're never going to get to a place where everything is just always included, which from my perspective also means the consistent thing is always specifying exactly what should be in every build.

Copy link
Member

Choose a reason for hiding this comment

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

(Also, for fundamental overhauls like this, that impact everyone working on the project, that impact every project, etc., I'd prefer if we have a discussion about the direction rather than an ~500 file diff just appearing. If it was necessary for you to do the work in order to come up with the proposal, then ok, and it being potentially throw-away is just part of the process; but if that could have been achieved just by experimenting with a couple of projects, presumably that would have resulted in less work for everyone?)

Copy link
Member

Choose a reason for hiding this comment

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

Explicit inclusions feels like it supports more predictable engineering at a relatively small cost of adding a line in XML when you create a file. Also, as someone who greps more than using an IDE, it allows me to see exactly what's going on without also look at what file is positioned where on disk.

Copy link
Member

Choose a reason for hiding this comment

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

My thinking is that the lower-level your code is, the more you are writing platform-specific code. And the more platform-specific code you write, the more you need to be explicit about what is and what isn't included in your project. I don't think it has anything to do with size of your project. dotnet/aspnetcore is by no means "small" or CS101, but they use EnableDefaultItems in all their projects.

The same can be said for using #ifs in your code. If you only need them in one or two spots, it is fine. But at the level we need to specialize code in the shared fx, it would be a nightmare.

That's why I think the current situation we have is acceptable. We have code that is both low-level (shared fx) and high-level (Microsoft.Extensions). Using the approach that best fits the project makes sense to me.

@radical
Copy link
Member

radical commented Apr 5, 2022

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ViktorHofer
Copy link
Member Author

ViktorHofer commented Apr 5, 2022

@stephentoub (cc @eerhardt) good that you were asking about the diff. I noticed that the Extensions projects which already use the EnableDefaultItems feature in main embed their Strings.resx file twice. One time because of the EnableDefaultItems feature (as expected) and a second time in resources.targets which results in the compiler receiving it twice:

/resource:C:\git\runtime5\artifacts\obj\Microsoft.Extensions.Configuration.Json\Debug\net7.0\FxResources.Microsoft.Extensions.Configuration.Json.SR.resources /resource:C:\git\runtime5\artifacts\obj\Microsoft.Extensions.Configuration.Json\Debug\net7.0\Microsoft.Extensions.Configuration.Json.Resources.Strings.resources

That fix which is part of the first commit makes the Extensions assemblies now actually smaller :)

@radical
Copy link
Member

radical commented Apr 5, 2022

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ghost
Copy link

ghost commented Apr 6, 2022

Tagging subscribers to this area: @dotnet/area-infrastructure-libraries
See info in area-owners.md if you want to be subscribed.

Issue Details

Commit 1 - Infrastructure changes

  1. The generators.targets file had a bug that complained when a project
    uses the default targeting pack references because the
    ArrayMarshaller.cs file was not imported.
    I also cleaned the generators.targets file by simplifying
    conditions.
  2. Enable "default items" via the <EnableDefaultItems /> SDK switch
    for any project except tests (for now).
  3. Remove outdated infrastructure that isn't needed anymore based on
    project file changes.

Commit 2 - Delete dead code that dates back to the mono BCL build

Commit 3 - Ref/Src/Gen-Project file hygiene

  1. Use the SDK's default items feature so that compile items in the
    project directory are imported automatically. Disable that feature
    in few projects which heavily depend on manually including compile
    items based on the TargetPlatformIdentifier.

    Changes made mimic the usage in the Microsoft.Extensions.* projects
    which already used the default items feature.

    I made sure that the numer of comile items included before the change
    and after the change is identical.

    In a follow-up change it would make sense to clean-up all the
    BCL files to use the same set of suffixes, i.e.

    • .NETFramework only files: .netframework.cs instead of
      • .net46.cs
      • .netfx.cs
      • .netframework.cs
      • .net48.cs
      • etc.

    That would allow to define central glob
    exclusion patterns for i.e. .NETFramework builds:

    • TFI .NETFramework: *\**.netcoreapp.cs
    • TFI .NETCoreApp: *\**.netframework.cs
    • ...
  2. Remove the unnecessary declaration of <Reference /> and
    <ProjectReference /> items in out-of-band projects as they already
    build on top of the shared framework (targeting pack) and make that
    the default behavior for anything that is out-of-band.

  3. Clean-up Reference and ProjectReference items that weren't used by
    the compiler anymore, i.e. System.Runtime.ComilerServices.Unsafe and
    System.Runtime.Extensions (as those are now facades).

  4. Add empty lines to separate property and item groups from each other
    so that project files are easier to read and look the same as
    project files that "dotnet new" produces.

Commit 4 - React to analyzer warnings/errors

Projects which previously didn't auto-reference System.Memory,
do so now (projects which are out-of-band and sit on top of the
shared framework). Analyzers which are conditioned on the reference
being available now kick in and hence these two files needed to be
updated.

Author: ViktorHofer
Assignees: ViktorHofer
Labels:

area-Infrastructure-libraries

Milestone: 7.0.0

@ViktorHofer
Copy link
Member Author

Resolved merge conflicts.

@ViktorHofer ViktorHofer removed the request for review from MichalStrehovsky April 6, 2022 06:03
@ViktorHofer
Copy link
Member Author

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

1. The generators.targets file had a bug that complained when a project
   uses the default targeting pack references because the
   ArrayMarshaller.cs file was not imported.
   Also cleaning-up the generators.targets file by simplifying
   conditions.
2. Enable "default items" via the "<EnableDefaultItems />" SDK switch
   for both ref and source projects.
3. Remove outdated infrastructure that isn't needed anymore based on
   project file changes.
1. Use the SDK's default items feature so that compile items in the
   project directory are imported automatically. Disable that feature
   in few projects which heavily depend on manually including compile
   items based on the TargetPlatformIdentifier.

   Changes made mimic the usage in the Microsoft.Extensions.* projects
   which already used the default items feature.

   I made sure that the numer of comile items included before the change
   and after the change is identical.

   In a follow-up change it would make sense to clean-up all the
   BCL files to use the same set of suffixes, i.e.
   - .NETFramework only files: .netframework.cs instead of
     - .net46.cs
     - .netfx.cs
     - .netframework.cs
     - .net48.cs
     - etc.

   That would allow to define central glob
   exclusion patterns for i.e. .NETFramework builds:
   - TFI .NETFramework: "*\**.netcoreapp.cs"
   - TFI .NETCoreApp: "*\**.netframework.cs"
   - ...

2. Remove the unnecessary declaration of "<Reference />" and
   "<ProjectReference />" items in out-of-band projects as they already
   build on top of the shared framework (targeting pack) and make that
   the default behavior for anything that is out-of-band.

3. Clean-up Reference and ProjectReference items that weren't used by
   the compiler anymore, i.e. System.Runtime.ComilerServices.Unsafe and
   System.Runtime.Extensions (as those are now facades).

4. Add empty lines to separate property and item groups from each other
   so that project files are easier to read and look the same as
   project files that "dotnet new" produces.
Projects which previously didn't auto-reference System.Memory,
do so now (projects which are out-of-band and sit on top of the
shared framework). Analyzers which are conditioned on the reference
being available now kick in and hence these two files needed to be
updated.
@ViktorHofer
Copy link
Member Author

Resolved merge conflicts.

@ViktorHofer
Copy link
Member Author

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ViktorHofer ViktorHofer mentioned this pull request Apr 6, 2022
@ViktorHofer ViktorHofer marked this pull request as draft April 6, 2022 14:42
@ViktorHofer ViktorHofer added the NO-REVIEW Experimental/testing PR, do NOT review it label Apr 6, 2022
@ViktorHofer
Copy link
Member Author

Spoke with @stephentoub offline and we agreed on that it's easier to review the changes by splitting them into separate logical units. Please hold reviewing this PR.

@ViktorHofer
Copy link
Member Author

ViktorHofer commented Apr 6, 2022

Thanks everyone for their comments. Just to clarify, I didn't intend to put up such a big change without an upfront discussion. As noted in #67650 (comment) I unfortunately mis-interpreted a comment when I tested enabling the default items feature on a single library to get feedback from the area owners.

I apologize here and now for the way this was perceived by some of you and want to emphasize that this wasn't my intention.

On the upside at least trying out the enable default items feature helped me find:

  1. Dead code: Delete dead code #67648 and
  2. Resources being embedded into assemblies twice for Microsoft.Extensions projects: Project file hygiene #67532 (comment)

I will make sure that the rest of the changes won't be lost but I will close these PRs to first have another discussion around these other changes to make sure that there isn't another disconnect in communication.

@stephentoub
Copy link
Member

Thanks, @ViktorHofer. Sorry for any miscommunication on my part.

@ViktorHofer ViktorHofer deleted the ProjectFileHygiene branch April 6, 2022 16:32
@ghost ghost locked as resolved and limited conversation to collaborators May 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Infrastructure-libraries NO-REVIEW Experimental/testing PR, do NOT review it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants