MSBuild and CppCheck

CppCheck is an easy to use static code analysis tool. If you want to use it right away, there is a stand alone GUI version in the package. Static code analysis is like having another programmer look over your code and comment on what you have written. I think it is a good idea to run a lot of non conflicting static tools simultaneousely. I even think that it is a good idea to hinder compilation if such a tool lists any errors. CppCheck states on its project page “zero false positives” – so running it should never have a negative effect.

Here I want to show how to get MSBuild to execute a CppCheck task. The following snippet is the one I want to write into my project xml. It just calls the actual CppCheck target somewhere else. The point of that is of course the attempt of getting some reuse out of the effort.

The examples in this text looks broken because the text highlighting tool used is breaking it. For some reason it keeps creating endtags where I don’t want them. So copy with care and work yourself forward in small increments.

<Target Name="Build" Returns="@(ManagedTargetPath)">
<MSBuild Projects="..\Utility\cppcheck\cppcheck.vcxproj" properties="ProjectDir = $(ProjectDir)" />
<MSBuild Projects="$(MSBuildProjectFile)" Targets="NormalBuild" />
</Target>

<Target Name="NormalBuild" Condition=" '$(_InvalidConfigurationWarning)' != 'true' " DependsOnTargets="_DetermineManagedStateFromCL;$(BuildDependsOn)" Returns="@(ManagedTargetPath)">
<ItemGroup>
<ManagedTargetPath Include="$(TargetPath)" Condition="'$(ManagedAssembly)' == 'true'" />
</ItemGroup>
</Target>

There is a problem here that I do not adress. The tests are not automatically excluded. You may or may not want this though. Since a copy of CppCheck will live inside of your project I suggest editing the cppcheck.vxproj file and just filter the files you want to exclude.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="CppCheck" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<CppCheckFiles Include="$(ProjectDir)/**/*.c" />
<CppCheckFiles Include="$(ProjectDir)/**/*.cpp" />
</ItemGroup>

<Target Name="CppCheck"
Inputs="@(CppCheckFiles)"
Outputs="$(ProjectDir)\CCPCheck\%(CppCheckFiles.Filename)%(CppCheckFiles.Extension).stamp" >
<Exec Command="cppcheck.exe %(CppCheckFiles.FullPath) --enable=style --template="{file}({line}): error:{severity}-{id}: {message}""/>
<MakeDir Directories="CCPCheck"/>
<Touch
Files="CCPCheck\%(CppCheckFiles.Filename)%(CppCheckFiles.Extension).stamp"
AlwaysCreate = "true" />
</Target>
</Project>

The above xml code is the MSBuild ready buildscript for CcpCheck. I will go through it line by line and summarize some features.

  • line 2
  • The default target is set so you do not have to worry about the implementation when calling it.

  • lines 3 to 6
  • The itemgroup of files you want to have checked. If you want to filter some files you can not filter them here. Removing files from an itemgroup is only possible once the task is running. I suggest creating a target dependency for that.

  • line 8
  • The inputs and outputs are important for the incremental build. It’s all about the file timestamps. If the modification of an input file is younger than the last output file a rebuild is needed. Inputs and outputs have to map 1:1 for this to work.

  • line 9
  • The execution command starts CppCheck with parameters that are docummented in the CppCheck manual. The “–template” option provides the format for the output. All output is formatted to look like an error. The file/line combination in the output allows you to doubleclick the message in VS2010 and jump right to the error source.

  • line 10
  • This ensures that our timestamp directory exists.

  • lines 11 to 12
  • “Touch” and “always create” will create the timestamps that we need for incremental build to work.

I hope this little guide is fun and useful for you. It is not all too detailed but it touches on enough detail to get anyone started.

Feel free to comment about your experience with this approach.

MSBuild and GTest

Noting your intentions in testform is an excellent idea. To do that you want to have a testframework like googletest.

After getting a testframework you want to set it up so that it runs every time you press on compile. In fact you most likely do not want to run the program at all but just run your tests. As long as you do not break a test your code is still what you intended it to be. If you find a bug, just add a test. If you want to add a feature add a test for it first.

Most buildcontrol tools can be set up so that one click compilation and test will work. Here is one way to do it with MSBuild.

Create a new empty C++ project without any fancy stuff like precompiled headers etc. In that project you want two new files. One something_main.cpp and one something_test.cpp. Specifically the endings are important. The endings will be used to filter your files later. For example we avoid a conflict between two main functions. One from the testframework, one from your application. Another useful thing is to filter other test from unittests. That way you could have a seperate build for your time consuming tests.

You can not copy paste the following files easily, some manual work is required. Here is the content of the files:

something_test.cpp

#include "../Utility/GTest/gtest.h"
TEST(casename, testname){ EXPECT_EQ(1,1); }

something_main.cpp

void main(void){}

something.vcxproj

Most of the build file is automatically generated with just a small portion of manual editing. After you created a new project the vcxproj file already exists. At some point you want to copy the testframework into your project, or at least that is what i do. The place where you want it to be already influences some lines in the other files. You need the path for all include statements. The include statement of something_test.cpp and the include statement of the build xml (line 153). Your overall foldersetup will look something like the folders in the next picture. Note how few files the googletest framework will use. Also I screwed up the naming – but do not worry about that.

The xml build contains references to a test build configuration. To get it you would have to edit the xml file and the solution file. I suggest taking the shortcut via Visual Studio. Use the assistant to create a new build configuration. Copy the Properties for it from the Debug configuration. And Name it “Test” – that is the name used in the build xml above. If you can not access the assistant you most likely have the express edition installed. In that case you have to configure Visual Studio first.

