Skip to content

Support for BaseIntermediateOutputPath - #3527

Merged
forki merged 8 commits into
fsprojects:masterfrom
theimowski:base_intermediate_output_path
Apr 11, 2019
Merged

forki merged 8 commits into
fsprojects:masterfrom
theimowski:base_intermediate_output_path

Conversation

@theimowski

Copy link
Copy Markdown
Member

This is a follow up for #2642
I didn't go the "try to parse MSBuild variable for global restore" path, but instead decided to add option to disable paket global restore.

Given following Directory.Build.props file:

<Project>

  <PropertyGroup>
    <IsWindows Condition="...">true</IsWindows>
    <IsOSX Condition="...">true</IsOSX>
  </PropertyGroup>

  <PropertyGroup>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/obj/**/*</DefaultItemExcludes>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/bin/**/*</DefaultItemExcludes>
    
    <!-- THIS IS NEW -->
    <PaketDisableGlobalRestore>true</PaketDisableGlobalRestore>
    <!-- THIS IS NEW -->

  </PropertyGroup>

  <PropertyGroup Condition="'$(IsWindows)' == 'true'">
    <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/windows/</BaseIntermediateOutputPath>
    <BaseOutputPath>$(MSBuildProjectDirectory)/bin/windows/</BaseOutputPath>
  </PropertyGroup>

  <PropertyGroup Condition="'$(IsOSX)' == 'true'">
    <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/osx/</BaseIntermediateOutputPath>
    <BaseOutputPath>$(MSBuildProjectDirectory)/bin/osx/</BaseOutputPath>
  </PropertyGroup>

</Project>

I read PaketDisableGlobalRestore property in Paket.Restore.targets :

...

    <!-- Do a global restore if required -->
    <Exec Command='$(PaketBootStrapperCommand)' Condition=" '$(PaketBootstrapperStyle)' == 'classic' AND Exists('$(PaketBootStrapperExePath)') AND !(Exists('$(PaketExePath)'))" ContinueOnError="false" />
    <Exec Command='$(PaketCommand) restore' Condition=" '$(PaketRestoreRequired)' == 'true' 
        AND '$(PaketDisableGlobalRestore)' != 'true' " ContinueOnError="false" />
    

...

which basically makes I skip global restore.
Then for each project I pass BaseIntermediateOutputPath:

    <!-- Step 3 Restore project specific stuff if required -->
    <Message Condition=" '$(PaketRestoreRequired)' == 'true' " Importance="low" Text="Detected a change ('$(PaketRestoreRequiredReason)') in the project file '$(MSBuildProjectFullPath)', calling paket restore" />
    <Exec Command='$(PaketCommand) restore --project "$(MSBuildProjectFullPath)" 
     --output-path "$(BaseIntermediateOutputPath)" --target-framework "$(TargetFrameworks)"' Condition=" '$(PaketRestoreRequired)' == 'true' AND '$(TargetFramework)' == '' " ContinueOnError="false" />
    <Exec Command='$(PaketCommand) restore --project "$(MSBuildProjectFullPath)" 
     --output-path "$(BaseIntermediateOutputPath)" --target-framework "$(TargetFramework)"' Condition=" '$(PaketRestoreRequired)' == 'true' AND '$(TargetFramework)' != '' " ContinueOnError="false" />

End game for my use case is I can build same project simultaneously on OSX and Windows and paket doesn't interfere.
I have few projects in solution, that's why skipping global restore optimisation is reasonable for me.

I'm aware my proposed solution isn't ideal, but at least it works for me and requires an explicit opt-in.
Please let me know what you think @forki @matthid @0x53A - if this is OK then I'll proceed with adding some docs and an integration test

@forki

forki commented Mar 21, 2019

Copy link
Copy Markdown
Member

@matthid ??

@matthid

matthid commented Mar 21, 2019

Copy link
Copy Markdown
Member

This doesn't scale for more projects and introduces a perf regression, for example this most likey makes fake solution unworkable.

While this is opt in I'm not a fan, in fact this pseudo fixes the issue until one with a huge solution needs this... Personally I wouldn't merge this. But it solves someone's problem. It will be an option practically nobody has enabled and therefore we will not catch regressions easily...

Well that's my 2cents

@theimowski

Copy link
Copy Markdown
Member Author

Do you have other ideas how to otherwise add support for BaseIntermediateOutputPath?
In #2642 you mentioned using https://github.com/enricosada/dotnet-proj-info - do you still think that's the way to go?

@theimowski

Copy link
Copy Markdown
Member Author

