Skip to content

Conversation

@Nirmal4G
Copy link
Contributor

@Nirmal4G Nirmal4G commented Feb 1, 2021

Fixes #3497

Context

We as devs want simplified singular root output path across build and publish.

Changes Made

Promote PublishDir to BuildDir status
Use BuildDir to initialize MSBuildProjectExtensionsPath
Use BuildDir for mismatch warning instead of BaseIntermediateOutputPath

Testing

TBD

Notes

This is just a concept of the new output paths behaviour using a new common directory to hold all the temporary build outputs. This is not the final implementation as this break previous behaviour. I'm still experimenting, whether to introduce a new property to split the behaviour, either within the targets or to a new targets file with an import switch. If we do favour the spilt, we can do it with #1686. The Sdk way easier since it also reduces duplicating the logic between .NET SDK and the Common targets.

Please hold up your reviews until it's out of draft.

@Forgind
Copy link
Contributor

Forgind commented Feb 1, 2021

Note for reviewers:
The first five commits are cosmetic; the sixth is the relevant change. Skip to that one.

Copy link
Contributor

@Forgind Forgind left a comment

Choose a reason for hiding this comment

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

I'd like to avoid changing any defaults in making this, but I think this is a good start, though I haven't looked to see if I like all the whitespace changes. (I did see it was just a draft, but I wanted to try to do a little better on feedback than last time 😊)

@dsplaisted as the issue author.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change? Seems like it would confuse people. Did you mean to make it $(BuildDir)app.publish?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. This was intentional. Making publish a first-class citizen of the MSBuild process. So, I placed it in the root instead.

I've wanted to ask, why the app. prefix? why not just publish?

Is it because of the explorer's sorting that you wanted to make publish folder come first?

@dsplaisted
Copy link
Member

@Nirmal4G Can you remove the whitespace / formatting changes from this PR and submit them separately? That will make it a lot easier to review the changes related to the output directory.

@dsplaisted
Copy link
Member

@Nirmal4G Thanks for your work on this.

We try hard to avoid breaking changes in MSBuild. That means we can't change the output paths used for projects that haven't set BuildDir. It also means that BaseIntermediateOutputPath needs to work the same way as it does today, while in this PR it looks like you are replacing its functionality with BuildDir.

We will also need to decide whether BuildDir is the property name we want to use for this. I think there were various suggestions, and previously my preference was RootOutputPath. I'm warming up to BuildDir with this PR though. Regardless, I don't think figuring out the name to use should block other progress on this PR.

@dsplaisted
Copy link
Member

Actually, understanding this more, I don't think it really addresses #3497. What that issue tracks is a way to set a common output path for multiple projects (ie in a solution/repo). Then the project name would be automatically appended to that common output path (along with other components, such as bin or obj, the configuration, platform, TargetFramework, etc. The way I think we can do that is here: #3497 (comment)

I think that's more useful than having a single property that allows you to override both the output and intermediate paths for a single project.

Copy link
Member

@benvillalobos benvillalobos left a comment

Choose a reason for hiding this comment

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

My big concern so far is nailing down exactly what BuildDir should be. It sounds like BuildDir should just default to the root of the project? So no matter where it is, BaseOutputPath (bin) and BaseIntermediateOutputPath (obj) just plant themselves at (builddir)/bin or obj respectively.

Also, changing the pre-existing outputpath properties sounds pretty fishy to me. How realistic is it a dev would override these?

Thanks @Forgind for pointing out the 6th commit as the main one to look at.

@Forgind
Copy link
Contributor

Forgind commented Feb 4, 2021

Before I forget: please retarget to master.

@Nirmal4G
Copy link
Contributor Author

Nirmal4G commented Feb 5, 2021

@dsplaisted

We try hard to avoid breaking changes in MSBuild. That means we can't change the output paths used for projects that haven't set BuildDir.

I agree and I do have a solution, same as I did in #5238, we can use a property to switch to a new behaviour when BuildDir is set.

Then the project name would be automatically appended to that common output path

This, I wanted to ask. Do we want to append to BuildDir or each of the other paths that depend on (e.g.: *OutputPaths)?

  1. build/<project-name>/{bin,obj,ext,...}/...
  2. build/{bin,obj,ext,...}/<project-name>/...

Which directory structure do you prefer as the default?

It also means that BaseIntermediateOutputPath needs to work the same way as it does today

