Home > OS >  How do I configure Visual Studio 2022 to build projects on another drive?
How do I configure Visual Studio 2022 to build projects on another drive?

Time:01-08

I have a system with a 1 TB SATA-connected SSD as the system disk and a 256 GB M.2 SSD as an auxiliary data disk/scratch drive. I would like to configure Visual Studio 2022 to create all project build directories (but not the projects themselves) inside a folder on this scratch drive (F:\build). From what I can tell, CMake-based projects can achieve this by creating a global CMakeSettings.json template; however, I haven't found anything for MSBuild-based projects. Is it possible to configure the MSBuild defaults to do this?

A folder tree of what I'm trying to do would look a little like this:

F:\
|- foo
|- bar
|- build
   |- Project1
   |- Project2

CodePudding user response:

MSBuild is not a build script generator like CMake. When you create a project file with Visual Studio or the dotnet tool, the project itself is an MSBuild script. The project file should be source controlled. It is not a 'scratch' file.

Generally, MSBuild projects use an 'intermediate' directory and an 'output' directory. By default, the intermediate directory is obj\ and the output directory is bin\. These defaults can be changed by changing the BaseIntermediateOutputPath and BaseOutputPath properties. (See List of common properties and parameters.)

You can set or change properties globally by using a Directory.Build.props file. (See Customize your build.) The Directory.Build.props file is imported very early which is important because there are numerous properties defined based on the BaseIntermediateOutputPath and BaseOutputPath properties.

You might create a Directory.Build.props file like the following:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$([MSBuild]::GetPathOfFileAbove('$(MSBuildThisFile)', '$(MSBuildThisFileDirectory)../'))" />

  <PropertyGroup>
    <Acme-Drive Condition="'$(Acme-Drive)' == ''">F:</Acme-Drive>
    <Acme-BuildDir Condition="'$(Acme-BuildDir)' == ''">$(Acme-Drive)\build\</Acme-BuildDir>

    <BaseOutputPath Condition="'$(BaseOutputPath)' == ''">$(Acme-BuildDir)$(MSBuildProjectName)\bin\</BaseOutputPath>
    <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">$(Acme-BuildDir)$(MSBuildProjectName)\obj\</BaseIntermediateOutputPath>
  </PropertyGroup>

</Project>

Some notes on this MSBuild code:

  • MSBuild will search up the directory structure and will load the first Directory.Build.props file found. The Import will search for and if present will load the next file. It's a good practice to always add the Import when creating a Directory.Build.props file (or a Directory.Build.targets file). The chain of imports will continue to work if Directory.Build.* files are added or removed in the directory tree.
  • Acme-Drive and Acme-BuildDir are custom properties. 'Acme-' is used as a prefix. The prefix can be anything that is appropriate for your organization or product. The prefix both provides a lower chance of a property name collision and indicates this is a custom property.
  • The Condition="'$(Acme-Drive)' == ''" tests if the property is unset. The value F: is only set if the Acme-Drive property doesn't already have a value. Properties can be redefined and overridden from other files and from the command line. For example, passing /p:"Acme-Drive=z:" on the MSBuild command line would switch the drive for that one run.
  • The value of the $(MSBuildProjectName) property is the name of the current project.

If

  • Your local working directory for the source code is C:\repos\MyProduct.
  • The code above is saved as C:\repos\MyProduct\Directory.Build.props.
  • You have project files:
    • C:\repos\MyProduct\project1\Project1.csproj
    • C:\repos\MyProduct\project1\Project2.csproj

then

  • Both projects will use the same Directory.Build.props file.
  • For Project1, $(BaseOutputPath) will be F:\build\project1\bin.
  • For Project2, $(BaseOutputPath) will be F:\build\project2\bin.
  • Related