October 2020


  • Blog

Setting the Visual Studio Debugger path using CMake

Debugging our just-built executables was a real source of frustration early on in our Windows programming experience. Getting all the correct libraries into the path was tedious at best, and more often than not a nightmare of hellish proportion. To be certain, copying files around and hacking environment variables to this end is just asking for it. It’s not a matter of if a critical mistake will be made, it’s a matter of when; and that’s just the command line version of events. Needless to say, we weren’t happy.

When it came time to run the code in the Windows Debugger, things were almost just as bad. Every time we wanted to debug an executable, we had to make modifications to a generated Visual Studio project file. The procedure was time consuming, tedious, and error prone. We needed a solution that would ensure the correct behavior every time, and without any human intervention. The problem was that CMake did not, and to the best of my knowledge does not currently have, any mechanism for modifying the Visual Studio Debugger path in a generated project. Still, we needed to get the job done with CMake. Maybe it couldn’t set the debugger path, but it could write out a configured file. Enter the Visual Studio .user file.

The Solution

Before we begin, I am aware that Microsoft suggests avoiding the use of .user files. Their caution stems from source code control issues however, and the files we are about to generate are intentionally volatile. We aren’t going to commit anything in the build directory to our source code repository, though the input file that follows should be placed somewhere in your source tree and committed.

Step 1:
Create a CMake input file called “project.vcxproj.user.in” with the following content:

<?xml version="1.0" encoding="utf-8"?>	 	
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">	 	
 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">	 	

The value for PATH in the LocalDebuggerEnvironment tag is of course up to you; the above is merely a simple example using “Debug” as the Configuration Type.

Step 2:
Configure project.vcxproj.user.in for each executable in your solution/project; something like this:

foreach(src ${EXEC_SRCS}) 
	add_executable(${src} ${src}.cc) 
	configure_file(project.vcxproj.user.in ${CMAKE_BINARY_DIR}/${src}.vcxproj.user @ONLY) 

Now when you start a debugging session, the appropriate paths will be set and things should work as expected. There are likely other and perhaps better ways to accomplish this goal, with the ideal solution being to set the debugger path with some CMake property. In the meantime, we make do with the tools avalable to us.

Continue Reading

An “aha” moment; grep for Windows

For the past few years, I’ve slowly migrated away from my beloved Linux development environment to the at-first dreaded Windows platform. Mind you, this move was not by choice; I’m just following the money. As Winston Zeddmore once said; “If there’s a steady paycheck in it, I’ll believe anything you say”. I’m down with that.

In some cases, I very much enjoy the GUI tools. Eclipse (of course), Winmerge, Notepad++, and the Cmake GUI come to mind right away. In others cases, the GUI thing irritates the living daylights out of me. Take grep for instance — my God do I miss grep! Windows Search, no matter how nifty, is not a tool for tearing through all the makefiles in your project looking for a string like “$$HACK”, and doing so in seconds or fractions thereof. Eclipse search functionality is very powerful, but for the “down and dirty” tasks, a bit like smashing a peanut with a sledgehammer. Before you say it though, I’m not interested in installing Cygwin, the GNU utilities for windows, or the MKS toolkit. This is not a religious decision on my part; I want my development workstation as lean and stable and uniform with respect to OS as I can keep it, because I’d rather not rely on utilities that the client may not have on their workstation.

So all the aforementioned aside, I stumbled upon the “findstr” command on Windows last year. It’s apparently been there all along, I was simply unaware of it. It’s essentially grep for Windows, and although it may be a bit dumber than it’s UNIX counterpart, all the basics are present.

Posted in Tools Windows

Continue Reading

Overriding the default CMake build types

Let’s imagine that our C++ source code utilizes Design By Contract methodology. The default build types provided by CMake are too general to work for us, and we want to be able to toggle use of contracts during the compile. We need to create new build types that suit our needs, and we need them to work on Linux and Windows. And so we’d do something like this in CMakeLists.txt:

# Set the Configuration types ...
    set(CMAKE_CONFIGURATION_TYPES Debug_contracts Debug_no_contracts Release_contracts Release_no_contracts 
         RelWithDebInfo_contracts RelWithDebInfo_no_contracts CACHE STRING "Supported configuration types"
    set(CMAKE_CONFIGURATION_TYPES Debug_contracts Debug_no_contracts Release_contracts Release_no_contracts 
         CACHE STRING "Supported configuration types"
# And then make the Project function call.

And then set values for your newly defined build types:

# Just an example for Debug_contracts; repeat with needed flags for other types.
# Contracts on is the default state. We'd add /DNDEBUG in a "no_contracts" config. 
        "${MY_CXX_FLAGS} /Zi /D"_ITERATOR_DEBUG_LEVEL=2" /MDd /LDd /Od " 
        CACHE STRING "Compiler flags for Debug_contracts builds" )       
        CACHE STRING "Linker flags for shared libraries; Debug_contracts" )
        CACHE STRING "Linker flags for executables; Debug_contracts")            
else() # Linux
        CACHE STRING "Compiler flags for Debug_contracts builds") 
       CACHE STRING "Linker flags for executables; Debug_contracts") 

Note that setting CMAKE_CONFIGURATION_TYPES prior to the project function call will not eliminate the default configuration types (Debug, Release, MinSizeRel, RelWithDebInfo, et al.), from the cache, but will prevent them from appearing in the VS configuration list.

Continue Reading