Tag Archives: Visual Studio

Debugging Optimized Code in Visual Studio 11

Good to know

http://blogs.microsoft.co.il/blogs/sasha/archive/2011/10/12/debugging-optimized-code-in-visual-studio-11.aspx

VC11, the compiler in Visual Studio 2012, has a new undocumented switch. Add /d2Zi+ to your builds. This blog post was written before 2012 was released, but I guess this feature never got out of the undocumented phase, which might mean it’s not entirely stable.

I’m still going to try it.

Controlling where Visual Studio puts files

I actually like Visual Studio. More specifically, I like Microsoft’s C++ compiler as being both speedy and producing pretty good code on x86 and x64. So, it’s more accurate to say that I tolerate Visual Studio overall. It’s frustrating how they can take good ideas (msbuild) and screw them up (msbuild).

Visual Studio by default scatters artifacts everywhere. I like a tidier build folder. Here are the non-build-output artifacts I know about (as opposed to your source files like .cpp, or as opposed to build artifacts like .obj, .lib and .exe).

  • *.aps
  • *.filters
  • *.idb
  • ipch/
  • *.sdf
  • *.suo
  • *.user

Why should these be kept separate from your source? Because you hand source to other people, but you would never hand any of these artifacts to others.

.suo

This is present in Visual Studio 2003 and up. Microsoft calls this “Solution User Options”, or alternatively “solution options file”; it is per-user, and contains environment state like window positions, breakpoints and so forth.

Tough luck; barring writing some ninja file system filter, your .suo files go right next to the .sln file. It’s pretty ugly.

.sdf

This is present in Visual Studio 2010 and up. This is the IntelliSense database.

First off, if the IntelliSense database is disabled, neither the .sdf file (which is the IntelliSense database) nor ipch folders (which contain IntelliSense’s precompiled information) are created.This is draconian, but maybe you see no need for IntelliSense because you use some other tool like Visual Assist. This isn’t quite the same as fully disabling Intellisense, but almost – the only feature that still works if you do this is the #include auto-complete.

To disable the IntelliSense database, go to Tools -> Options -> Text Editor -> C/C++ -> Advanced, and change Disable Database to True. This will have the side-effect of removing ipch folders, too. I’m not saying you want to do this.

If you want to just move where the .sdf file goes, then follow the directions for relocating the ipch folders below – the .sdf database and the ipch folders are created in the same location.

ipch/

This is present in Visual Studio 2003 and up. This contains precompiled information that IntelliSense generates and uses.

Starting with Visual Studio 2010, Intellisense creates an ipch folders to store precompiled headers. Of course, it can’t use the compiler’s precompiled headers, it has to make its own (that was mild sarcasm, sorry). By default, this goes next to the corresponding solution file (*.sln).

Unfortunately, there’s no solution-level control for anything – a solution file is really just a container to reference project files, and have a modicum of coordination in regards to build dependencies. But, at least for Intellisense, there is a global preference for where to store ipch files; you can put all your ipch folders in your temp folder, for example. The folder names inside the ipch folder are already disambiguated with the name of the solution and a hash of the full path to the solution to avoid conflicts.

Visual Studio 2010

Go to Tools > Options > Text Editor > C/C++ > Advanced ->Fallback Location (Tools menu, pick the Options menu item to bring up the Options dialog, expand the Text Editor section, expand the C/C++ subsection, click on the Advanced subsection, scroll down to the sub-group labelled Fallback Location).

Set Always Use Fallback Location to True. If you do nothing else, this will put your ipch folders in %TEMP% (which at least in Windows 7 defaults to C:\users\AppData\Local\Temp\ if your boot is C: and you haven’t played with any default settings). If you want more fine-grained control, put a path into Fallback Location – but, honestly, %TEMP% is a good place for these. Observation notes that it puts its files inside a VC++ folder in your temp director.

You’ll also want to set Do Not Warn If Fallback Location Used to True. If you leave it set to False, you’ll get a ominous-looking dialog when Visual Studio starts up and can’t find the database file; users who press Cancel will inadvertently disable IntelliSense for that session of Visual Studio. And you’ll get this each time you start up, unless you click the checkbox in the dialog (which says “don’t warn me again”). There are probably uses for this warning, but I can live without it.