I very much prefer if we remove the MSBuildProjectExtensionsPath's dependency on BaseIntermediateOutputPath. Anything pre-build goes into the extensions path, so (along with central package versioning feature) caching them is a benefit on builds in the near future. It doesn't hurt to at least plan for it.

Besides, the change I made just relaxes BIOP and not constrain it. So, there'll be no-breaking change on this part but we do have previews to check and confirm it.

@benvillalobos
Copy link
Member

To be clear, I'm against changing the default that bin/ obj/ folders are located in project roots. If there's an incredibly compelling argument for it I'm all ears, but I imagine this would break a whole lot of people.

If we're talking about simply allowing a user to set BuildDir, and bin/ and obj/ would be placed at whatever that location is, I see no problems there.

I'm not sure what the benefit of adding an ext/ to every build is?

Just like bin and obj, I've introduced ext folder to hold all the project restores, external tools hooking up with msbuild, etc... That way the outputs from these tools are kept separate, since, the pre-build events take a long time in the build process. This way, they are easy to include/copy/ignore in cache-enabled builds (e.g.: docker builds).

Where would these outputs go previously? in obj?

@Nirmal4G Nirmal4G changed the base branch from vs16.9 to master February 13, 2021 10:03
@Nirmal4G
Copy link
Contributor Author

I'm against changing the default...If there's an incredibly compelling argument for it I'm all ears...

#MeToo but yes there's a compelling argument to me is that having a sensible and standard output paths across different types of projects for variety of different use cases. I'll create a proposal based on what I learn from this PR. We can have the discussion there.

Where would these outputs go previously? in obj?

Yes, currently but I do propose we move it to a separate folder only when under build directory.

All of this doesn't mean I want to remove existing behavior.

Base automatically changed from master to main March 15, 2021 20:09
@Nirmal4G Nirmal4G changed the base branch from main to vs16.10 May 13, 2021 11:40
@Nirmal4G Nirmal4G changed the base branch from vs16.10 to vs16.11 May 29, 2021 07:45
@Nirmal4G Nirmal4G changed the title Support Common output via BuildDir and PublishDir Support Common output via BuildDir and PublishDir Jun 21, 2021
@Nirmal4G Nirmal4G changed the base branch from vs16.11 to main August 12, 2021 08:01
Make Common props, targets and tasks easier to read and understand.

Ensure they follow consistent formatting

E.g.: 2-space indent
```xml
  <!-- Single Line Comment Text -->
  <!--
    Multi Line Comment Text
    Another Comment Text
      Indented Comment Text
  -->
```
Make Common props, targets and tasks easier to read and understand.

in all files:
 - Fix improper leading and trailing spacing of strings within quotes.

in 'Microsoft.Common.props':
 - Move 'BaseIntermediateOutputPath' logic out of 'MSBuildProjectExtensionsPath' block.

in 'Microsoft.Common.CrossTargeting.targets':
 - Remove temporary import depending on 'CoreCrossTargetingTargetsPath' property.

in 'Microsoft.Common.CurrentVersion.targets':
 - Add single quotes to property names in text.
 - Set 'ProjectPath' to the now available 'MSBuildProjectDirectory'.
 - Simplified condition logic wherever based on 'OutputType' property.
 - Use 'ConfigurationName' property instead of 'Configuration' property.
Promote PublishDir to BuildDir status
Use BuildDir to initialize MSBuildProjectExtensionsPath
Use BuildDir for mismatch warning instead of BaseIntermediateOutputPath
When pointing build and publish outside of project directory, we need to check the same
and append the project name to them so that the projects' outputs doesn't clash.

There are no property functions available to check if a path is a parent of another path.
So, we resort to using this hack until a suitable alternative is made available.
We don't need to split them but this will become crowded as we add
output path features later. So, it is best to split them now.

The order of checking the OutputPath properties is now reversed,
meaning the early paths come first instead of the final path properties.

This leads to fail early for the path properties in the order of importance.
Setting custom build and publish folder names is now enabled via 'BuildDirName' and 'PublishDirName'.
The defaults are 'build' for build directory and 'publish' for publish directory.
1. *BaseIntermediateOutputPath* -> *BuildDir*
2. *ConfigurationAndPlatform* -> *OutputPaths*
3. ProjectExtensionsPath: *obj* -> *ext*
@Nirmal4G
Copy link
Contributor Author

Closing this since I re-forked the repo, the branch ref to this PR was removed as well. I'll open a new PR soon.

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.

Support setting a root output path for all projects in a repo or solution with a single property

4 participants