This question is related to How to code a utility msbuild project so that it depends on a "real" C# project?
So I have a working sample code where there is a utility project depending on a "real" C# project. It works fine when building on the console. Here are the files:
C:\work\a [master]> tree /F
Folder PATH listing for volume OSDisk
Volume serial number is F6C4-7BEF
C:.
│ .gitignore
│ run.ps1
│ Subject.sln
│ Utility.targets
│
├───Subject
│ Subject.csproj
│
└───Utility.Subject
Utility.Subject.proj
C:\work\a [master]>
Subject\Subject.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}</ProjectGuid>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
Utility.Subject\Utility.Subject.proj
<Project ToolsVersion="Current">
<PropertyGroup>
<MasterProject>..\Subject\Subject.csproj</MasterProject>
<MasterAsmName>Subject</MasterAsmName>
</PropertyGroup>
<Import Project="..\Utility.targets" />
</Project>
Utility.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OutputPath>bin</OutputPath>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(MasterProject)" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.Common.CurrentVersion.targets" />
<Target Name="Build" DependsOnTargets="ResolveProjectReferences">
<PropertyGroup>
<DllPath>$(MasterProject)\..\bin\$(MasterAsmName).dll</DllPath>
</PropertyGroup>
<Message Text="*** Good" Importance="High" Condition="Exists('$(DllPath)')"/>
<Message Text="*** Bad" Importance="High" Condition="!Exists('$(DllPath)')"/>
</Target>
</Project>
Subject.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30413.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Subject", "Subject\Subject.csproj", "{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utility.Subject", "Utility.Subject\Utility.Subject.proj", "{EA5BE444-40F0-4972-A03E-5B794FAECF21}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2CF0D00-8B1B-4FCC-AF4B-5A354044F786}.Release|Any CPU.Build.0 = Release|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4DD676B7-ECF7-413E-9FC6-D4ED7EC73889}
EndGlobalSection
EndGlobal
And it works fine on the command line:
C:\work\a [master]> MSBuild.exe /v:m /nologo
Subject -> C:\work\a\Subject\Bin\Subject.dll
*** Good
C:\work\a [master]>
The problem is Visual Studio. When opening the solution in VS the latter modifies the solution file by changing the target platform of the utility project from Any CPU to x86. This causes VS to skip the utility project altogether. We can actually see it when using devenv on the command line. Please, observe:
No modified files initially:
C:\work\a [master]> git st
## master
C:\work\a [master]>
Run devenv on the command line:
C:\work\a [master]> devenv .\Subject.sln /build debug
Microsoft Visual Studio 2019 Version 16.11.3.
Copyright (C) Microsoft Corp. All rights reserved.
Build started...
1>------ Build started: Project: Subject, Configuration: Debug Any CPU ------
1> Subject -> C:\work\a\Subject\Bin\Subject.dll
2>------ Skipped Build: Project: Utility.Subject, Configuration: Debug x86 ------
2>Project not selected to build for this solution configuration
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 1 skipped ==========
C:\work\a [master +0 ~1 -0 !]>
Notice in particular:
2>------ Skipped Build: Project: Utility.Subject, Configuration: Debug x86 ------
2>Project not selected to build for this solution configuration
That means VS skips the utility project. But it also modifies the solution file so as to skip it in the future:
C:\work\a [master +0 ~1 -0 !]> git st
## master
M Subject.sln
C:\work\a [master +0 ~1 -0 !]>
Visual Studio replaces the lines
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Release|Any CPU.Build.0 = Release|Any CPU
with
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|Any CPU.ActiveCfg = Debug|x86
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|x86.ActiveCfg = Debug|x86
{EA5BE444-40F0-4972-A03E-5B794FAECF21}.Debug|x86.Build.0 = Debug|x86
How can I prevent it?