How to change %(DisableSpecificWarnings) in Visual Studio 2019 - c++

After upgrading to VS 2019 I'm trying to make the C++ warnings useful again by disabling some that I don't care about, for example C26812
I know I could go to every project's property page and add this string to "Disable Specific Warnings" but that would be too much duplication (I've got a lot of projects). So instead I'm trying to change the DisableSpecificWarnings variable which is common to all Projects: 4996;6031;%(DisableSpecificWarnings)
How and where can I change this global variable in Visual Studio 2019 ?

For anyone interested, I ended up creating one GLOBAL.props file which is shared across projects.
To add this sheet, select project go to "Property Manager", select the Project and do "Add Existing Property Sheet". For example DisableSpecificWarnings used by all sub-projects is defined here. For further information on Compile and Link properties, see MSBuild documentation:
Clcompile: https://learn.microsoft.com/en-us/visualstudio/msbuild/cl-task?view=vs-2019
Link: https://learn.microsoft.com/en-us/visualstudio/msbuild/link-task?view=vs-2019
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<DisableSpecificWarnings>4675;4541;4702;4267;4996;26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

Project defaults come from several .props files, organized by scope, language and platform. The location (and even presence) of those .props files has changed between versions, and can depend on the history of past versions installed prior to VS 2019.
One (safer) way to identify the default .props being actually used is to create a new C++ project and look at the <Import Project ... /> lines in the generated .vcxproj file. For example, I am getting the following on my machine, in increasing order of specificity.
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
The last one is supposed to be the most specific, carrying the per-user per-platform settings. It appears to no longer be created with fresh VS 2019 installs, but it is inherited from prior versions and is still recognized when present (see Microsoft.Cpp.Win32.user.props file missing for example).
To see what "$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" expands to, open the project settings and pretend to change any of editable paths in the configuration, then click Edit in the dropdown menu and paste the .props path in the edit box. The actual path will show right below it, for example C:\Users\<user name>\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props.
Find the file on disk, or create it if it doesn't exist already, and insert the following under Project/ItemDefinitionGroup/ClCompile.
<DisableSpecificWarnings>26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
If the .props file did not exist and you had to create it from scratch, the complete file would be:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<DisableSpecificWarnings>26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
</Project>
In order to modify the per-machine defaults, rather than the per-user ones, follow the same steps but use one of the $(VCTargets) files instead.

Related

What does the BuildMacro element do in Visual studio properties and projects?

I have seen this several times:
<PropertyGroup Label="UserMacros">
<SomePropertyName>trunk</SomePropertyName>
</PropertyGroup>
<ItemGroup>
<BuildMacro Include="SomePropertyName">
<Value>$(SomePropertyName)</Value>
</BuildMacro>
</ItemGroup>
How is this different from just defining the property? To my surprise, there are only three results for this word on the MSDN, and only one is in English. The one result didn't really help me understand the construct above.
The BuildMacro is used to create custom user macros in property sheet. It could make you manage them in visual studio.
The steps:
Open View > Other Windows > Property Manager
Open property page under Configuration|Platform folder
Related links:
User-defined macros
Share or reuse Visual Studio project settings
What does BuildMacro actually do

VS2017 blocking on non-existing object files when debugging with pdb file

