DoxyPress and Visual Studio

Last week I wrote about integrating Doxygen with Visual Studio. In one of the comments about that post, legalize suggested that I use its modern C++ replacement DoxyPress instead. DoxyPress is a fork of Doxygen so you should be able to migrate very easily from Doxygen to DoxyPress; there is functionality included to convert an existing Doxygen configuration file to a DoxyPress project file.

Installing DoxyPress

Here are the instructions for using DoxyPress with Visual Studio 2015 and 2017.

  1. Download the 32-bit or 64-bit Windows installer for DoxyPress as appropriate.
  2. Use Run as Administrator to execute the installer. If you do not run the installer as administrator, the installer will not be able to install the files into Program Files (or Program Files (x86) as appropriate). If you execute the installer on a computer running Windows 8/8.1 or 10, you will probably see the following messagebox. If you do not see this messagebox, you may skip forward to step 5.
    SmartScreen
    This is displayed because Microsoft is being cautious and warning you about applications and websites it does not recognize. It does not mean that the installer contains malware, just that it is not in Microsoft’s list of high use applications.
  3. To proceed, click on More info:
    SmartScreen-moreinfo
  4. Either heed the warning and click on the Don’t run button, in which case you cannot install DoxyPress, or click on the Run anyway button to continue.
    Note: I cannot and will not guarantee that the installer for any version of DoxyPress does not contain any malware. As with every application you install, you ultimately take responsibility for that.
  5. The DoxyPress installer dialog will be displayed:
    DoxyPressLanguage
    Choose your preferred language and click Next>.
  6. Continue clicking the Next> button until the installer installs DoxyPress. If the following messagebox is not displayed, proceed to step 7. If the messagebox is displayed, you did not use Run as Administrator.
    DoxyPressNoInstall
    Click the OK button to go back to the installer dialog and click Cancel, then go back to step 2 to rerun the installer using Run as Administrator.
  7. When the installation completes, click on the Finish button to close the installer.

Integrating DoxyPress With Visual Studio

  1. To integrate DoxyPress with Visual Studio, open Visual Studio and select the Tools -> External Tools… menu button. This will open the External Tools dialog:
    ExternalTools
  2. Click on the Add button. The dialog changes to:
    AddExternalTool
  3. Set the Title to DoxyPress, the Command to the executable for DoxyPress (e.g. C:\Program Files\DoxyPress\doxypress.exe), the Arguments to $(ProjectDir)DoxyPress.json, and the Initial directory to $(ProjectDir). Note that there is no ‘\’ character in the Arguments value. Check the Use Output window checkbox. The bottom portion of the dialog box should look similar to this:
    AddDoxyPress
  4. Click the Apply button to add DoxyPress as a menu item.
  5. Again click the Add button.
  6. Set the Title to DoxyPressApp, the Command to the executable for DoxyPressApp (e.g. C:\Program Files\DoxyPress\DoxyPressApp.exe), leave the Arguments blank, and set the Initial directory to $(ProjectDir). Do not check any checkboxes that are not already checked.
  7. Click the OK button to add the DoxyPressApp menu item and close the dialog box.

Generating Documentation the First Time