Alternatively I'm thinking of finding Directory.Build.props and appending all nodes before parsing each ProjectFile

@0x53A

0x53A commented Mar 21, 2019 •

Copy link
Copy Markdown
Contributor

Alternatively I'm thinking of finding Directory.Build.props and appending all nodes before parsing each ProjectFile

MsBuild is a full programming evironment in xml, that approach is going to fail for anything but the simplest files.

That's also why any "outside" parsing of project files will fail - you need msbuild. https://github.com/enricosada/dotnet-proj-info does use MsBuild and so should work correctly.


My opinion is that the perf hit would be acceptable for anything but the largest solutions with literally hundreds of projects, the restore is cached anyway. But as always with performance, it needs to be timed and profiled.

@0x53A

0x53A commented Mar 21, 2019

Copy link
Copy Markdown
Contributor

But that was exactly why I stopped with my PR :)

@matthid

matthid commented Mar 21, 2019

Copy link
Copy Markdown
Member

My opinion is that the perf hit would be acceptable for anything but the largest solutions with literally hundreds of projects, the restore is cached anyway. But as always with performance, it needs to be timed and profiled.

Sadly this is not the problem. In fact the problem is that even while Microsoft caches its stuff Paket does not and basically last time I checked even if Microsoft cache was up to date it would still call Paket.exe and calling paket.exe is the most expensive thing in the whole process, it doesn't even matter what paket does because spawning the process and parsing command line is already too slow. So as you can see caching doesn't even matter at all.

@matthid

matthid commented Mar 21, 2019

Copy link
Copy Markdown
Member

Looking at this PR again, maybe it is acceptable:
The most important thing is to not call paket.exe a second time after the project has been restored successfully.
I think this PR still holds this property. I feel like if we add a fast-path for command line parsing for this particular call it is fine by me.
So this option will slow down the initial restore by a lot, but future restores are still fine.

@theimowski

Copy link
Copy Markdown
Member Author

I feel like if we add a fast-path for command line parsing for this particular call it is fine by me.

Do you mean restore with --output-path argument?

If so, shall I simply remove Output_Path case from RestoreArgs and parse it directly in main ?

@theimowski

Copy link
Copy Markdown
Member Author

Like in 25b1e8b ?

@matthid

matthid commented Mar 22, 2019

Copy link
Copy Markdown
Member

If so, shall I simply remove Output_Path case from RestoreArgs and parse it directly in main ?
Like in 25b1e8b ?

Yes, however please leave it in the argu arguments such that --help and users giving a different ordering works as expected.

@theimowski

Copy link
Copy Markdown
Member Author

Ok - done. Added also a short note to docs
I'll add an integration tests next week (hopefully)

@theimowski
theimowski force-pushed the base_intermediate_output_path branch from 424a468 to 6a8ab32 Compare March 25, 2019 12:22
@theimowski theimowski changed the title [WIP] Support for BaseIntermediateOutputPath Support for BaseIntermediateOutputPath Mar 26, 2019
@theimowski

Copy link
Copy Markdown
Member Author

@matthid This is now ready for review

@theimowski
theimowski force-pushed the base_intermediate_output_path branch from 821c4ce to 0c68e18 Compare April 2, 2019 14:51
@forki

forki commented Apr 3, 2019

Copy link
Copy Markdown
Member

can you please merge with master?

@theimowski
theimowski force-pushed the base_intermediate_output_path branch from 0c68e18 to 8730c47 Compare April 3, 2019 10:23
@theimowski

Copy link
Copy Markdown
Member Author

There you go

@theimowski

Copy link
Copy Markdown
Member Author

Seems CI is telling me I broke one existing integration tests - will investigate

@theimowski
theimowski force-pushed the base_intermediate_output_path branch from 8730c47 to b83e1d5 Compare April 8, 2019 11:36
@theimowski

theimowski commented Apr 8, 2019 •

Copy link
Copy Markdown
Member Author

The integration test fails probably due to breaking change in restore cli arguments:
I added --output-path parameter to restore in Paket.Restore.targets, but apparently integration tests are using an older build of paket.
How can I trick the netcore integration tests to use a freshly built paket?

@theimowski

Copy link
Copy Markdown
Member Author

Think I finally got it right

@forki
forki requested a review from matthid April 11, 2019 07:13
@forki
forki merged commit ec76778 into fsprojects:master Apr 11, 2019
@forki

forki commented Apr 11, 2019

Copy link
Copy Markdown
Member

thanks. this is released

@theimowski
theimowski deleted the base_intermediate_output_path branch April 11, 2019 09:12
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.

4 participants