We are in the process of switching Visual C++ projects to the vc141 toolchain (VS 2017). We have encountered a problem where Visual Studio is unable to use a .pdb file whose source .obj files don't exist anymore (for example because they have been compiled on a build server).
Let's take a very simple executable project:
#include <iostream>
int main() {
std::cout << "Hello world\n";
std::cin.ignore();
}
The .vcxproj file is all default, except for <GenerateDebugInformation>true</GenerateDebugInformation> to generate the pdb file.
Reproduction steps are, always using VS2017:
Compiling the project
Placing a breakpoint inside main
Removing the intermediate Debug/ directory containing the .obj files
Disabling build-on-run through the configuration manager (so it won't recreate them)
Starting a debug session
This works fine with the vc100 (VS 2010) toolchain, and the breakpoint works, but it immediately triggers the following error with vc141:
Error: Unable to open file
<path>\Debug\main.obj. Error code = 0x80070003.
This very generic error code corresponds indeed to FACILITY_WIN32/ERROR_PATH_NOT_FOUND. The path to main.obj can be found inside both versions of the .pdb file, thus it is unclear to us why VS suddenly breaks down when it doesn't find it.
The "Modules" view shows that the .pdb file seems to be loaded correctly. Additionally, the breakpoint's tooltip shows the following error:
The breakpoint will not currently be hit. Unexpected symbol reader error while processing MyUser_141.exe.
What could be a solution or a workaround for this problem, given that we cannot debug on the machine that compiles the binaries in our real-case application?
Here is the full .vcxproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<RootNamespace>MyUser_141</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectGuid>{90982029-29B8-4C9B-AFB7-B8F555F15C1E}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
Further research:
We tried some other toolchain versions. The bug is not present in v14.0 (VS 2015), but is present as soon as 14.11 (VS2017 15.3).
Using v141_xp, which as far as we can tell uses the same toolchain but older system libraries, works.
To fix this, make the following change in the property pages of the project(s) that build your executable(s) and DLL(s):
Configuration Properties -> Linker -> Debugging -> Generate Debug Info -> Generate Debug Information optimized for sharing and publishing
Static libraries, having no link step, don't need this. .EXEs and DLLs do.
When you specify /DEBUG with no additional options, the linker defaults to /DEBUG:FULL for command line and makefile builds, for release builds in the Visual Studio IDE, and for both debug and release builds in Visual Studio 2015 and earlier versions. Beginning in Visual Studio 2017, the build system in the IDE defaults to /DEBUG:FASTLINK when you specify the /DEBUG option for debug builds. Other defaults are unchanged to maintain backward compatibility.
Source : https://developercommunity.visualstudio.com/content/problem/259283/error-unable-to-open-file-mainobj-error-code-0x800.html

Batch compiling only one project in a solution

Say I have a solution that contains three projects
SolutionA
ProjectA
ProjectB
ProjectC
The whole solution is set to build as AnyCPU. However, ProjectB is a managed C++ project and I would like it (and only it) to build both Win32 and x64. I am using TFS to perform these builds nightly. Is there any good way to accomplish this?
The .sln file itself cannot build same project in two configurations or platforms at the same time. One possible workaround is to create a custom project, that would be invoked by .sln and would call in its turn a projectA twice -- with two different values of Platform parameter. The custom project file would look like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
</PropertyGroup>
<Target Name="build">
<MSBuild Project="ProjectA.vcxproj" Properties="Platform=Win32;Configuration=$(Configuration)" />
<MSBuild Project="ProjectA.vcxproj" Properties="Platform=x64;Configuration=$(Configuration)" />
</Target>
</Project>
For this to work you need to do the following. 1. In the solution disable build of ProjectA (or remove it from .sln). 2. Add your custom project to the .sln.
Also, remember, you cannot pass explicit /p:Platform option to the

Compiling c++ project through the command prompt

I'm having a hard time trying to figuring out what field to fill into an xml file I'm creating. I have been trying to follow 'Using MSBuild to Create a Visual C++ Project'(http://msdn.microsoft.com/en-us/library/dd293607.aspx) but I'm stuck on the xml part.
So the fields are:
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets" />
</Project>
The only part I know I have to change is the Item group portion to match all my .cpp and .h files. Are all the fields necessary? Can you give an example for the $(VCTargetsPath) in each of the Import Projects? This seems simple but only after the first time of doing it. Thanks.
VCTargetsPath is property of the toolset, defined in registry. In your case, for ToolsVersion="12", registry location would be HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0. Normally the toolset is configured automatically when you install appropriate SDK.
I honestly never created a C++ project file with msbuild in the editor, always let vs do it for me and include/invoke the vcxproject file through my seperate custom build file... however, the TargetPath, is the directory of the configured targets for C++ of MSBuild, on my machine with vs 2013 installed its (configured to use the vc++ 12.0 tools): C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120.
These imports define the ClInclude task and all other C++ related tasks your tools support.

How can I force the C++ platform in MSBuild?

I have a program which must build as 32 bit. It gets shipped with an x64 application. As a result, there is an installer which gets a bitness.
The installer is built with a wixproj that must be built with /p:Platform=x64 -- but the vcxproj needs to build as x86.
I tried forcing Platform to be x86 or Win32 by setting it explicitly:
<PropertyGroup>
<Platform>Win32</Platform>
</PropertyGroup>
but it appears that the command line switch that got passed to the wixproj "wins" when building.
Is there some way that the project file can force Platform to be Win32 no matter what is specified on the command line?
(for csproj I was able to do this:
<PropertyGroup>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
but that doesn't have any effect on C++ it seems)
Finally figured this out. MSBuild has a setting TreatAsLocalProperty that allows a project file to override any variable, which goes into the Project node at the beginning of the file.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build"
ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
TreatAsLocalProperty="Platform"> <!-- !!! -->
<PropertyGroup>
<Platform>Win32</Platform>
</PropertyGroup>
<!-- Now Platform is Win32 no matter what! -->
</Project>