Here's what I ended up doing:
The problem I was trying to solve is not repeating myself (D.R.Y.) and specifying a solution-wide output directory (in a solution with a lot of projects) - that is, when compiling a solution, all projects would have their output directory set to something like $(SolutionDir)bin\Debug
or $(SolutionDir)bin\Release
. It is worth mentioning that some projects are included across repositories and in more than one solution.
At first, I created an MSBuild file (a <Project>
XML - called it MySolution.sln.targets
). In it, I defined a <PropertyGroup>
that overrode the <OutputPath>
property to:
$(SolutionDir)bin\$(Platform)\$(Configuration)
Then I added the following import to all the relevant projects, before the build targets import:
<Import Project="$(SolutionPath).targets" />
That way, each solution has an accompanying .targets
file defining such things that I want to be solution-wide.
This worked well, but then I encountered the following problem: The abovementioned $(Platform)
and $(Configuration)
macros refer to the project's properties, not the solution-wide ones. What would happen if my solution's Debug/Any CPU configuration still built some very specific project in its Release configuration? As far as I'm aware, after thoroughly examining the documentation, no such macros are exported that have a solution-wide granularity.
I found ceztko's Visual Studio extension which made Visual Studio export exactly the macros that I was looking for - but after some experimentation and fiddling, I discovered that this extension set them too late - only upon building the solution. This caused issues with Visual Studio's Incremental Build feature - It kept thinking that the projects were out of date because it was looking in the wrong place - it wasn't aware of the variables, but MSBuild.exe was.
I started fiddling with the IVsUpdateSolutionEvents
interface, tracing when each method is called - and then discovered that IVsUpdateSolutionEvents.OnActiveProjectCfgChange
is called twice when opening a 1-project solution in a fresh Visual Studio, or when changing the solution's configuration from Debug to Release. Further fiddling revealed that if I set the project to compile in Release in both solution configurations, this method now got called once instead of twice when changing solution configurations.
I forked the extension's repository and amended the issue by moving the macro-setting logic to the above-mentioned method. You can find it here.
Disclaimer: this may not interact so well with batch-build operations from the IDE, and requires you to export these properties yourself when building from MSBuild.exe's command-line.
Good luck in your travels.