What configuration and platform does msbuild use by default when building a solution file or project files - msbuild

If I execute msbuild from the command line with my solution file or project file as input without setting configuration and platform how does msbuild determine which configuration and platform to use for each project in the solution or the single project file?

In case of solution files - both msbuild and xbuild try to find Debug config and Mixed platforms platform, but if that doesn't exist then it falls back to the first one that it can find under SolutionConfigurationPlatforms in the .sln file. Keep in mind that this is just solution level config/platform, and it uses the mapping in ProjectConfigurationPlatforms in the .sln file to determine the config/platform to use for the project.
In case of project files, the *proj files usually have the default Configuration and Platform specified. But if even that is missing then the Microsoft.Common.*targets file chooses Debug|AnyCPU as the default.
Update: default specification in the csproj might look like this:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
...
It's essentially saying "if $(Configuration) is unspecified, then set it to Debug", and similar for Platform.

Related

VS 2022 change project variable like $(AssemblyName)

How to change variables like $(AssemblyName)? I cannot find where they are defined.
Defaults for these are defined in the SDK that your project uses. For example, if your project file looks like:
<Project Sdk="Microsoft.NET.Sdk">
Then you'll find these defined by the Microsoft.NET.Sdk.props file that is part of that SDK.
The definition for <AssemblyName> defaults to your project name:
<AssemblyName Condition=" '$(AssemblyName)' == '' ">$(MSBuildProjectName)
</AssemblyName>
You can set this in your project file if you want it to be different from the default:
<PropertyGroup>
<AssemblyName>WhateverNameIWant</AssemblyName>
</PropertyGroup>
Expert tip: If you want to see everything that is defined in your project, you can see how MSBuild processes the file by running either of these commands (they're equivalent):
dotnet build -pp > out.txt
msbuild /pp > out.txt
Spoiler: there's a lot encapsulated in the SDK.

How to avoid Visual Studio 2022 to add project configuration to output path

Visual Studio 2022 is adding subfolders to the base output path.
Is there a way to prevent it from adding Release/Debug subfolders to the output path?
Visual Studio 2022 - Project properties
The output path is a concatenation of a bunch of MSBuild properties. Depending on your project type, it can happen in the project file, in a targets file you import explicitly, or in an implicit import such as via an MSBuild SDK. In any of these cases, you should be able to override it by setting the value explicitly in your project file.
Taking the 3rd case as an example (using the Microsoft.NET.Sdk), in Microsoft.NET.DefaultOutputPaths.targets you'll find the defaults specified like this:
<BaseOutputPath Condition="'$(BaseOutputPath)' == ''">bin\</BaseOutputPath>
<BaseOutputPath Condition="!HasTrailingSlash('$(BaseOutputPath)')">$(BaseOutputPath)\</BaseOutputPath>
<OutputPath Condition="'$(OutputPath)' == '' and '$(PlatformName)' == 'AnyCPU'">$(BaseOutputPath)$(Configuration)\</OutputPath>
<OutputPath Condition="'$(OutputPath)' == '' and '$(PlatformName)' != 'AnyCPU'">$(BaseOutputPath)$(PlatformName)\$(Configuration)\</OutputPath>
<OutputPath Condition="!HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
Notice how the $(OutputPath) is basically appending the $(Configuration) to the $(BaseOutputPath).
If you want to always have the same output path, you can set <OutputPath>Your\Desired\Path</OutputPath> in your project file. Once you've set the value, this default logic above will be skipped based on the now-false condition ('$(OutputPath)' is no longer empty).
However, this may break incremental build if you build different configurations without deleting the contents of the output folder between builds.
I know this is an old question, but here's the full solution based on Microsoft's Debugger Settings:
Click on Project > [name of project]
In Build > Output, change the Base output path to C:\ [full directory path] \ [name of project]
Click on Project > Edit Project File
Add to PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>C:\[full directory path]\[name of project]</OutputPath>
In my case - with a Nunit test project it didn't help either. The Debug and Release folders were always created.
I had to make the following changes in the project file:
From:
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<IsPackable>false</IsPackable>
<BaseOutputPath>bin\</BaseOutputPath>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>
to:
(add the two false values and BaseOutputPath --> OutputPath and BaseIntermediateOutputPath --> IntermediateOutputPath)
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<IsPackable>false</IsPackable>
<OutputPath>bin\</OutputPath>
<IntermediateOutputPath>obj\</IntermediateOutputPath>
</PropertyGroup>

Can't deploy from VS2013 (or TeamCity) after TypeScript 1.6 upgrade

Today I updated to TypeScript 1.6, and now the CopyPipelineFiles task is failing when trying to deploy web applications.
I redirect TypeScript's compiled JavaScript output directory to scripts\compiled\ in the Web project's settings (via TypeScriptOutDir entry in the csproj file) and this has always worked fine up until now. Typescript files are being compiled correctly, and to the correct directory (ie scripts\compiled\ under the web project directory).
However, the CopyPipelineFiles task seems to be getting confused about the root directory of TypeScript files, and now always assumes that it is the root directory of the web project. As a result, it's adding folders to the path that don't exist, for example, after compiling scripts\foo.ts, instead of grabbing scripts\compiled\foo.js MSBuild is looking for \scripts\compiled\scripts\foo.js. I have tried using $(ProjectDir) in the output directory, and I've also tried setting the TypeScriptRootDir to the appropriate root directory (e.g. scripts\) but the problem persists.
The only way I've been able to remedy the situation is to remove the output directory and allow the compiled JavaScript files to be output to the same locations at their TypeScript counterparts.
The following is an example of a real error I've received, where the path of the TypeScript file would be scripts\account\app.ts:
Copying file scripts\compiled\scripts\account\app.js to obj\Release\AspnetCompileMerge\Source\scripts\compiled\scripts\account\app.js failed. Could not find a part of the path 'scripts\compiled\scripts\account\app.js'
This happens on all local machines with Typescript 1.6 installed, as well as our TeamCity build server with 1.6 installed.
Filed a bug report with the TypeScript team and they've confirmed it. Seems to be an issue with how the compiler is computing absolute paths. The workaround right now is to explicitly set relative paths for both the outDir and the rootDir, so something along the lines of this:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>
<PropertyGroup>
<TypeScriptRootDir>Scripts\typescript</TypeScriptRootDir>
</PropertyGroup>
In my case I've just moved both the outDir and rootDir to the property group with no condition since I don't need to switch the outputDir between builds, something like so:
<PropertyGroup>
<TypeScriptRootDir>Scripts\typescript</TypeScriptRootDir>
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>

What is default msbuild platform

How does msbuild chose a platform if it is not specified? It seems to me that for some solutions it selects "Mixed Platforms" for others "x86".
I switch on the diagnostics level of logging and the only thing I can see is that "Initial Properties" at the beginning contain e.g. "Platform = Mixed Platforms" without any explanation why.
To preempt some answers, I know that I can override the platform manually. That is not an issue. I need to know what msbuild does when it is NOT specified.
This may help: I was researching this and finally tracked down the default platform for my install, by looking in Microsoft.Cpp.Default.props (line 21 in this version of Visual Studio), which lives in Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120:
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
This means that under VS12 (Visual Studio 2013) MSBuild will pick Win32 as the platform if no other platform is explicitly specified. As noted in some other questions, setting an environment variable named Platform will change the default to the value you set.
Important note: If you invoke MSBuild on a Visual Studio solution file (*.sln) rather than a project file, and you don't specify a platform in the MSBuild arguments, then it appears that MSBuild will choose the platform automatically based on the first entry under the SolutionConfigurationPlatforms global section in the solution file. I haven't found this documented anywhere but from experimentation it appears to be the case. This means that editing your project file and providing a different default Platform property (as described above), MSBuild will ignore this default, because it will have chosen the platform already before it even starts looking at the project. Invoking MSBuild directly on the project file seems to bypass this behavior.
MSBuild does not choose but whatever MSBuild project it is building may default certain properties. I am assuming that your question relates to how MSBuild builds a solution file.
msbuild.exe "somesolution.sln" /t:Build
You need to look at the projects that make up the solution, in there you will see the properties that are set. For example you will probably see the following at the top of the project file:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
...
</PropertyGroup>
This shows a PropertyGroup containing amongst others two properties, Configuration and Platform. Their values are set based on a Condition. The condition says says that if no value has been set for the property Configuration it should default to 'Debug'. Likewise if nothing is set for Platform it should default to AnyCPU.
You may also see a Conditional PropertyGroup:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
What this condition says is that if the property Configuration and Platform match Debug and AnyCPU then it should apply all of the properties contained within.
A point to note is that the property names are just an arbitrary name and the values are just strings. However when building .Net projects there is a convention to which these properties and their values are a part. To see what the default values are you do not need to open each project in a text editor. You can go into Visual Studio and look at the solution configuration.

How or why is MSBuild choosing the x64 platform when I don't specify it instead of AnyCPU?

I'm running msbuild.exe via Rake from a regular PowerShell console. This is the command as printed from a diagnostic level run
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "D:/Projects/machine.specifications/Source/Machine.Specifications/Machine.Specifications.csproj31881140" /maxcpucount /target:Build /verbosity:diagnostic /property:Configuration=Debug /property:TrackFileAccess=false /property:BuildInParallel=false /property:BuildRunner=Rake
And the build is failing because msbuild is picking x64 as the Platform.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(483,9): error : The OutputPath property is not set for project 'Machine.Specifications.csproj37103470'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='X64'. You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project.
I'm not passing it in on the command line (or from the script). The csproj has a default configuration
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
and two specific configurations
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
So, I expected the AnyCPU platform to be selected. But, for some reason, something is picking or sending in x64. I don't think the Rake system is a problem here, I've seen this behavior before on raw cmd line calls to msbuild (but I haven't documented them).
I'm on 64-bit Windows 7, calling msbuild 4.0. I don't know if that's relevant.
I am loading the 64-bit Visual Studio tools (C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64) using Invoke-BatchFile in my PowerShell profile. Could that be the culprit?
Why would msbuild deliberately choose x64 anyway? The 32-bit version doesn't choose x86 for you.
*1: The PowerShell console is at %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
*2: I'm running the MSpec build (here's the rakefile and the msbuild call)
When you launch Visual Studio x64 command window, it sets an environment variable :
Platform=X64
This is a difference from the 32 bit command window, where this environment variable is not defined, and MSBuild then uses the conditional logic to use default platform.
You can either remove the Platform environment variable in your batch file, or pass in explicit Platform property as a parameter to MSBuild.