5

MSBuild is strange

I already tried this and another answer and I also tried this one

After that, I changed <IntermediateOutputPath> and <BaseIntermediateOutputPath> and <OutputPath> in the .csproj file but...

It keeps creating this piece of strange stuff in the old obj folder (I don't use nuget)

project.assets.json
project.nuget.cache
project.packagespec.json
...

I have already read about Visual Studio legacy workflow causes this behaviour but do any workarounds exist?

My current .csproj file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <StartupObject>Program</StartupObject>
    <IntermediateOutputPath>..\..\obj\</IntermediateOutputPath>
    <BaseIntermediateOutputPath>..\..\obj\</BaseIntermediateOutputPath>
    <OutputPath>..\..\bin\Build\</OutputPath>
  </PropertyGroup>
  
  <ItemGroup>
    <ProjectReference Include="foo\dependency.csproj" />
  </ItemGroup>

</Project>
caxapexac
  • 781
  • 9
  • 24

2 Answers2

6

Solved by creating Directory.Build.props file in the root of project with:

<Project>
    <PropertyGroup>
        <MSBUildProjectExtensionsPath>..\..\obj\</MSBUildProjectExtensionsPath>
    </PropertyGroup>
</Project>

Very dirty and non-obvious microsoft-style hack

Found here

Is there any good .NET compiler for windows without penetrating youself?

caxapexac
  • 781
  • 9
  • 24
  • Just FYI. Modifying `.csproj` and adding `..\..\obj\` works in my case. However, `Directory.Build.props` doesn't work. Thanks to the information [here](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019#msbuildprojectextensionspath) – Hustlion May 10 '21 at 08:36
  • @Hustlion FYI Directory.Build.props has worked for me in the past, but I had have to restart VS after every edit. I just checked again. With VS2019, I had close and re-open the the sln for your change to BaseIntermediateOutputPath in Directory.Build.props to take effect. MS warns against the use of Directory.Build.props because it may intriduce a dependency which is not a build machine. This is why I use it, to make changes to my local .csproj such as 0 – Andrew Dennison Mar 25 '22 at 14:39
1

I needed something similar. Having two .csproj files in the same directory, with different target frameworks would otherwise fail without this change I made in one of the .csproj files.

The project can have the MSBuildProjectExtensionsPath, but it must be defined before importing the SDK.

<?xml version="1.0" encoding="utf-8"?>

<Project>
  <!-- Implicit top import required explicitly to change build output path -->
  <PropertyGroup>
    <MSBuildProjectExtensionsPath>legacy</MSBuildProjectExtensionsPath>
    <BaseIntermediateOutputPath>$(MSBuildProjectExtensionsPath)\obj</BaseIntermediateOutputPath>
    <OutputPath Condition="'$(Configuration)' != ''">$(MSBuildProjectExtensionsPath)\bin\$(Configuration)</OutputPath>
  </PropertyGroup>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

  ...

  <!-- Implicit top import required explicitly to change build output path -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

All changes were needed (not just the property MSBuildProjectExtensionsPath) for dotnet SDK builds, else cross pollination between projects of the project.assets.json file occurs resulting in build failures.

I could not use the Directory.Build.props file, as this would affect both my project files (and they needed to be kept separate).

Please note, this likely does not satisfy the use case if someone does try to override these variables in their own Directory.Build.props, so you'd have to extend this solution for that additional use case and still test.

J. Curl
  • 21
  • 3
  • Oh wow .NET is still full of hacks (as always) – caxapexac Jun 25 '23 at 13:34
  • According to docs you cant change BaseIntermediateOutputPath or something in anywhere aside Directory.Build.props just because they've decided so – caxapexac Jun 25 '23 at 13:36
  • 1
    If you define `MSBuildProjectExtensionsPath` after the SDK definition, you get the error: "error MSB3540: The value of the property "MSBuildProjectExtensionsPath" was modified after it was used by MSBuild which can lead to unexpected build results. To set this property, you must do so before Microsoft.Common.props is imported, for example by using Directory.Build.props. For more information, please visit https://go.microsoft.com/fwlink/?linkid=869650". It's from here that you are given multiple options to customise the build. – J. Curl Jun 25 '23 at 13:49
  • 1
    This answer has the limitation, that if the user did provide their own `Directory.Build.props`, then this won't be handled without extra work (e.g. adding conditions, extending variables). – J. Curl Jun 25 '23 at 13:54
  • 1
    I updated the answer to provide a cleaner build structure. Note the condition for an empty configuration to avoid making a directory that isn't needed. – J. Curl Jun 25 '23 at 13:56