These instructions assume you have added the appropriate DoxyPress comments to your source code. To use DoxyPress to generate documentation:

  1. In Visual Studio, select the project you are documenting in the Solution Explorer.
  2. If this is the first time you will be generating the documenation for this project, select the Tools -> DoxyPressApp menu item. If this is first time you have ever run DoxyPressApp, the following messagebox will be displayed:DoxyPressAppSetupFileMissingThe setup file contains the location and size of the DoxyPressApp window, a list of the most recently opened DoxyPress project files, and the path to the directory that the last DoxyPress.json file was saved in.
  3. Click on the Default Location button. This saves the settings in C:\Users\<yourusername>\AppData\Local\CS\DoxyPressApp\DoxyPressApp.json. The DoxyPressApp dialog will now open:DoxyPressApp
  4. Select each of the topics in the Setup, Build Settings, and Output Formats tabs to configure the output that will be generated by DoxyPress. The various settings are described in the DoxyPress Project File web page.
  5. When done, select the Run tab:DoxyPressAppRun
  6. Click on the Options for DoxyPress button. This opens the Passed Parameters dialog:NamedParameters
  7. Enter the values you want, then click the Ok button to close the dialog.
  8. Click the Run DoxyPress button. The first time you click on Run DoxyPress, the Save File dialog will open so you can save the DoxyPress project file. Navigate to the project directory (the directory containing the Visual Studio project file (vcxproj file) and enter the file name DoxyPress.json. This file name must match the name specified in the Arguments in step 3 in the section Integrating DoxyPress With Visual Studio, above. Click the Save button to save the file and close the Save File dialog.
  9.  Your documentation will now be generated. If you selected HTML output in the Output Formats tab, click the Display HTML button to view the generated documentation; otherwise, open the generated documentation to ensure that it is created as you would like it.
  10. If you wish to make changes to how the documentation is generated, repeat steps 4 – 9 until you are satisfied. Once you are satisfied with the generated output, close DoxyPressApp.

Regenerating Documentation

When you want to regenerate your documentation, select the project in Visual Studio’s Solution Explorer and then select the Tools -> DoxyPress menu item. It will use the DoxyPress.json file you saved in the instructions above so it is not necessary to run DoxyPressApp again for the selected project.

Doxygen and Visual Studio

Doxygen is a tool for generating documentation from annotated source code. Originally created specifically for C++, it now also supports C, Objective-C, C#, PHP, Java, Python, IDL, Fortran, VHDL, Tcl, and D. Output formats include HTML, Latex, RTF (MS-Word), PostScript, hyperlinked PDF, compressed HTML, and Unix man pages. Although developed in OS X and Linux, there is also an MS Windows executable.

This post will not discuss how to document your source code for use with Doxygen, nor will it list the advantages and disadvantages of using Doxygen. You will have to decide if Doxygen is the right tool for you. You should see the Doxygen website for that. This post will simply show how to use Doxygen with Visual Studio.

There are no extensions for integrating Doxygen with Visual Studio. However, Doxygen, and Doxywizard, a wizard-based executable for creating the configuration file for use with Doxygen, are command line executables which can easily be run from the Visual Studio Tools menu. Adding Doxygen and Doxywizard to the Tools menu is done as follows. The instructions work for both Visual Studio 2015 and Visual Studio 2017.

  1. Download and install the latest Doxygen Windows binary.
  2. Open the Visual Studio Tools dropdown menu and select External Tools…
  3. This opens the External Tools dialog:
    ExternalTools
    Click the Add button. The dialog changes to this:
    AddExternalTool
  4. Change the Title to Doxygen, the command to point to the Doxygen executable (C:\Program Files\doxygen\bin\doxygen.exe on my computer), the arguments to $(ProjectDir)\Doxyfile, and initial directory to $(ProjectDir). Check the Use Output window checkbox. The lower portion of the dialog box will look like this:
    AddDoxygen
    $(ProjectDir) is the macro in Visual Studio that points to the project directory (the directory that contains the project’s vcxproj file).
  5. Click the Apply button to add the Doxygen menu item to the Tools menu.
  6. Click the Add button.
  7. Enter DoxyWizard as the Title, the location of the doxywizard executable  as the Command (e.g. C:\Program Files\doxygen\bin\doxywizard.exe), leave Arguments blank, and $(ProjectDir) as initial directory. Leave all checkboxes unchecked.
  8. Click the OK button to add the DoxyWizard menu item and close the dialog box.

The first time you use Doxygen with a project, select the Tools -> DoxyWizard menu item to open the DoxyWizard dialog, shown here:
DoxyWizardDialog

  1. Step 1: Set the working directory to be the $(ProjectDir) directory. That is the directory containing the project’s vcxproj file.
  2. Step2: Use the Wizard and/or Expert tabs to set the configuration values.
  3. Select the Run tab and then Run doxygen.
  4. If you wish, go back and change the various configuration values.
  5. Once you are satisfied with the values you have set, close the dialog. This will display the Unsaved changes message box. Click Save to save the configuration. Select the directory that contains the project’s vcxproj file. This will ensure that the configuration file is found when you run Doxygen.

You should only run DoxyWizard once for each project that you are documenting. For each subsequent document generation, use Tools -> Doxygen. Provided you saved the configuration file in the correct location, Doxygen will run correctly, saving its generated documentation to the specified directory, and sending its output to the Visual Studio Output window.

 

Google Test and Visual Studio

As you may surmise from the title, this post discusses integrating Google Test into Visual Studio. It will not discuss why you might want to use Google Test rather than Microsoft Test; I leave that to you to decide.

To fully use Google Test with Visual Studio 2015, you need two components:

  • Google Test (and Google Mock, which is included in the download), and
  • A test runner.

Installing and Using Google Test

To use Google Test, you should build a static library for Google Test as a separate project in the solution for the code you want to test. You should also create a separate project containing the unit tests.

Installing Google Test

You need to perform this step only once:

  1. Download Google Test from github. Place it in its own directory, I chose C:\googletest, so if you place it in a different location, make the appropriate changes in the instructions given in the rest of this post.

Using Google Test

Perform the following steps for each solution that you use Google Test with:

  1. If you have not already generated a solution for your code, do so now. For this post, I created a solution containing an empty project called MyProject.
  2. Add Google Test to the solution: Add a new Win32 Project to the solution. Name it GTest or something similar. Set the Application type as Static library, and clear the checkmark for Precompiled header. The Application Settings page of the Win32 Application Wizard should look like this:
    googletest1
    Click the Finish button to create the project.
  3. In the Visual Studio Solution Explorer, select the GTest project. Add the files gtest_main.cc and gtest-all.cc from C:\googletest\googletest\src as Existing Items. DO NOT copy the files to GTest project directory.
  4. As with all software projects, you must determine if you will be sharing the code for your solution with others. If you are, or you intend to use Google Test in multiple solutions, then I recommend setting user-wide settings in Visual Studio as outlined in this step; otherwise, you can set the include directories directly (also specified in this step).
    You must add …\googletest and …\googletest/googletest to the project’s Include Directories.  You do so using one of the following methods (not both!):
    (a) Create a User Macro that contains the location of your googletest directory. You need to do this only once for each configuration that you build. The settings are used for every solution and project that you build from now on. See User-Wide Settings in Visual Studio 2015 for how to do this.
    I created a macro called GTEST that points to C:\googletest\googletest, then added the following to the Include Directories:
    . $(GTEST)
    . $(GTEST)/include
    (b) Add c:\googletest\googletest and c:\googletest\googletest\include to the Include Directories for the GTest project. You must perform this step for every project and every configuration in every solution that uses Google Test.
  5. Now build the project or solution. There should be no build errors in the GTest project.
  6. If you performed step 4(a), above, and not step 4(b), open Windows Explorer and navigate to the directory containing the GTest project. Open the GTest.vcxproj file in a text editor; WordPad works well. Near the bottom of the file you will see the following lines:
     <ClCompile Include="..\..\..\..\..\..\googletest\googletest\src\gtest-all.cc" />
     <ClCompile Include="..\..\..\..\..\..\googletest\googletest\src\gtest_main.cc" />

    Change these lines to:

     <ClCompile Include="$(GTEST)\src\gtest-all.cc" />
     <ClCompile Include="$(GTEST)\src\gtest_main.cc" />

    Save the file and rebuild the solution. There should be no errors.

  7. You need some code to test. For my simple MyProject, I added a file called arithmetic.h that contains the following:
    #pragma once
    int square(const int value)
    {
        return value * value;
    }
  8. Add a new Win32 project for the unit tests. Name the project after the project containing the code under test and append Test or Tests. This is required later for test discovery by the test runner we will install later. (This is the default naming scheme for test executables; if you want to use a different naming scheme, refer to Christian Soltenborn’s comments on this post. Christian is the developer of GoogleTestAdapter, which you will install later.) In the Application Settings page of the Win32 Application Wizard, select Console application as the Application type, and uncheck the Precompiled header checkbox. Click Finish.
  9. In the Solution Explorer, select the References item for your tests project. Select the Add Reference… menu item from either the context menu or the Project dropdown menu. This opens the Add Reference dialog. Select the Solution item under Projects in the dialog. Now select both GTest and the project containing the code that you will be testing. For MyProject, the dialog will look like this:googletest2
    Click the OK button.
  10. Open the MyProjectTests.cpp file and replace any text in that file with the following code:
    #include "gtest/gtest.h"
    #include "../MyProject/arithmetic.h"
    
    TEST(SquareTests, Square)
    {
        EXPECT_EQ(0, square(0));
        EXPECT_EQ(-4, square(-2));
    }

    This code tests the square function that we created in arithmetic.h, above. If you performed step 4(b), above, you must repeat that step for your tests project.

  11. Rebuild the solution.
  12. Set MyProjectTests as the startup project. Start the program without debugging (using the Start Without Debugging menu item in the Debug dropdown menu, or by pressing Ctrl-F5). This will open a console window and run the tests. The output should look like this:googletest3
    Note that there is a failed test. The lines between [RUN ] SquareTests.Square and [ FAILED ] SquareTests.Square (3 ms) give both the location of the failed test and the expected and actual values. This indicates that either the code being tested is in error or the test itself is in error. In this case, it is the test that is in error. We will correct this later.

Installing  A Test Runner

As currently configured, Visual Studio and Google Test allow you to run tests, but you must look at every error and manually go to the test that errors. The MS Testing Framework is integrated into a test explorer. It would be nice if Google Test could also use the test explorer.

This is where test runners come in. There are two test runners for Google Test that are available as Visual Studio extensions:

  1. Google Test Runner for Visual Studio 2015; and,
  2. Google Test Adapter

To load either extension, click on the Tools->Extensions and Updates… menu item. This opens the Extensions and Updates dialog. Select Online and then search for google test.
I first tried Google Test Runner, but I got the following output:

------ Run test started ------
Found 1 tests, resolving symbols
Loading symbols from C:\Users\jimor_000\Source\Repos\test\x64\Debug\MyProjectTests.exe
From C:\Users\jimor_000\Source\Repos\test\x64\Debug\MyProjectTests.exe, found 1 symbols in 55 ms
In C:\Users\jimor_000\Source\Repos\test\x64\Debug, running: C:\Users\jimor_000\Source\Repos\test\x64\Debug\MyProjectTests.exe --gtest_output="xml:C:\Users\jimor_000\AppData\Local\Temp\tmp610C.tmp"
Opened results from C:\Users\jimor_000\AppData\Local\Temp\tmp610C.tmp
Could not load file or assembly 'FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
at FSharp.Data.Runtime.XmlRuntime.GetChildrenArray(XmlElement value, String nameWithNS)
at FSharp.Data.Runtime.XmlRuntime.ConvertArray[R](XmlElement xml, String nameWithNS, Func`2 f)
at GoogleTestRunner.ResultParser.getResults(IMessageLogger logger, String outputPath, FSharpList`1 testCases)
at GoogleTestRunner.GoogleTestExecutor.runOnce(IFrameworkHandle framework, IRunContext runContext, FSharpList`1 allCases, FSharpList`1 cases, String executable, Boolean runAll)
at GoogleTestRunner.GoogleTestExecutor.runTests(FSharpList`1 allCases, IEnumerable`1 cases, IRunContext runContext, IFrameworkHandle framework, Boolean runAll)
No test is available in C:\Users\jimor_000\Source\Repos\test\x64\Debug\MyProjectTests.exe. Make sure that installed test discoverers & executors, platform & framework version settings are appropriate and try again.
========== Run test finished: 0 run (0:00:01.7510369) ==========

Google Test Runner is written in F# and requires a version of FSharp.Core that is not installed with Visual Studio 15 Update 3. I posted an Issue and the response was that the developers have no time to maintain the extension, so users should switch to Google Test Adapter.

Installing Google Test Adapter

Google Test Adapter is a complete rewrite of Google Test Runner in C#. According to its developer, it is also now more feature complete. See the comment by Christian Soltenborn. It is actively being developed and maintained, so there should be no support problems like there are with Google Test Runner.

Here is how to install Google Test Adapter:

  1. Select the Tools->Extensions and Updates… menu item. This opens the Extensions and Updates dialog.
  2. Select Online, then search for google test.
  3. Download, then install Google Test Adapter.
  4. Restart Visual Studio.

Using Google Test Adapter

  1. If the Test Explorer window is not open, open it by selecting the Test->Windows->Test Explorer menu item.
  2. Immediately after Google Test Adapter was installed, no tests will be visible in the Test Explorer window. To populate the test explorer with tests, you must rebuild your solution. Do so now. Remember, you must name your test project to end in either Test or Tests for the tests to be discovered.
  3. For MyProject, the Test Explorer window now looks like this:
    testexplorer
    Note the single test called SquareTests.Square. If several tests are created, then all tests will be listed.
  4. To execute tests, select one of the Run items in the Test Explorer window, or one of the Test->Run-> menu items. Here is the result:
    testexplorer2
    Note the links to the source and to the stack trace. Selecting the stack trace item takes you to the test that failed.
  5. The square of -2 is 4, not -4, so the test is in error, not the square function. Correcting this bug, then building the solution again and rerunning the test gives:
    testexplorer3
    indicating that the test now passes.

That’s it. You can now continue to add more tests and more code to test.

You should also see the GoogleTestAdapter documentation on GitHub for information on additional capabilities.

This post was updated on August 1, 2017 to add the following section.

Running Tests Automatically As Part of Build Process

Visual Studio Enterprise Edition

The following only works if you are using Visual Studio Enterprise Edition:

  1. Do either of the following, as they are equivalent:
    (a) Select the Test->Test Settings->Run Tests After Build menu item.
    (b) In Test Explorer, click the Run Tests After Build button at the top of the window. This button is shown in the image below. It is the one with the yellow background indicating that it is selected.
    runtestsafterbuild
  2. Rebuild the solution. The tests should run.

Other Editions of Visual Studio

Even though the menu item and button mentioned for the Enterprise Edition may be active, they only work for the Enterprise Edition. To run tests in other editions of Visual Studio, do the following:

  1. Open the properties dialog for the project containing the tests.
  2. Select Build Events->Post-Build Event.
  3. Set the Configuration that you want the tests to run for.
  4. Set the Platform that you want to tests to run for.
  5. For the command line, enter the location and name of the test executable {“$TargetDir)MyProjectTests.exe” in this case}. Enter a description, such as “Run Unit Tests”. This text is for documentation purposes only; it does not appear anywhere. Make sure that Use In Build is set to “Yes”.
  6. The properties dialog should now look similar to this:
    runtestspostbuild
    Click the OK Button to close the dialog.
  7. Rebuild the solution. The Output window will contain:
    1>------ Build started: Project: MyProjectTests, Configuration: Debug Win32 ------
    1>MyProjectTests.vcxproj -> C:\Users\jimor_000\Source\Repos\MyProject\Debug\MyProjectTests.exe
    1>MyProjectTests.vcxproj -> C:\Users\jimor_000\Source\Repos\MyProject\Debug\MyProjectTests.pdb (Partial PDB)
    1>Running main() from gtest_main.cc
    1>[==========] Running 1 test from 1 test case.
    1>[----------] Global test environment set-up.
    1>[----------] 1 test from SquareTests
    1>[ RUN ] SquareTests.Square
    1>c:\users\jimor_000\source\repos\myproject\myprojecttests\myprojecttests.cpp(7): error : Expected: -4
    1>To be equal to: square(-2)
    1> Which is: 4
    1>[ FAILED ] SquareTests.Square (1 ms)
    1>[----------] 1 test from SquareTests (1 ms total)
    1>
    1>[----------] Global test environment tear-down
    1>[==========] 1 test from 1 test case ran. (1 ms total)
    1>[ PASSED ] 0 tests.
    1>[ FAILED ] 1 test, listed below:
    1>[ FAILED ] SquareTests.Square
    1>
    1> 1 FAILED TEST
    1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(133,5): error MSB3073: The command "C:\Users\jimor_000\Source\Repos\MyProject\Debug\MyProjectTests.exe
    1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(133,5): error MSB3073: :VCEnd" exited with code 1.
    1>Done building project "MyProjectTests.vcxproj" -- FAILED.
    ========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
  8. If any tests fail, run all tests in the Test Explorer window. When you do this, the following message box is displayed:
    builderrors
    This is displayed because running the tests was part of the build process for the test project. If the tests ran, then the test program was created. You can therefore safely click on the Yes button to run the tests.