.vcxproj.user

This is present in Visual Studio 2012 and up.

This file contains per-user settings. Specifically, it seems to exist to contain the debug settings like “Working Directory” and “Command Arguments”, and was previously persisted in the .suo file (is this correct?). Generally, you don’t check this file into source control. This file is created by a wizard, but it’s set to a default value, so if you just delete the file, there should be no harm. If a user changes any debug settings, this file will get created.

Reference

http://stackoverflow.com/questions/4315681/how-to-change-ipch-path-in-visual-studio-2010

http://stackoverflow.com/questions/3922660/which-visual-c-file-types-should-be-committed-to-version-control/3923352#3923352

http://blogs.msdn.com/b/vcblog/archive/2010/03/09/intellisense-browsing-options-in-vc-2010.aspx

http://msdn.microsoft.com/en-us/library/vstudio/kcw4dzyf.aspx

 

Debug heap on Visual Studio == slowness

This hit me recently. It’s described in this StackOverflow post.

Why does my STL code run so slowly when I have the debugger/IDE attached?

Running from the IDE imposes a pretty large cost on debug STL code – the StackOverflow post dramatizes it, but it’s still pretty significant. Worse, there’s even a cost on release STL code. You can disable it by setting an environment variable _NO_DEBUG_HEAP to 1, and fortunately you can do this directly in the IDE, and not globally.

While I appreciate having extra debugging to find problems, the debugging cost can’t be high enough that it prompts you to disable it.

Visual Studio 2012 solution file grammar

Here is the start for a grammar for sln files in Visual Studio 2012. Since the solution file format hasn’t changed much since Visual Studio 2005, a little parameterization probably handles all projects, and I’ve attempted to do that here. Also, I’ve made non-terminals as short as possible without killing readability, in the interests of making something that’s legible in just a few columns. And I really need to respect the whitespace indentation rules – the parser in Visual Studio doesn’t force them on input, but does follow indentation rules on output, so I may as well bake them into the grammar somehow.

Also note that MSBuild has an internal parser for sln files that you can access with some work – see Getting Visual Studio version of a Solution file. I have no idea if there is a formal grammar with a parser, or if Microsoft only has ad-hoc parsers. I’m guessing the latter…

sln = ver-header entries
entries = (project | global)+

ver-header = visual-studio ", " format-version "\n" comment-version "\n"
visual-studio = "Microsoft Visual Studio Solution File"
format-version = "Format Version numeric-version
numeric-version = nv_2002 | nv_2003 | nv_2005 | nv_2008 | nv_2010 | nv_2012
nv_2002 = "7.00"
nv_2003 = "8.00"
nv_2005 = "9.00"
nv_2008 = "10.00"
nv_2010 = "11.00"
nv_2012 = "12.00"
comment-version = "# Visual Studio " year-version
year_version = "2005" | "2008" | "2010" | "2012"

project = project-id "\n" project-parms* "EndProject" "\n"
project-id = "Project(" '"{' pt-guid '}"' )" = " proj_parms
proj_parms = proj-name ", " proj-path ", " proj_guid
pt-guid = vcppguid | vbguid | vcsharpguid | webguid | siguid
vcppguid = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
vbguid = "F184B08F-C81C-45F6-A57F-5ABD9991F28F"
vcsharpguid = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"
webguid = "E24C65DC-7377-472b-9ABA-BC803B73C61A"
siguid = "2150E333-8FDC-42A3-9474-1A3956D46DE8"
proj_name = '"' STRING '"'
proj_path = '"' STRING '"'
proj_guid = HEX{8} "-" HEX{4} "-" HEX{4} "-" HEX{4} "-" HEX{12}

global = "Global" "\n" global-section* "EndGlobal" "\n"
global_section = gs_start "\n" gs_body "EndGlobalSection" "\n"
gs_start = "GlobalSection" "(" gs_kind ")" " = " gs_when
gs_kind =   "SolutionConfigurationPlatforms"
          | "ProjectConfigurationPlatform"
          | "SolutionProperties"
          | "ExtensibilityGlobals"
          | "ExtensibilityAddIns"
