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
Related
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.
I am a big fan of the C++ Core Guidelines and I like to follow them in all projects I work on, so I enabled the following option in my project template in Visual Studio 2017:
This tool is great and helps me write better code, but I simply cannot figure out how to make it only analyze my files. Whenever my project has a dependency such as Boost or OpenCV, I will get plastered with a wall of warnings:
These dependencies are added through vcpkg, however, the same thing happens when adding them manually with C/C++ > General > Additional Include Directories.
Is there any way to only make these warnings apply to project files, and not all included files?
As mentioned in the comments, right after the following section in your .vcxproj near the end of the file:
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
The problem may be solved by adding the following after the section mentioned above:
<PropertyGroup Condition="'$(Language)'=='C++'">
<CAExcludePath>$(QTDIR)\include;.\GeneratedFiles;$(CAExcludePath)</CAExcludePath>
</PropertyGroup>
Furthermore, if you are using vcpkg, which was the case in my situation, you will need to add the following element to the CAExcludePath:
$(VcpkgRoot)include
This will ensure that all headers from any packages will not be analyzed.
While trying to answer this SO question I encountered an issue which I cannot explain and would appreciate your input on.
Setup:
Have solution consisting of several C++ projects (Test.sln),
Add a brand new project to your solution (BuildInstaller.vcxproj),
Open BuildInstaller.vcxproj in text editor and append following xml fragment right before closing </Project> tag:
<Target Name="Build">
<MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=Win32" />
<MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=x64" />
</Target>
Above code overrides default Build target of the BuildInstaller project and everytime the project is being built, it builds its parent solution with Release configuration for both Win32 and x64 platforms,
To prevent unbounded recursion, open Configuration Manager in Visual Studio and uncheck "Build" checkbox for BuildInstaller project for all combinations of Debug/Release and Win32/x64,
Then, still in Configuration Manager, create a new configuration, e.g. Installer for which you should uncheck all the other project's Build checkbox and leave it checked for BuildInstaller only,
Now build your solution for Installer configuration.
I would expect this build to finish successfully, but it simply hangs, even though BuildInstaller should not be built recursively as we are recursively building the Test.sln only for Release configuration.
I am not asking whether this is a good approach or how to work around it, I am just curious why the build hangs. Setting output window verbosity to Diagnostic was of no help to me.
I am using Visual Studio 2013 Ultimate.
MSBuild has an internal protection about recursion in the projects. Normally your build will fail with error MSB4006 in a case if any sort of circular dependency is discovered in the build graph. That said, if I were to guess what might have caused the hang, and if it is related to recursion, I would have inclined on the side of .sln files. The reason is that the way MSBuild treats .sln files is quite peculiar. Any time it encounters .sln file, it converts it to intermediate representation that actual MSBuild engine can understand. That intermediate representation does not have any identifier similar to the project file, thus the circular dependency detection logic might not work correctly if .sln is in the loop.
To solve your particular problem, there are couple of ways. The easiest one is to remove BuildInstaller.vcxproj from Test.sln. The second is to modify BuildInstaller.vcxproj as follows:
First, create an ItemGroup, populated with all projects from the solution:
<ItemGroup>
<AllMyProjects Include="..\Proj1\Proj1.vcxproj" />
<AllMyProjects Include="..\Proj2\Proj2.vcxproj" />
...
<!-- DO NOT ADD BuildInstaller project to prevent recursion!!! -->
</ItemGroup>
Then build the projects for every configuration:
<Target Name="Build">
<MSBuild Projects="#AllMyProjects" Properties="Configuration=Release;Platform=Win32" />
<MSBuild Projects="#AllMyProjects" Properties="Configuration=Release;Platform=x64" />
</Target>
The downside of the second approach is that you have to remember to maintain list of projects in sync between .sln and your installer project.
I am newbie.
I want to create a Visual C++ project as programmatically.
I have tried EnvDTE objects but they are working on instance of current solution but I want to edit different project file of different solution that not opened anywhere.
How can I get instance of different project to edit it?
And I am using Visual Studio 2013 Express. Is there any limimation for it? Should I use VSPackage's?
Thanks.
In general I would recommend considering a build system like CMake or Scons. It allows to generate build scripts for arbitrary platform (as such it includes MSVS solution files).
However, you might simply edit project file with some script or program. Project files are plain xml files and it's easy to add external files.
<ItemGroup>
<ClCompile Include="some_file.cpp" />
</ItemGroup>
I have a solution with several C++ projects. For some of the projects I need some custom file copy, e.g. to copy some configuration files to the output directory or to copy the output files of one project to a specific folder after build.
In some cases I don't want or cannot add these files to the projects directly through the Visual Studio IDE. I created simple .targets files which I can reuse and add to the projects which need the file copying.
Here is a simple example .targets file for copying configuration files:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CopyCustom
</BuildDependsOn>
</PropertyGroup>
<ItemGroup>
<CustomFiles Include="$(ProjectDir)Config\**\*.xml" />
</ItemGroup>
<PropertyGroup>
<DestCustFolder>$(OutDir)Config\</DestCustFolder>
</PropertyGroup>
<Target Name="CopyCustom"
Inputs="#(CustomFiles )"
Outputs="#(CustomFiles ->'$(DestCustFolder)%(RecursiveDir)%(FileName)%(Extension)')">
<Message Text="Copy custom files..." />
<Copy SourceFiles="#(CustomFiles )" DestinationFiles="#(CustomFiles->'$(DestCustFolder)%(RecursiveDir)%(FileName)%(Extension)')" SkipUnchangedFiles="true" />
</Target>
</Project>
Through the "Build Customization" dialog in Visual Studio I add it to the project so it will be included like this at the end of the project file:
<ImportGroup Label="ExtensionTargets">
<Import Project="..\Targets\CopyCustom.targets" />/
</ImportGroup>
This should enable incremental build of my custom target. If I just edit one of my custom files (and none of the C++ files) and build it form the console with
msbuild foo1.vcxproj
it will actually detect the changes and does an incremental build for my custom target. If no changes are made the target is skipped.
If I do however build inside Visual Studio it will not detect changes to the custom files and only and gives me the message that the project is up to data:
========== Build: 0 succeeded, 0 failed, 5 up-to-date, 0 skipped ==========
I would have to additionally change one of the C++ files to make it check all targets again and to the incremental build.
I was expecting that Visual Studio just executes MSBuild which will then do the up-to-date check on the projects, so it should be the same result as running MSBuild from the console. I was trying to get more information by setting the verbosity level to diagnostic but I just get the same line. It seems to me that MSBuild is not even executed for the project but Visual Studio itself determines that the project is up-to-date.
So I was wondering how Visual Studio actually determines when it should execute MSBuild for a project.
I asked basically the same question before on the MSDN forum but couldn't get a clear answer.
See this suggestion on Microsoft Connect.
Basically you need to set DisableFastUpToDateCheck property to true to disable the fast-up-to-date check.
Just add to your vcxproj or your targets file:
<PropertyGroup>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
I found an answer by looking into the book "Inside the Microsoft Build Engine, Second Edition".
Note: I also updated the same in my question in the MSDN forum but I will mainly duplicate the text here again for completeness.
On page 280 they actually saying that the IDE does a "fast up-to-date check" on the project-level. It only spawns a project build and does a more fine-grained check on the individual tasks if this rough project-level check fails.
When running MSBuild from the command line however there is always a fine-grained up-to-date check on the individual tools.
So the IDE only seems to do this fast check on the files which are added to the projects directly and set as one of the "Input File" types.
In my opinion this is not a good design. I would prefer that the IDE is only used to edit the MSBuild project files and then just invokes MSBuild to do the up-to-date check. This would make it much clearer.
I can understand that in a solution with a lot of projects it can make the up-to-date check much faster but there should be at least an option to disable the fast up-to-date check. I was checking the IDE if there is a way to disable this behavior but could not find anything.
The solution suggested here actually works and I am using it at the moment. But I added several custom targets for different kinds of custom files. If I add a new custom file I should never forget to set it to "Custom Build Tool" otherwise the incremental build for this file will not work.
I guess a solution would be to make a full build customization for my custom files and use specific file extensions for them so Visual Studio will automatically detect them when I add them to the project and sets the right Item Type.