Compile Time Checking of Class Template Types

But all I wanted to do was…

Oh, how many times have we all said that? This adventure started as I was coding ChaosExplorer. I had completed the coding for displaying Mandelbrot and Multibrot Sets and their associated Julia Sets. I have two classes derived from wxGLCanvas, called MultibrotPanel and MandelJuliaPanel. The first panel displays the Multibrot Sets and the second panel displays the corresponding Julia Sets. In the MultibrotPanel class, I have methods that are used to animate a number of properties. These methods are bound to timer events. I am not going to go into detail here; you can see the code on GitHub.

Here is the gist of it. I have a StartTimer method and a StopandReleaseTimer method that are defined as follows:

   void StartTimer(const int timerInterval, TimerHandler handler);
    void StopAndReleaseTimer(TimerHandler handler);

TimerHandler is defined using the following alias:

using TimerHandler = void(MultibrotPanel::*) (wxTimerEvent&);

Great! Everything works. Now I wanted to use other formulae to display other fractals and their Julia Sets. Much of the code in MultibrotPanel and MandelJuliaPanel would be duplicated, with the major differences being the use of different GLSL shader programs. The fractal panels similar to MultibrotPanel also reference different Julia Set panels because the Julia Set displays are created as the result of selecting menu items in the context menus in the fractal panels. So this suggested that the common functionality of the various panels should be placed in base classes and the code specific to each fractal formula should be in derived classes. Also, because the various panels reference different shader programs and Julia Set panels, templatizing the panel classes would be a good idea. The diagram, below, shows the class hierarchy.