Posting the xml build file does not look good and takes up a lot of space. However talking about it without the file is kind of pointless. So please go ahead and download the file. I suggest opening it with notepad++ and switching the language to xml. Reading from top to bottom through the build xml:

  • line 80 Here are the precompiler definitions for the Test|Win32 build. The _Debug definition was removed since it can interfere with the testframework. An empty property $(INJECT_HERE) was inserted. This allows us to inject preprocessor definitions later.
  • lines 104 to 113 Leave this part alone. Visual Studio will automanage this part. It basically lists all your project files that are to be compiled.
  • line 115 to 117 Another inject mechanism. This one creates a key. If we start in test configuration the key contains a long string. If we start in non test configuration the key contains an empty string. Looking at this key later will tell us if we started in test configuration.
  • line 122 The default build target gets re-specified here. This overrides the old buildtarget. The old buildtarget was set during one of the import statements. If you want to take a look at them you can output their path using the message task. They are also xml files following the msbuild schema.
  • line 123 Deleting the gtest obj files ensures a rebuild of them (unless nothing at all was edited) That way precompiler definitions are reapplied.
  • line 124 in any case and for all builds, the target TestBuild is executed. Testbuild is specified below. It basically builds the unittests. Since testbuild is the only target in Test configuration this will return the testexecuteable to Visual Studio. Visual Studio will then execute the returned executeable if you started the build as build and run.
  • line 125 and 126 These two lines are conditional and are executed when not executing test. RunTest runs the tests and outputs to the buildlog. If the tests fail the returnvalue of the executed gtest file tells msbuild to abort the build. There will be a builderror in Visual Studio allowing you to see what went wrong.
  • line 136 this is my favorite line in the whole file. There is an inject to inject a keyword into the preprocessor (see line 80) But only if it is run in testmode the injected string is not empty. (see line 116) This allows your testframework wheather it was started with the testconfiguration or not. Provided of course your testframework gets recompiled at every run. (see line 123)
  • line 139 to 144 this is a copy of the original build from one of the imported files. the new build did overwrite it – but since it is still needet here is a copy of it. The only change is the new dependencie ModifyFiles.
  • line 146 Just a simple exec task to run the tests.
  • lines 150 to 157This target filters the files before the normal build is executed. For the testbuild the main file has to be removed since the testframework has its own main function. Also we want to remove all testcode from the normal release and debug builds This is the place to filter if you want a _fake implementation for every class or _integration for non unittests.

When I am testing I like my console to remain open so I can enjoy the view. Hitting CTRL + F5 works here, but usually I am too lazy to hit that correctly. After jumping through a lot of hoops to get the precompilerdefinition through, we are free to add a conditional pause to the googletest main function. Something along these lines:

#ifdef MSBUILD_RUN_WITH_STOP_AT_END
std::cout<<"....\n"; 
_getch();
#endif

You should be able to copy these results and have your own googletest build party. When you do, please pay attention to the colors of googletest when executing the test build. The regular wondows console is not an ansi console and I do not have colors there using ansi escape sequences. However if you run the tests within the Visual Studio console there are colors. That makes me wonder if Visual Studio ships with its own ansi console. If you have information about that feel free to comment.

There are some things, like incremental build or creating config files on the fly, that I was unable to explain in this context. I will continue in the next few days with CppCheck and/or PClint to fill that gap.

Hello World with MSBuild.exe

I recently sorted my old code and i was thinking that i will not keep all of it. While i delete most of it though i will remake some of it and put it up on this blog.

If i start a new project these days i usually select my toolchain first. Afterwards i copy all tools i want to use somewhere into my project. That way i dont have to worry about their versions later. The final step before starting to code is to mix all tools into the build process. That is quite important since it allows you to do all you want to do in one click.

Along this line i will present a mini series of MSBuild tutorials to show how i link the programs. Starting, as alway, with a hello world example.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="mainTarget" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="mainTarget">
<Message Text="Hello World" Importance = "high"/>
</Target>
</Project>

This code can be saved in any file and msbuild.exe will take the filename as a parameter. There is a DefaultTargets information that tells MSBuild what to execute if no target is specified. The target has a task that will print a message on execution. The message has its importance increased to maximum, so it gets displayed without regard to a verbosity level. I saved it on my computer as a simple txt file. After locating the highest version of MSBuild.exe on my computer i executed the xml script. The following output was created on my machine (german, because the world hates me and defaults to installing everything in german for me):

Microsoft maintains a MSBuild.exe reference.

  1. The things you want MSBuild.exe to do are grouped as targets.
  2. Targets consist of tasks.
  3. There is other stuff as well.

The capabilities of MSBuild appear pretty much complete. Microsoft delivers a set of Tasks that can be used to create Targets. There are more than the microsoft tasks available. Everyone can write new tasks in C#. Even better, most are already available and collected in other sources online. Examples include the ZIP task or the nunit (c#) task.

A new C++ project comes with a premade *.vcxproj file. This fresh file contains references to other prepared msbuild files. The actual build targets are somewhat hidden in the referenced files.

Portions of the generated project file are managed by visual stuio and are best left alone. Some portions can be overridden to change behaviour. Some portions are best modified from within visual studio because they have to line up with changes to the solution file. Some portions are waiting to be added by the customizing programmer (procustogrammer).

In the upcoming days i will link a cpp toolchain together. I will blog about it here for all readers including future me.