gs_kind_05 =   "SolutionConfiguration"
             | "ProjectConfiguration"
             | "ProjectDependencies"
gs_when = "preSolution" | "postSolution"
gs_body = gs_configs | gs_plats | gs_props
gs_configs = (gs_config "\n")*
gs_config = sol_cfg_plat " = " sol_cfg_plat
sol_cfg_plat = sol_cfg "|" sol_plat
sol_cfg = "Debug" | "Release" | STRING
sol_plat = "Win32" | "x64" | STRING
gs_plats = (gs_plat "\n")*
gs_plat = "{" proj_guid "}" "." sol_cfg_plat "." gs_action " = " sol_cfg_plat
gs_action = "ActiveCfg | "Build.0"
gs_props = "HideSolutionNode = " ("TRUE" | "FALSE") "\n"

This is horribly incomplete and horribly informal. I need to work more in individual elements and write the grammar fragments for them. The above would parse a subset of solution files, but it would generate many illegal solution files. Also, there are some elements that are deprecated and probably converted to newer elements. I noted a few of those in the gs_kind_05 field for elements that stopped existing at some point after VS 2005.

This is what an trivial wizard-generated solution file looks like in Visual Studio 2012, that has one project. I have split lines in some cases using a C-preprocessor ‘\’ syntax, in order to not have line wrapping, and I made short GUIDs for the same reason. Visual Studio probably needs the exact Microsoft GUID format – a 128-bit GUID split into 5 chunks of 32-16-16-16-48 bits, respectively. For completeness’ sake, I turned 8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942 into 8BC9-8D11-00A0C91B, and 67DC3F40-5C82-445C-8EE9-0B78724D839D into 67DC-8EE9-0B78724D.

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9-8D11-00A0C91B}") = "vc12-test-1-empty", \
        "vc12-test-1-empty\vc12-test-1-empty.vcxproj", \
        "{67DC-8EE9-0B78724D}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Win32 = Debug|Win32
        Release|Win32 = Release|Win32
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {67DC-8EE9-0B78724D}.Debug|Win32.ActiveCfg = Debug|Win32
        {67DC-8EE9-0B78724D}.Debug|Win32.Build.0 = Debug|Win32
        {67DC-8EE9-0B78724D}.Release|Win32.ActiveCfg = Release|Win32
        {67DC-8EE9-0B78724D}.Release|Win32.Build.0 = Release|Win32
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
EndGlobal

Some notes

For SolutionConfigurationPlatforms, I can’t figure out what’s going on here. I’m guessing that one side is a label that’s used in places, and the other side is the actual name of a config. I’m guessing that there’s some unification going on here for projects that have different subsets of configurations? I tried editing one side or the other, but Visual Studio must be “repairing damage”, because it puts things back the way it wants it.

For Project, I can’t figure out what the proj-name item is actually for. I don’t know what uses it, because it doesn’t control what’s displayed in Visual Studio (the name from the vcxproj file itself is used).

The values for GlobalSection are actually in the registry, in a key named SolutionPersistence for the relevant version of Visual Studio. Each entry just has a GUID, which in turn probably points to a DLL that handles that value? There are 20 of these in my installs of VS 2010 and VS 2012, and even the deprecated VS 2005 variants are listed, so maybe they aren’t deprecated?

Visual Studio 2002, which is “Format Version 7.00″, and Visual Studio 2003, which is “Format Version 8.00″, did not have the second comment line with the Visual Studio year entry.

Project dependencies are in a ProjectSection inside a Project entry, like so:

Project("{8BC9-8D11-00A0C91B}") = "Tool", "Tool.vcproj", "{0C1B-BCF4-01F038A7}"
    ProjectSection(ProjectDependencies) = postProject
        {6678-A354-3A61F442} = {6678-A354-3A61F442}
    EndProjectSection
EndProject

The dependencies are always “project depends on itself”, instead of “B depends on A”. It’s possible that there’s some other dependency allowed?

Reference

Hack the Project and Solution Files

Premake generates sln files, but in an ad-hoc fashion. It doesn’t read them.

Solution (.sln) File from MSDN – old, it’s for VS 2005, but still mostly relevant.

Hand-constructing Visual Studio 2012 vcxproj

Here is the simplest legal vcxproj that I could make.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
</Project>

The first line declares it as an XML file, with the body in UTF-8.

<?xml version="1.0" encoding="utf-8"?>

The root element of an MSBuild XML document is Project. I’m assuming that the ToolsVersion=”4.0″ refers to MSBuild 4.0.

<Project DefaultTargets="Build" ToolsVersion="4.0"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

Every vcxproj must have at least one project configuration. This is wrapped inside an ItemGroup element that has a label of “ProjectConfigurations”. There are only a few sub-elements of Project allowed.

  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>

You can have as many project configurations as you want, although the real variable is Configuration – you’re more limited on Platform, since MSBuild has to understand that platform.

This project file will actually open up in Visual Studio, or be parsed by MSBuild, but you need a few more elements before you have something useful. First, note that project XML files are written in a specific order, and parsed as they are written. The XML is not in a canonical order, so you can’t use a tree parser to read or write these.

First off, a lot of the behavior is inherited. There are some magic import lines to scatter throughout your project file. Let’s focus on those. Here they are in a group. (Note for expert users: I am ignoring the fact that project files try to inherit from a user directory – that’s an abomination, and you don’t want that in your project files).

...
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
...
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
...
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
...

All of these are found in your MSBuild folder, which for me is C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110; your mileage may vary.

Microsoft.Cpp.Default.props handles some default settings; if you don’t specify Platform, then Platform=Win32; if you don’t specify a Configuration, then Configuration=Debug; and so on.

Microsoft.Cpp.props is a wrapper to import the proper platform props, which is “$(VCTargetsPath)\Platforms\$(Platform)\Microsoft.Cpp.$(Platform).props”, which simply turns around and imports “$(VCTargetsPath)\Microsoft.Cpp.Platform.props”. The layers are used by platforms like ARM to declare min platform versions. This eventually leads to files like Microsoft.Cpp.Win32.v110.props, which sets paths, and Microsoft.Cpp.Common.props, which sets the majority of the defaults.

Microsoft.Cpp.targets sets up a lot of the default scaffolding for building C++ projects. Or, to restate it, it sets up the project file to build C++ projects. It’s one of the final lines in your project file.

It would be interesting to draw out the map of what’s included here; I suspect there is some organizational method, but it’s not obvious at first glance.

Note that if you use Microsoft.Cpp.props, you will get what the system defaults to – for me, it actually defaults to v100, which is Visual Studio 2010. So you need a few lines before that include to set specific properties for the project. Strictly speaking, you only need to set the PlatformToolset to v110; everything else has a default.

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v110</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>

Now, if you put all of this together, you’ll end up with a project file that opens in Visual Studio and could actually be used to add files to, build with, and etc. It’s still not a complete project file; if you compare against a wizard-generated one, you’ll see lots of extra settings. But it is complete and almost useful.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.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">
    <ProjectGuid>{FBEF15CB-6F54-49E3-853B-4238684902B8}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <RootNamespace>SHA1</RootNamespace>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v110</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <Import Project="..\time-hash.lib.props" />
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Why am I doing this? I need to construct good Visual Studio projects automatically, and I don’t want to create things based on copy/paste information.

MSBuild

Microsoft’s new way, so we must use it. It’s hopefully better than driving builds through an IDE with “devenv” invocations.

This is scattered bits while I try to put a coherent picture together.

Walkthrough: Using MSBuild

Walkthrough: Creating an MSBuild Project File from Scratch

MSBuild Targets

These are half-related.

Visual Studio project properties for multiple projects (from StackOverflow)

Using property sheets in Visual Studio 2010 (from StackOverflow)

How to: Add New Property Sheets to C++ Projects

Visual Studio and MSBuild

printf(“Hello MSBuild!\n”);

Converting to MSBuild

Response to the feature poll

Exploring the New MSBuild Features for Visual C++ 2010