panels.png

My first attempt resulted in the following declarations:

template <typename T, typename U>
class MultibrotPanel<T, U> : public PlottingCPanel<T, U>
{...};
template <typename T, typename U>
class PlottingCPanel<T, U> : public ChaosPanel<T>
{...};
template <typename T>
class ChaosPanel<T> : public wxGLCanvas
{...};

where T is the shader program class that is used to draw the fractal, and U is the panel class that displays the corresponding Julia Sets.

Compiling this produces an error on the TimerHandler alias definition that is shown above. I could not figure out how to proceed, so I jumped over to Stack Overflow to post the problem. Arunmu posted a possible solution that involved checking that the TimerHandler pointed to a class that contained an appropriate callback for the timer. A bit of an ugly solution, but the problem at least is caught at compile time.

While studying the solution, I realized that there is only one shader program and one Julia Set panel that the MultibrotPanel class references. Therefore, MultibrotPanel does not need to be a templated class at all; only PlottingCPanel (and ChaosPanel) need to be templated classes. So, the MultibrotPanel class declaration becomes:

class MultibrotPanel : public PlottingCPanel<GLMultibrotShaderProgram, MandelJuliaPanel> {...};

and the TimerHandler alias can stay in its original form. So, my initial problem is solved! But that got me thinking. I know, that is a dangerous thing. The first templated class in PlottingCPanel must be a shader program, and the second templated class must be a Julia Set panel. But as declared, there is nothing to prevent the programmer from using any class in either position. It would therefore be nice to ensure, at compile time, that the declared classes are the correct type. And this brings us back to the answer to my post on Stack Overflow and a number of other posts as well. The posts use a combination of constexpr and static_assert to ensure at compile time that the classes are of the right type.

