Tag: Cplusplus

  • C Assert and Wrapping Macros in Do/While Loops

    I was planning on writing a couple of entries on C macros, including assert macros and why you should wrap your macros in do/while loops. While doing a bit of research I came across a couple of excellent blog posts by Charles Nicholson on these very topics. Rather than try and out do him, I’ll just refer you to him!

    Building a Better Assert Macro
    http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/

    Why You Should Be Wrapping Your Macros in Do/While Loops
    http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/

  • Targeting Windows 2000/XP RTM/XP SP1 from Visual Studio 2010

    I’m currently working on a little native C application using the C-runtime libraries (CRT) to detect Windows power events. I ran into a problem when testing my application on Windows XP Professional 32-bit RTM (e.g. “Gold Release”, no service packs). When I attempt to run the application, I get the following error message:

    Entry Point Not Found
    Entry Point Not Found. The procedure entry point DecodePointer could not be located in the dynamic link library KERNEL32.dll.

    Huh?!

    After a little digging, it turns out the Microsoft rather quietly discontinued targeting the Windows 2000 and Windows XP RTM/SP1 platforms with Visual Studio 2010. The last release that will target these platforms is Visual Studio 2008.

    There were various suggestions on how to workaround this issue including recompiling the CRT, implementing the missing functions in your own w2kcompat.lib, FASM/MASM assembly magic, and reverting to using Visual Studio 2008.  However all of these offered significant drawbacks for me. I do not want to be in the business of supporting a custom compiled version of the CRT. I don’t understand the assembly editing based solutions sufficiently to feel comfortable supporting them on x86 and x64 platforms in the field.

    The workaround that works for me and that I ultimately used is to target the Visual Studio 2008 (VC 9.0) Platform Toolset from within my Visual Studio 2010 projects as suggested here and here. There were three key upsides for me with this solution:

    1. This seems like the most reasonable option to support in deployments. No custom builds and no assembly hacking.
    2. I can continue to use VS2k10 and all it’s goodness. (Well, almost. Any feature added in the VC10 runtime won’t be available. )
    3. This modification can be done on a per project (and actually, per Build Configuration) basis, so I don’t have to make system-wide changes to my VS install.

    The major downside to this option is that it requires me to have Visual Studio 2008 installed, but this was something I was willing to live with.

    One way to accomplish this workaround that was suggested is to place the path to the Visual Studio 2008 VC libs (e.g. “C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\lib” for 32-bit builds) first in the Additional Library Directories under the Linker options for your project. This messy because you have to do this for every configuration of every project in your solution that needs it and it varies for x86 versus x64 builds. Making matters worse is that the location of these files may vary from system to system, so what works for one developer’s machine may not work for another. Not ideal.

    The cleaner and easier way to do this is to set the Platform Toolset in the project’s general properties pane. You still need to do this for each project as well as all configurations and all platforms. However, unlike the previous method, this one uses the same value across configurations and platforms and it’s portable across machines.

    Setting the Platform Toolset in Visual Studio 2010
    Setting the Platform Toolset in Visual Studio 2010
  • Suppress Unreferenced Parameter/Variable Warnings in Windows C/C++ Applications

    I use warning level 4 (/W4) for all of my projects as well as “warnings as errors” (/WX) on Release builds. During development I often run into C4100 warnings for unreferenced parameters or variables that are either:

    1. Currently unused but will be used once development is complete
    2. Due to a specific required signature (e.g. for use in a Windows callback in an API) but that I don’t need

    In the past I’ve just used a cast to suppress the warnings like this:

    // Suppress C4100 Warnings for Unused Parameters
    (void*) param1;
    (void*) param2;
    

    I came across a collection of handy macros today in WinNT.h (you should include <Windows.h>):

    //
    // Macros used to eliminate compiler warning generated when formal
    // parameters or local variables are not declared.
    //
    // Use DBG_UNREFERENCED_PARAMETER() when a parameter is not yet
    // referenced but will be once the module is completely developed.
    //
    // Use DBG_UNREFERENCED_LOCAL_VARIABLE() when a local variable is not yet
    // referenced but will be once the module is completely developed.
    //
    // Use UNREFERENCED_PARAMETER() if a parameter will never be referenced.
    //
    // DBG_UNREFERENCED_PARAMETER and DBG_UNREFERENCED_LOCAL_VARIABLE will
    // eventually be made into a null macro to help determine whether there
    // is unfinished work.
    //
    
    #if ! defined(lint)
    #define UNREFERENCED_PARAMETER(P)          (P)
    #define DBG_UNREFERENCED_PARAMETER(P)      (P)
    #define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V)
    
  • Integrating the Subversion Revision into the Version Automatically with Native C/C++

    We’ve covered how to automatically include the mercurial revision into the version. Now how about doing this for Subversion?

    The basics of how to accomplish this are much the same as in the mercurial example. The major difference is that I don’t use WSH to generate the version file. Unlike TortoiseHg, which includes the CLI tools for Mercurial, TortoiseSVN does not. Therefore you have two choices:

    1. Download a CLI SVN implementation like SlikSVN and implement a script similar to the one that we did for Hg.
    2. Use the SubWCRev.exe utility that comes with TortoiseSVN to generate your version file from a template

    Since I already use TortoiseSVN and SubWCRev has already done the heavy-lifting for me, I’ve decided to go that route. As usual, I’ll be doing my example using Visual Studio 2010 Professional although these techniques should work on other versions of VS as well.

    The source code for this post is available here.

    Step 1: Setup Basic Versioning

    First we need to have the basic building blocks in place, as discussed in Versioning a Native C/C++ Binary with Visual Studio

    Step 2: Add an SVN Version Template

    Next we create a file named svn_version.h.tmpl in our project. I generally keep it under the Resources filter. This file serves as the basis of the SVN version header that we ultimately want to include in our project. The tokens (e.g. $WCREV$) will be automatically replaced by the SubWCRev utility later.

    #ifndef _SVN_VERSION_H_
    #define _SVN_VERSION_H_
    
    #define SVN_LOCAL_MODIFICATIONS $WCMODS?1:0$  // 1 if there are modifications to the local working copy, 0 otherwise
    #define SVN_REVISION            $WCREV$       // Highest committed revision number in the working copy
    #define SVN_TIME_NOW            $WCNOW$       // Current system date &amp; time
    
    #endif
    

    Step 3: Add the Pre-build Step

    Finally we need to add a pre-build step which will execute the SubWCRev tool, thus generating the svn_version.h file prior to the binary being built.

    1. Right-click on your project
    2. Select Properties
    3. Click Build Events
    4. Click Pre-Build Event
    5. In the Configuration drop-down, select All Configurations
    6. In the Command Line field, enter:
      SubWCRev.exe $(SolutionDir) $(ProjectDir)\svn_version.h.tmpl $(ProjectDir)\svn_version.h
    7. In the Description field, add a comment such as:
      Generate the svn_version.h file with the necessary repo identify info for versioning

    NOTE:If you have multiple projects in the same solution that all need to use the same information from Subversion you have a few choices. One is to put the template and pre-build event in one project which all the other projects depend on and add a link to the svn_version.h file that gets generated. Another option is to create a specific version project that all it does is generate the svn_version.h file and define common version information and then have every project in the solution depends on it so it’s executed first in the build order.

    Step 4: Update Version.h

    The version.h file we created in the basic versioning post needs to be updated to include the generated svn_version.h file and to make use of its defines.

    #include "svn_version.h"
    
    #define STRINGIZE2(s) #s
    #define STRINGIZE(s) STRINGIZE2(s)
    
    #define VERSION_MAJOR               1
    #define VERSION_MINOR               0
    #define VERSION_REVISION            0
    #define VERSION_BUILD               SVN_REVISION
    
    #if SVN_LOCAL_MODIFICATIONS
      #define VERSION_MODIFIER "M"
    #else
      #define VERSION_MODIFIER
    #endif
    
    #define VER_FILE_DESCRIPTION_STR    "Built " STRINGIZE(SVN_TIME_NOW) " from r" STRINGIZE(SVN_REVISION)
    #define VER_FILE_VERSION            VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
    #define VER_FILE_VERSION_STR        STRINGIZE(VERSION_MAJOR)        \
                                        "." STRINGIZE(VERSION_MINOR)    \
                                        "." STRINGIZE(VERSION_REVISION) \
                                        "." STRINGIZE(VERSION_BUILD)    \
                                        VERSION_MODIFIER
    
    #define VER_PRODUCTNAME_STR         "c_svn_autoversion"
    #define VER_PRODUCT_VERSION         VER_FILE_VERSION
    #define VER_PRODUCT_VERSION_STR     VER_FILE_VERSION_STR
    
    #if LIBRARY_EXPORTS
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
    #else
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".exe"
    #endif
    #define VER_INTERNAL_NAME_STR       VER_ORIGINAL_FILENAME_STR
    
    #define VER_COPYRIGHT_STR           "Copyright (C) 2011"
    
    #ifdef _DEBUG
      #define VER_VER_DEBUG             VS_FF_DEBUG
    #else
      #define VER_VER_DEBUG             0
    #endif
    
    #define VER_FILEOS                  VOS_NT_WINDOWS32
    #define VER_FILEFLAGS               VER_VER_DEBUG
    
    #if LIBRARY_EXPORTS
      #define VER_FILETYPE              VFT_DLL
    #else
      #define VER_FILETYPE              VFT_APP
    #endif
    

    Step 6: Add SVN Ignore on svn_version.h

    Finally, we need to go ahead and add an svn:ignore on svn_version.h because we don’t want its difference checking in every commit and we don’t want it constantly marking the working copy as modified if it’s tracked.

    Results

    Now when each time you build your projects, the latest Subversion information of the working copy is automatically included in the file version information.

    Version info with Subversion
    Version info with Subversion

    Final Thoughts

    So there you have it, you can now automatically include all the necessary information from your Subversion working copy in your build to map them one-to-one with the source code that was used.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Versioning a Native C/C++ Binary with Visual Studio

    Last time in  Mapping Binaries in the Field to Source Code in the Repository we talked about the value of including version information in your binaries. Today I’m going to explain how to accomplish this in Visual Studio for a native C/C++ binary. I’m using 2010 Professional, but it should work on other versions as well.

    The source code is available here.

    Step 1: Add a Version Resource

    1. Right-click on your project
    2. Select Add->Resource
    3. Select Version
    4. Click New

    This will give you two files: resource.h and <project_name>.rc. I generally rename the .rc file to be version.rc

    Step 2: Updating Version.rc

    Out of the box the version.rc file will have you define the values right there. I recommend that you instead define the values in a version.h file and use those defines in the version.rc file.

    Edit the resource file in a text editor:

    1. In the Solution Explorer, Right-click on version.rc
    2. Select Open With
    3. Select C++ Source Code Editor
    4. Scroll down to the Version section

    Here is a template Version section that I frequently use (and will build on below):

    /////////////////////////////////////////////////////////////////////////////
    //
    // Version
    //
    VS_VERSION_INFO VERSIONINFO
     FILEVERSION        VER_FILE_VERSION
     PRODUCTVERSION     VER_PRODUCT_VERSION
     FILEFLAGSMASK      0x3fL
     FILEFLAGS          VER_FILEFLAGS
     FILEOS             VER_FILEOS
     FILETYPE           VER_FILETYPE
     FILESUBTYPE        0x0L
    BEGIN
        BLOCK "StringFileInfo"
        BEGIN
            BLOCK "040904b0"
            BEGIN
                VALUE "FileDescription",  VER_FILE_DESCRIPTION_STR "\0"
                VALUE "FileVersion",      VER_FILE_VERSION_STR "\0"
                VALUE "InternalName",     VER_INTERNAL_NAME_STR "\0"
                VALUE "LegalCopyright",   VER_COPYRIGHT_STR "\0"
                VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR "\0"
                VALUE "ProductName",      VER_PRODUCTNAME_STR
                VALUE "ProductVersion",   VER_PRODUCT_VERSION_STR "\0"
            END
        END
        BLOCK "VarFileInfo"
        BEGIN
            VALUE "Translation", 0x409, 1200
        END
    END
    

    Step 3: Adding a Version Header

    Next we create a file named version.h to provide a more convenient location to set the various version information. This is especially useful if you are sharing version information across multiple projects in a single solution. Here’s the information I generally start with mine:

    
    #define STRINGIZE2(s) #s
    #define STRINGIZE(s) STRINGIZE2(s)
    
    #define VERSION_MAJOR               1
    #define VERSION_MINOR               0
    #define VERSION_REVISION            0
    #define VERSION_BUILD               0
    
    #define VER_FILE_DESCRIPTION_STR    "Description"
    #define VER_FILE_VERSION            VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
    #define VER_FILE_VERSION_STR        STRINGIZE(VERSION_MAJOR)        \
                                        "." STRINGIZE(VERSION_MINOR)    \
                                        "." STRINGIZE(VERSION_REVISION) \
                                        "." STRINGIZE(VERSION_BUILD)    \
    
    #define VER_PRODUCTNAME_STR         "c_version_binary"
    #define VER_PRODUCT_VERSION         VER_FILE_VERSION
    #define VER_PRODUCT_VERSION_STR     VER_FILE_VERSION_STR
    #define VER_ORIGINAL_FILENAME_STR   VER_PRODUCTNAME_STR ".exe"
    #define VER_INTERNAL_NAME_STR       VER_ORIGINAL_FILENAME_STR
    #define VER_COPYRIGHT_STR           "Copyright (C) 2011"
    
    #ifdef _DEBUG
      #define VER_VER_DEBUG             VS_FF_DEBUG
    #else
      #define VER_VER_DEBUG             0
    #endif
    
    #define VER_FILEOS                  VOS_NT_WINDOWS32
    #define VER_FILEFLAGS               VER_VER_DEBUG
    #define VER_FILETYPE                VFT_APP
    

    Step 4: Add the Necessary Include

    The final step is to add the necessary include line to the version.rc file for the version.h file:

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    #include "version.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    

    Results

    Now when you build your application, all the version info above will be defined in the binary itself. Much of this information is available directly from the Details pane of the Properties window in Explorer.

    Version Info
    Version Info

    Final Thoughts

    Note that this information is static from build to build. You must change the version numbering yourself or use a script to auto-increment values. I’ll be discussing how to make the BUILD number automatically correspond to the revision info from the working copy of the source code using Mercurial or Subversion in an upcoming post.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET