Set up a .NET Core/Standard solution with multiple projects such that they all build and publish into a centralized directory without polluting the source directory.
These setup steps should be followed before attempting to reproduce the issue using either method below.
$ mkdir MyApp && cd MyApp
$ mkdir src && cd src
$ dotnet new console -o MyApp.Cli
$ dotnet new classlib -o MyApp.Lib
$ dotnet new mstest -o MyApp.Tests
$ dotnet new sln -n MyApp
$ dotnet sln add MyApp.*/*.csproj
$ cd ..
In this method, we try to define the output/publish paths in Directory.Build.props file.
Create the ./src/Directory.Build.props file and add the output/publish path
properties:
<Project>
<PropertyGroup>
<PublishDir>$(MSBuildThisFileDirectory)\..\build\publish\$(MSBuildProjectName)</PublishDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\bin\Release</OutputPath>
<IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\obj\Release</IntermediateOutputPath>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\obj\Release</BaseIntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\bin\Debug</OutputPath>
<IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\obj\Debug</IntermediateOutputPath>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\build\$(MSBuildProjectName)\obj\Debug</BaseIntermediateOutputPath>
</PropertyGroup>
</Project>Build the solution:
$ dotnet build src/MyApp.sln
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restoring packages for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj...
Restoring packages for /home/foo/MyApp/src/MyApp.Lib/MyApp.Lib.csproj...
Restoring packages for /home/foo/MyApp/src/MyApp.Tests/MyApp.Tests.csproj...
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Lib/obj/Debug/MyApp.Lib.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Cli/obj/Debug/MyApp.Cli.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Lib/obj/Debug/MyApp.Lib.csproj.nuget.g.targets.
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Cli/obj/Debug/MyApp.Cli.csproj.nuget.g.targets.
Restore completed in 153.15 ms for /home/foo/MyApp/src/MyApp.Lib/MyApp.Lib.csproj.
Restore completed in 153.15 ms for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj.
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Tests/obj/Debug/MyApp.Tests.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/../build/MyApp.Tests/obj/Debug/MyApp.Tests.csproj.nuget.g.targets.
Restore completed in 223.42 ms for /home/foo/MyApp/src/MyApp.Tests/MyApp.Tests.csproj.
MyApp.Lib -> /home/foo/MyApp/build/MyApp.Lib/bin/Debug/netstandard2.0/MyApp.Lib.dll
MyApp.Tests -> /home/foo/MyApp/build/MyApp.Tests/bin/Debug/netcoreapp2.2/MyApp.Tests.dll
MyApp.Cli -> /home/foo/MyApp/build/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.48
As a result, all of the build artifacts are correctly placed in the ./build
directory:
$ find . -iname 'bin' -or -iname 'obj'
./build/MyApp.Tests/obj
./build/MyApp.Tests/bin
./build/MyApp.Cli/obj
./build/MyApp.Cli/bin
./build/MyApp.Lib/obj
./build/MyApp.Lib/bin
Publish the console application project:
dotnet publish src/MyApp.Cli/MyApp.Cli.csproj
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restoring packages for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj...
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/obj/MyApp.Cli.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/obj/MyApp.Cli.csproj.nuget.g.targets.
Restore completed in 119.63 ms for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj.
MyApp.Cli -> /home/foo/MyApp/src/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
MyApp.Cli -> /home/foo/MyApp/build/publish/MyApp.Cli/
Notice this line in the output where the intermediate dll is written in the source tree instead of the intermediate output path:
MyApp.Cli -> /home/foo/MyApp/src/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
And if we look at our working directory, bin and obj folder directories exist in the src tree:
$find . -iname 'bin' -or -iname 'obj'
./build/MyApp.Tests/obj
./build/MyApp.Tests/bin
./build/MyApp.Cli/obj
./build/MyApp.Cli/bin
./build/MyApp.Lib/obj
./build/MyApp.Lib/bin
./src/MyApp.Cli/obj
./src/MyApp.Cli/bin
In this method, we try to define the output/publish paths in the project files directly and change how the SDK is imported.
Add path properties to project files and make sure SDK targets are imported in the correct order:
./src/MyApp.Cli/MyApp.Cli.csproj
-<Project Sdk="Microsoft.NET.Sdk">
+<Project>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
+ <PublishDir>$(MSBuildThisFileDirectory)\..\..\build\publish\$(MSBuildProjectName)</PublishDir>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Release</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</BaseIntermediateOutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Debug</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</BaseIntermediateOutputPath>
+ </PropertyGroup>
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
</Project>./src/MyApp.Lib/MyApp.Lib.csproj
-<Project Sdk="Microsoft.NET.Sdk">
+<Project>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Release</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</BaseIntermediateOutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Debug</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</BaseIntermediateOutputPath>
+ </PropertyGroup>
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
</Project>./src/MyApp.Tests/MyApp.Tests.csproj
-<Project Sdk="Microsoft.NET.Sdk">
+<Project>
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Release</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Release</BaseIntermediateOutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <OutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\bin\Debug</OutputPath>
+ <IntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</IntermediateOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)\..\..\build\$(MSBuildProjectName)\obj\Debug</BaseIntermediateOutputPath>
+ </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
</ItemGroup>
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
+ <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
</Project>Build the solution:
$ dotnet build src/MyApp.sln
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restoring packages for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj...
Restoring packages for /home/foo/MyApp/src/MyApp.Tests/MyApp.Tests.csproj...
Restoring packages for /home/foo/MyApp/src/MyApp.Lib/MyApp.Lib.csproj...
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/../../build/MyApp.Cli/obj/Debug/MyApp.Cli.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Lib/../../build/MyApp.Lib/obj/Debug/MyApp.Lib.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/../../build/MyApp.Cli/obj/Debug/MyApp.Cli.csproj.nuget.g.targets.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Lib/../../build/MyApp.Lib/obj/Debug/MyApp.Lib.csproj.nuget.g.targets.
Restore completed in 154.76 ms for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj.
Restore completed in 154.77 ms for /home/foo/MyApp/src/MyApp.Lib/MyApp.Lib.csproj.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Tests/../../build/MyApp.Tests/obj/Debug/MyApp.Tests.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Tests/../../build/MyApp.Tests/obj/Debug/MyApp.Tests.csproj.nuget.g.targets.
Restore completed in 233.18 ms for /home/foo/MyApp/src/MyApp.Tests/MyApp.Tests.csproj.
MyApp.Lib -> /home/foo/MyApp/build/MyApp.Lib/bin/Debug/netstandard2.0/MyApp.Lib.dll
MyApp.Tests -> /home/foo/MyApp/build/MyApp.Tests/bin/Debug/netcoreapp2.2/MyApp.Tests.dll
MyApp.Cli -> /home/foo/MyApp/build/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.98
As a result, all of the build artifacts are again correctly placed in the
./build directory:
$ find . -iname 'bin' -or -iname 'obj'
./build/MyApp.Tests/obj
./build/MyApp.Tests/bin
./build/MyApp.Cli/obj
./build/MyApp.Cli/bin
./build/MyApp.Lib/obj
./build/MyApp.Lib/bin
Publish the console application project:
$ dotnet publish src/MyApp.Cli/MyApp.Cli.csproj
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restoring packages for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj...
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/obj/MyApp.Cli.csproj.nuget.g.props.
Generating MSBuild file /home/foo/MyApp/src/MyApp.Cli/obj/MyApp.Cli.csproj.nuget.g.targets.
Restore completed in 117.97 ms for /home/foo/MyApp/src/MyApp.Cli/MyApp.Cli.csproj.
MyApp.Cli -> /home/foo/MyApp/src/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
MyApp.Cli -> /home/foo/MyApp/build/publish/MyApp.Cli/
Notice this line in the output where the intermediate dll is written in the source tree instead of the intermediate output path:
MyApp.Cli -> /home/foo/MyApp/src/MyApp.Cli/bin/Debug/netcoreapp2.2/MyApp.Cli.dll
$find . -iname 'bin' -or -iname 'obj'
./build/MyApp.Tests/obj
./build/MyApp.Tests/bin
./build/MyApp.Cli/obj
./build/MyApp.Cli/bin
./build/MyApp.Lib/obj
./build/MyApp.Lib/bin
./src/MyApp.Cli/obj
./src/MyApp.Cli/bin