The first class in the PlottingCPanel declaration is a shader program class. All shader program classes derive from the GLShaderProgram class. This class is not templated, so checking is quite easy:

#include <type_traits>
...
        static_assert(std::is_base_of<GLShaderProgram, T>::value, "T must be derived from GLShaderProgram");

The static_assert is the first statement in the ChaosPanel constructor. The second class in the PlottingCPanel class declaration must be a PlottingZ0Panel which is templated, so the simple solution used for checking the shader program class will not work.

How do we check that a templated class is the correct type? This brings us back to Arunmu’s answer to my Stack Overflow post and to other posts on Stack Overflow and a few other sites as well. I have created a simple program that tests these solutions. Here is the framework for the program. C is a templated class; the class specified by the template must be derived from A. All other classes should generate a compile error.

template<typename T>
class A
{
public:
// note that func only needs to be declared and not defined for test2 and test3 // static_asserts to work
void func();
};

class B : public A<int>
{};

class D {};

template<typename T>
class C
{
public:
C()
{
}
};

int main(int argsCount, char** args)
{
C<B> c;    // OK. Should compile
C<D> d;    // Should not compile because D is not derived from A
}

What do we need to add to generate the compile error for C<D> d;? In the Stack Overflow post How to Determine if a Type is Derived from a Template Class, Johannes Schaub – litb recommended a solution like the following:

template< typename T, typename U >
std::true_type is_based_impl(A const volatile&);
std::false_type is_based_impl(...);

template< typename T >
bool is_based_in_A(T&& t) {
    return decltype(is_based_impl(t))::value;
}

This solution uses templated variables which are not supported in Visual Studio 2015.

Solutions That Work

All of the solutions below use SFINAE (Substitution Failure Is Not An Error). The following statements comes from the SFINAE web page at cppreference.com. See that page for more information.

This rule applies during overload resolution of function templates: When substituting the deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.

is_base_of_template

I have placed each potential solution inside a different namespace so that the solutions are easily separated. From the post is_base_of of generic type, the following solution is proposed:

namespace test1 {
    // From http://coliru.stacked-crooked.com/a/eaeac2b9008a97d9 in answer to 'is_base_of of generic type'
    // at http://stackoverflow.com/questions/32477691/is-base-of-of-generic-type/32489730#32489730
    template <template <typename...> class Base, typename Derived>
    struct is_base_of_template
    {
        using U = typename std::remove_cv<Derived>::type;

        template <typename... Args>
        static std::true_type test(Base<Args...>*);

        static std::false_type test(void*);

        using type = decltype(test(std::declval<U*>()));
    };

    template <template <typename...> class Base, typename Derived>
    using is_base_of_template_t = typename is_base_of_template<Base, Derived>::type;
}

To use this, simply add

static_assert(test1::is_base_of_template_t<A, T>::value, "No!");

to the C class constructor. Compiling the program using Visual Studio 2015 generates the following output:

main.cpp
1>...\main.cpp(88): error C2338: No!
1>  ...\main.cpp(86): note: while compiling class template member function 'C<D>::C(void)'
1>  ...\main.cpp(97): note: see reference to function template instantiation 'C<D>::C(void)' being compiled
1>  ...\main.cpp(97): note: see reference to class template instantiation 'C<D>' being compiled

Test For Method – 1

For this solution, the templated base class must have a method that is unique to that class declared; it is not necessary to provide a definition for the method if the only purpose for this unique method is to test that the class is being used. Here is the code:

namespace test2 {
    // Based on Arunmu's answer to a somewhat related question that I asked on Stack Overflow:
    // http://stackoverflow.com/questions/37509611/templating-classes-and-aliases-causes-compile-errors/37510350#37510350
    template <typename T>
    constexpr auto has_func(const T& obj) -> decltype(std::declval<T&>().func(), bool())
    {
        return true;
    }

    constexpr auto has_func(...)
    {
        return false;
    }
}

To use this code, add

static_assert(test2::has_func(T()), "Another No!");

to the C class constructor. When compiled with Visual Studio, the following error messages are generated:

1>...\main.cpp(89): error C2338: Another No!
1>  ...\main.cpp(86): note: while compiling class template member function 'C<D>::C(void)'
1>  ...\main.cpp(97): note: see reference to function template instantiation 'C<D>::C(void)' being compiled
1>  ...\main.cpp(97): note: see reference to class template instantiation 'C<D>' being compiled

Test For Method – 2

Here is a second technique for testing for a unique method in the base class. In it, sizeof is used to distinguish between a class that has the method, and a class that does not.

namespace test3 {
    // based on one of guestgulkan's answers to 'writing and using a C++ template to check for a function's existence'
    // at http://www.cplusplus.com/beginner/70134/
    template <typename T>
    class Has_Func
    {
        typedef char one;
        typedef long two;

        template <typename C>
        static const one test(decltype(&C::has_func));
        template <typename C>
        static const two test(...)
        {
            return 962;         // could be any long int value
        }

    public:
        template <typename U>
        static constexpr bool has_func()
        {
            return (sizeof(test(U)) == sizeof(char));
        }

        static constexpr bool has_func()
        {
            return false;
        }
    };
}

Adding the following line to the C class constructor

static_assert(test3::Has_Func::has_func(), "Does not have func()");

and compiling produces the following compile error messages:

1>...\main.cpp(90): error C2338: Does not have func()
1>  ...\main.cpp(86): note: while compiling class template member function 'C<D>::C(void)'
1>  ...\main.cpp(97): note: see reference to function template instantiation 'C<D>::C(void)' being compiled
1>  ...\main.cpp(97): note: see reference to class template instantiation 'C<D>' being compiled

Using All Three Techniques

The test program uses all three techniques. Having all three static_assert calls in the constructor yields the following compiler output:

main.cpp
1>...\main.cpp(88): error C2338: No!
1>  ...\main.cpp(86): note: while compiling class template member function 'C<D>::C(void)'
1>  ...\main.cpp(97): note: see reference to function template instantiation 'C<D>::C(void)' being compiled
1>  ...\main.cpp(97): note: see reference to class template instantiation 'C<D>' being compiled
1>...\main.cpp(89): error C2338: Another No!
1>...\main.cpp(90): error C2338: Does not have func()

Note that lines 3-5 are included only once.

Limitations

  1. These techniques work only for public base classes.
  2. The second and third techniques work only for public methods.

Analysis

  1. The is_base_of type trait only works with non-templated base classes.
  2. The second and third techniques require that a method with a name that is unique to the base class be declared in the base class.
  3. It is not necessary to provide a definition for this method if its only purpose is to check for use of the base class.
  4. The first technique is the cleanest because it does not require any additions to the base class.

Conclusions

  1. It is possible to check at compile time if a template class is derived from a templated base class.
  2. This check should be performed at compile time because using a non-templated base class as a template class when a templated base class should be used is a design/code error, and therefore should be caught by the developer and not shown to the end user.
  3. The first technique is the cleanest and therefore the preferred technique for determining if a template class is derived from a templated base class.

The source code for the program is available on GitHub.

Improving Visual Studio Solution Build Times – Multiple Processors

Visual Studio is a powerful Integrated Development Environment for developing software for the Windows OS environment, and with its latest release (2015, Update 1), a number of tablet and phone OSes as well. As with all IDEs , the times required to build a solution using Visual Studio increases with the number of source files and projects in a solution. There are a number of different techniques that can be used to improve this build time. This post will discuss one of these techniques: using multiple processes and processors for the build.

MSBuild.exe is the builder used by Visual Studio to build solutions. MSBuild has a command line switch that tells MSBuild to use multiple processors if available to build the loaded solution. There is also a commercial product, Incredibuild, that integrates with Visual Studio to provide a different way of building the solution and can offload work to additional computers on the network.

Visual Studio and Multiple Processors

Visual Studio provides a property for each C++ project that controls whether MSBuild uses multiple processes to build the various projects in a solution. This setting is found on the Properties dialog for each project. The image below shows the Properties Pages for a C++ project. The setting is found under the C/C++ -> General item, and is called Multi-processor Compilation (the last item in the panel on the right of the dialog). There are three choices:

  • No
  • Yes (/MP)
  • <inherit from parent or project defaults>

multiprocessorsetting

No obviously means use a single process to perform the compiles, Yes means use as many processes as possible, and the third says to inherit the setting. You may use the technique discussed in User Wide Settings in Visual Studio 2015 to set a default setting for all new projects and for any projects that inherit the setting.

Let’s now look at the Yes setting. Using this switch, a number of processes are created to perform the build. The number of processes created, by default, is equal to the number of virtual processors on the computer performing the build (number of CPUs times the number of cores per CPU [times 2 if the cores support hyperthreading]). You can determine this number by starting Task Manager and selecting the Performance tab and the CPU item. The lower right of the displayed panel contains information about the CPUs, with the Logical processors line containing the number of logical (virtual) processors as shown in this image:

cpus

As you can see, on my computer, I have a total of 8 logical processors, so by default, Visual Studio would use up to 8 processes to build a solution.

It is possible to limit the number of processes. More information about this option is available in /MP (Build With Multiple Processes).

Visual Studio and Incredibuild

Incredibuild is a commercial product that accelerates builds by taking advantage of the multiple logical processors in the host computer, and if available, the processors in other computers on your network. At the start of each build, Incredibuild performs an analysis to determine the best way to build the Visual Studio solution, and divides the compiles and links among the available processors.

See Incredibuild 7.0 Review and How Incredible is Incredibuild for reviews of this product.

One advantage of Incredibuild over a number of other build accelerators is that Incredibuild integrates right into Visual Studio. As noted in the last review, above, one disadvantage is that linking files compiled with Incredibuild with those compiles with the normal build process may create executable files that crash. More information is provided in that review.

Build Accelerator Measurements

It’s nice to talk about multi-processor builds and Incredibuild, but how do they really compare? Some people claim great improvements in build time for very large solutions, and others say build times are worse with Incredibuild. I will perform a set of experiments to measure the build times for two open source software solutions that are the size that a typical user would encounter in his personal programming activities. Note: You should not extrapolate these results to much larger projects; you should repeat these measurements on your own software and hardware.

For each of the open source solutions, six separate measurements will be taken:

  1. Solution rebuild without using multi-processes;
  2. Solution rebuild using multi-processes;
  3. Solution rebuild using Incredibuild;
  4. Incremental build without using multi-processes;
  5. Incremental build using multi-processes; and,
  6. Incremental build using Incredibuild.

Test Setup

Hardware

All measurements are made on a single laptop that contains the following components. This is typical for a higher end laptop built within the last two years. Specifically, the laptop contains:

  • Intel Core i7-4710MQ CPU with 8 logical processors. More information about the CPU is displayed in the first image above this text.
  • 8 GB DDR3 RAM running at 1600 MHz.
  • 1 TB hard drive spinning at 5400 RPM.

Software

  • Visual Studio 2015 Community Edition (Update 1)
  • Incredibuild 7.1
  • Other software is running on the laptop during these tests, such as a web browser, an email client program, and a number of tasks that run in the background. This mix would be typical for a developer.

Source Code for the Measurements

The two open source software solutions used for these measurements are:

  • wxWidgets 3.1.0. wxWidgets contains 24 projects that generate 23 x64 Debug lib files.
  • libtins. libtins contains 4 projects that generate one lib file. The solution is built using the x86 Debug configuration.

Rebuild Test Procedure

  1. Visual Studio is started and the solution is loaded.
  2. The solution is built and the build time is measured. For the Incredibuild builds, the time is taken from the Incredibuild monitor panel; for other builds, the time is measured using a clock. In both cases, the times should be accurate to within one second.
  3. Visual Studio is terminated.
  4. Steps 1, 2, and 3 are repeated five times for each build type and for each solution.

The procedure above was chosen for two reasons:

  1. The first time that a rebuild is performed after it is loaded takes longer than subsequent builds. While I could have performed one or two solution builds before measuring build times, I chose to use the procedure outlined above. In either case, measured values relative to one another would be the same, only the actual measured values change.
  2. Additional software is running on the computer used for these tests. While no direct user interaction was performed with other programs during these tests, the other software may run a variable amount. For example, an email may be received by the email client program. The tests are performed a number of times to average out these variations.

Incremental Build Test Procedure

  1. Visual Studio is started and the solution is loaded.
  2. The solution is rebuilt to ensure that all object, lib, and executable files are compatible. See the discussion of advantages and disadvantages of Incredibuild in the section above titled “Visual Studio and Incredibuild”.
  3. A single blank line is added or removed at the end of one of the source files. Addition and removal are alternated between runs. The source file chosen resulted in the compilation of that file and the linking of a single lib file.
  4. A build is performed and the time taken is measured. For the Incredibuild builds, the time is taken from the Incredibuild monitor panel; for other builds, the time is measured using a clock.
  5. Steps 3 and 4 are repeated for a total of five measurements.
  6. Steps 2 through 5 are repeated for each of the build types (single process, multi-processes, and Incredibuild.

Measurements

Rebuilds

wxWidgetsRebuildTimes

libtinsRebuildTimes.png

The graphs above shows the rebuild times in seconds as indicated for the build types.

 

Incremental Builds

incrementalbuild

This graph shows the Incredibuild incremental build times for wxWidgets. The build times using a single process were less than 1 second, and the build times using multiple processes was just over 1 second. The tests were not repeated for libtins; however, you can assume that the results would be similar since only a single source file was modified.

Discussion of Results

Rebuilds

The procedure for the rebuilds measurements was chosen because it would typically mimic the procedure used for the integration of daily or more frequent changes in an agile development process.

It is interesting to note that the variation in rebuild times for the Incredibuild builds was the greatest. Also, the Incredibuild times were greater than the build times for the multi-process builds. The Incredibuild method starts with a “Preparing Build Tasks” task that takes several seconds to complete; the similar task in MSBuild for the multi-process builds takes much less time, but no doubt results in a different distribution of build tasks over the logical processors.

The build times for single process builds are longer than the build times for multi-process builds as would be expected. The relative difference in build times for libtins are what I would have expected; the surprising results are for the wxWidgets rebuilds. There are many times more files being compiled and libraries being built so I would have expected the difference between the single process and multi-process build times for wxWidgets to be relatively even greater, yet the differences are relatively minor. Also, the single-process build times for wxWidgets beat the Incredibuild build times for the same solution.

One of the possibly major advantages for Incredibuild is the splitting of build tasks across multiple computers on a network. It was not possible to test this, so no conclusion can be drawn about the build times using that scenario.

From the reviews and from testimonials on the Incredibuild web site, Incredibuild seems to shine for very large projects; that is, for projects that take many minutes to build. A very large solution was not selected for these tests because that does not fit the types of solution that I work on. As mentioned above, you may want to repeat these tests for your own solutions.

Incremental Builds

The incremental build times for single process and multi-processes were difficult to measure using a clock. However, the single process bulid times were definitely less than one second, and the multi-process build times were more than one second, but considerably less than two seconds.

Is this what one would expect? Shouldn’t the multi-process build time be less than the single process build time? In this case, no. Remember that a single source file is being compiled, and a single lib file is being linked. The linking cannot be performed until the source file has been compiled, so no parallel processing can be performed. The extra time required for the potential multi-process build is the time that MSBuild takes to determine that no parallel processing can be performed.

The extra time required for the Incredibuild builds was divided between determining the build tasks and the time taken to compile the source file. The time required to determine the build tasks is understandable; however, the much longer compile time was unexpected.

What Was Not Tested

The computer that the tests were run on has a single CPU with 4 cores and hyper-V support for a total of 8 logical processors. All 8 logical processes shared the same cache, so this may slow down the build processes. A second physically separate CPU would be expected to improve build times more than multiple cores on a single CPU, but this could not be tested.

Similarly, one of the potential advantages of Incredibuild is its ability to use the idle cycles of the CPUs on other computers on the same network to perform some of the build tasks. This also could not be tested.

 

Conclusions

  1. For those situations where multiple tasks (compiles, links) can be performed at the same time, setting the multi-processor switch in Visual Studio will reduce build times over the times of single-process builds.
  2. For situations where multiple tasks cannot be performed concurrently, there is a penalty for using the multi-processor switch. However, the number of times that multiple tasks cannot be performed concurrently relative to the number of times that multiple tasks can be performed concurrently dictates that setting the multi-processor switch is the recommended procedure.
  3. Incredibuild increases the build times for the standard “make a small change, build, and test” process that most developers use, and therefore Incredibuild should not be used for these development steps.
  4. For these open source projects and these specific test conditions, Incredibuild provided no improvement over the times for multi-process rebuilds.That does not indicate that Incredibuild does not improve the rebuild times for many other, and especially larger projects. There may be great advantages to using Incredibuild for integration builds, but you will have to perform your own tests.
  5. The open source projects used in these tests are typical of the type of software that I develop. Because Incredibuild provided no improvement in the build times for either of these projects, I will not be using Incredibuild in my build procedures.

 

 

User-Wide Settings in Visual Studio 2015

Back in my post on Creating wxWidgets programs with Visual Studio – Part 1, I included instructions for setting a system environment variable for the wxWidgets directory, and instructions for adding Include and Library directories for projects in Visual Studio. These latter instructions must be repeated for every project that uses wxWidgets. Thanks to a suggestion from legalize (see his comment on the post linked above), I will provide instructions to define a user macro from within Visual Studio 2015 that provides this variable on a per-user basis. I will also provide instructions for setting up the Include and Library directories across all projects and solutions on a per-user basis.

We will be creating user-wide settings for Visual Studio. Illogically, Microsoft has hidden the interface for these settings in the property manager for a single project. To begin, start Visual Studio 2015 and load a solution, or create a new one. Now select the View->Property Manager menu item. This opens the Property Manger tab as shown in this image for the HelloWorld sample program.

propertymanager

When you first display the Property Manager tab,  only HelloWorld will be visible. Click on the expander for HelloWorld to show the list of configurations, then expand one of the configurations that you will be building. In the image above, I have opened the Debug | x64 configuration. Note that if your solution contains more than one project, then each project will be listed. It is only necessary to open one of the project expanders. Note that the first item under Debug | x64 is Microsoft.Cpp.x64.user. For the Win32-related configurations, the first item is Microsoft.Cpp.Win32.user. Double-click on this item to open the Microsoft.Cpp.x64.user Property Pages or the Microsoft.Cpp.Win32.user Property Pages:

propertypages

Click on the User Macros item to display the image above. Now click on the Add Macro button to open the Add User Macro dialog. Fill in the name of the macro (WXWIN for wxWidgets), the macro value (C:\wxWidgets on my computer), and check the checkbox. The dialog will look like this:

addusermacro

Click the OK button to close the dialog. The property pages dialog now looks like this:

macroaddedpropertiespage.png

As you can see, the macro has been added. Add any other macros that you need.

Click on VC++ Directories, and click on Include Directories. See the image below.

includedirectories.png

Click on the down arrow box at the end of the Include Directories line and select <Edit…> to open the Include Directories dialog.

Double-click in the empty scroll box at the top of the dialog and enter $(WXWIN)\include. Double-click below this line and enter $(WXWIN)\include\msvc. Press Enter, and the dialog box will look like this:

IncludeDirectoriesDialog2

Click the OK button to close the Include Directories Dialog, and then the Apply button. Now select Library Directories and open the Library Directories dialog. Enter the path to the wxWidgets library files (e.g.$(WXWIN)/lib/vc_x64_dll if you created the wxWidgets x64 DLL configuration). Click the OK button to close the Library Directories dialog, and then the Apply and OK buttons on the Properties Pages dialog.

If you now expand the Release | x64 configuration and open the Microsoft.Cpp.x64.user Property Pages dialog, you will see that the user macro and the VC++ Directories are listed here as well. If you also build Win32 configurations, you will have to repeat all of this procedure for Microsoft.Cpp.Win32.user. The properties that you set are saved in the %LOCALAPPDATA%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.x64.user.props file for x64 configurations, and %LOCALAPPDATA%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props for Win32 configurations.

The next time you open a different solution or create a new solution, these properties will be included.

Visual Studio, wxWidgets, and OpenGL

The immediately previous post discussed OpenGL and many potential libraries and windowing toolkits that work with OpenGL. In this post, I will look at what I use for OpenGL programming on Windows 10 desktop:

  • Visual Studio 2015 Community Edition;
  • wxWidgets; and,
  • GLEW, the OpenGL Extension Wrangler.

The selection of a development environment is very much a personal choice. After using a number of batch build methods and Integrated Development Environments over the last few years, I have settled on Visual Studio as the best choice for me. It contains a C++ compiler that is C++14 compatible and even has the C++17 features that have been approved by the C++ Standards Committee. Visual Studio 2015 also integrates git for source control, and unit testing via Microsoft Unit Test Framework. There is a memory leak detector included in Debug mode. Note that the leak detector only works on the memory allocated on the CPU and does not detect memory leaks in the GPU.

I will be developing some complex applications, so one of the Standard Windowing Toolkit mentioned in my post on OpenGL Graphics, or something similar is required. Since I develop on Windows 10 for the desktop, then any of the standard toolkits will work. Win32 is a C interface that requires a lot of coding to perform any windowing tasks. MFC is a thin shell over Win32. While it is C++, it predates C++99 and retains many of the C structures used in Win32. The other full C++ windowing toolkits, wxWidgets, Qt, and GTKMM, are all multi-platform, and more advanced and C++ friendly than MFC; any one of them would work.

I chose wxWidgets because it is the only one of the multi-platform toolkits that displays using the native look and feel on Windows. Being multi-platform, it has the advantage over the Windows only toolkits in that any code I develop can be easily ported to other operating systems and windowing systems.  It can even be used atop GTK+ on Windows desktops, although that seems to be counter-productive.

Using wxWidgets with Visual Studio is covered in three posts on this blog:

gl.h declares OpenGL 1.1 functions, many of which have been deprecated. It has been supplemented with glu.h and glaux.h, which have also been deprecated. In order to access the full functionality of the OpenGL API as supported by your graphics card, a loading library is required. I use GLEW because it is easily installed for use with Visual Studio, and a number of the tutorials online use it. The OpenGL functions are directly callable, unlike some of the other loading libraries that require you to call a function to retrieve a pointer to the requested function before calling the function. Source code and 32- and 64-bit binaries for GLEW are available for Windows on Sourceforge. Alternatively, GLEW is included along with FreeGLUT and FLFW in a NuGet package called nupengl.core.

Before loading nupengl.core, you must first create a simple wxWidgets project. The process for this is described in Creating wxWidgets Programs with Visual Studio 2015 – Part 1. Select the platform you are building your application for (x86 or x64), and build the project. Once you have done this, you can install nupengl.core. To do this, select the solution in the Solution Explorer, then select the Tools->NuGet Package Manager->Manage NuGet Packages for Solution... menu item. This opens the Nuget – Solution tab shown below:

nupengl

Select the nupengl.core package, then select the projects that you want to include the package in (Hello Triangle in this case). Now click the Install button to install the nupengl.core. nuplegl.core.redist is installed at the same time as nupengl.core, so there is no need to install it explicitly.

You are now ready to create your first OpenGL application. That is the topic of the next post.