cppDepend

CppDepend – A Review

In my concurrency class, I use more than 60 programs. Most of the programs consist of a single source file. I’m quite curious if the static code analysis tool CppDepend can find any issues in my sources. Let me try it out.

 cppDepend

My Special Use-Case

My use case is unique for two reasons. First, I don’t expect too many issues with my examples for one reason: I give quite often concurrency classes and use these examples in my classes; therefore, I had many code reviewer. Second, my programs are most of the times not really sophisticated and quite short. They should only serve one purpose: show the particular concurrency features in isolation.

My Strategy

Due to my unique circumstances, here are my steps to get the static code analysis with CppDepend.

  1. Generate a CMake file for Visual Studio, GCC, and Clang
  2. Generate a Visual Studio Project from CMake
  3. Import the Visual Studio Project project into CppDepend
  4. Make the code analysis in CppDepend

Here we go.

1. Generate a CMake file for Visual Studio, GCC, and Clang

My customers work with Visual Studio, GCC, or Clang. To provide a way to compile all C++ sources to executables automatically, I use CMake. In sum, I have more than 300 C++ sources files in various directories. Each source file should become an executable. Writing a CMakeList.txt manually for each directory would be a boring step. Additionally, I would have to adapt it each time, if I modified the file names. Terrible!. To automate the boring stuff, I wrote a small python script generateCMakeFile.py. generateCMakeFile.py generates a CMakeList.txt file for the directory, in which I invoke it.

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

Be part of my mentoring programs:

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (starts March 2024)
  • Do you want to stay informed: Subscribe.

     

    Here it is.

    # generateCMakeFile.py
    
    import fnmatch
    import os
    
    # A few constants
    SUFFIX = "*.cpp"
    OUTPUT = "CMakeLists.txt"
    
    # The output file
    outputFile = open(OUTPUT, "w")
    
    # Return the full path to all files respecting the pattern
    def getFiles(dir_, patterns="*", recursive=True):
        patterns = patterns.split()
        retValue = []
        for path, dirs, files in os.walk(dir_):
            for file_ in files:
                for pattern in patterns:
                    if fnmatch.fnmatch(file_, pattern):
                        retValue.append(os.path.join(path, file_))
                        break
            if not recursive: break
        return retValue
    
    
    # Get all files of the current working directory ending with *.cpp
    def getAllFilenames():
        allFiles = getFiles(os.getcwd(), SUFFIX , False) 
        return [ os.path.basename(file_)[:-len(SUFFIX)+1] for file_ in allFiles ]
    
    # Create the CMakeLists.txt header for GCC, Clang, and MSVC
    def getHeader():
        return """# Require a recent version of cmake
    cmake_minimum_required(VERSION 2.8.4 FATAL_ERROR)
    
    # This project is C++ based.
    project(seminar)
    
    if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
        set(CMAKE_CXX_FLAGS "-O3 -std=c++14 -pthread")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
    	    message(WARNING "!!!! GCC versions must be at least 5.0 !!!!")
            message(WARNING "!!!! Adust the makefile to build with a different compiler. !!!!")
        endif()
    elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
        set(CMAKE_CXX_FLAGS "-O3 -std=c++14 -pthread")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
            message(WARNING "!!!! Clang version must be at least 3.5 !!!!")
    		message(WARNING "!!!! Adust the makefile to build with a different compiler. !!!!")
        endif()
    elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
        set(CMAKE_CXX_FLAGS "/Ox /EHsc")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)    
            message(WARNING "!!!! MSVC version must be at least 19.10 !!!!")
        endif()	
    else()
        message(WARNING "!!! You are using an unsupported compiler! Compilation has only been tested with GCC >= 5.0, Clang >= 3.5, or MSVC >= 19.10. !!!")
    endif()
        
    
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/")
    
    set(CMAKE_VERBOSE_MAKEFILE on)
    
    """
        
    # Create the list of all source files    
    def getAllNames(allNames):    
        outNames = "set(example_programs" 
        for entry in allNames:
            outNames += "    " + entry + "\n"
        outNames += "   )"
        outNames += "\n"
        
        return outNames
    
    # Create an executable from the source file
    def getTail():
        tail = """foreach(example_program ${example_programs})
      set(sources ${example_program}.cpp)
      source_group("Source Files" FILES{sources})
      add_executable(${example_program} ${sources})
    endforeach()"""
        return tail
    
    
    # Create the CMakeLists.txt
    allNames = getAllFilenames()
    
    print >> outputFile, getHeader()
    
    print >> outputFile, getAllNames(allNames)
    
    print >> outputFile, getTail()
    

     

    To understand the program, you should start with the three print statements add the end. The brown font goes directly into CMakeList.txt.

    Using the generateCMakeFile.py is straightforward. I copied the  generateCMakeFile.py to the directory, I wanted to use it. This step is not necessary but make the commandline easier to write.

    GenerateCmakeFile

    Finally, this is the autogenerate CMakeList.txt.

    # Require a recent version of cmake
    cmake_minimum_required(VERSION 2.8.4 FATAL_ERROR)
    
    # This project is C++ based.
    project(seminar)
    
    if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
        set(CMAKE_CXX_FLAGS "-O3 -std=c++14 -pthread")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
    	    message(WARNING "!!!! GCC versions must be at least 5.0 !!!!")
            message(WARNING "!!!! Adust the makefile to build with a different compiler. !!!!")
        endif()
    elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
        set(CMAKE_CXX_FLAGS "-O3 -std=c++14 -pthread")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
            message(WARNING "!!!! Clang version must be at least 3.5 !!!!")
    		message(WARNING "!!!! Adust the makefile to build with a different compiler. !!!!")
        endif()
    elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
        set(CMAKE_CXX_FLAGS "/Ox /EHsc")
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)    
            message(WARNING "!!!! MSVC version must be at least 19.10 !!!!")
        endif()	
    else()
        message(WARNING "!!! You are using an unsupported compiler! Compilation has only been tested with GCC >= 5.0, Clang >= 3.5, or MSVC >= 19.10. !!!")
    endif()
        
    
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/")
    
    set(CMAKE_VERBOSE_MAKEFILE on)
    
    
    set(example_programs    acquireConsume
        acquireRelease
        asyncLazyEager
        atomicCondition
        atomic
        blockingAsync
        conditionVariable
        dataRaceOnX
        dotProduct
        fetch_mult
        lockGuard
        mutex
        newAlgorithm
        packagedTask
        packagedTaskReuse
        promiseFuture
        promiseFutureSynchronize
        readerWriterLock
        relaxed
        safeInitializationCallOnce
        safeInitializationStatic
        singleton
        spinlockAcquireRelease
        spinLock
        threadArguments
        threadCreate
        threadLifetime
        threadLocal
        threadMethods
        time
        timeDuration
        transitivity
        uniqueLock
       )
    
    foreach(example_program ${example_programs})
      set(sources ${example_program}.cpp)
      source_group("Source Files" FILES{sources})
      add_executable(${example_program} ${sources})
    endforeach()
    

     

    2. Generate a Visual Studio Project from CMake

    To make my CppDepend life more comfortable, I switch from Linux to Windows and continue with Visual Studio.

    MakeVisualProject

    This step creates a 64-bit Visual Studio Project in the directory “C:\Users\raine\build“. 

    3. Import the Visual Studio Project project into CppDepend

    Now, it’s time to start CppDepend and create a new project Concurrency:

    NewProjectNext, I add Visual Studio to my new project.

    solution

    One step is still missing. I have to press the analyse button. It took my eight cores a few second to analyse the source files.

    4. Make the code analysis in CppDepend

    As I already assumed it, the most checks are green:

    analysis

    Of course, I’m only interested in the red (Error) and yellow (Warning) ones.

    Error:

    • Quality Gates:
      • This issue boils down to mainly one function: The method is too big, has too many local variables, and is poorly documented. What I liked about CppDepend was that it shows me the metric I violated. 
       

    QualityGates

    Warnings:

    • Code Smells:
      • The previous break of the Quality Gates was also a Code Smell; therefore, I can ignore this warning.
    • Object Oriented Design:
      • Only one of the thirty rules was violated: three of my constructors taking one argument were not explicit. Honestly, this is a rule I often preach in my seminars. Shame on me. 
       

    ExplicitConstructor

     

    •  Misc:
      • This is also an issue I should fix. I passed a std::string by copy.
       

    passByReference

    • Dead Code:
      • This violation was funny. The violation was that the destructor of the singleton was never called. To my excuse, I only used a singleton to explain the thread-safe initialisation of a variable.
    • Naming Conventions:
      • I’m not a big fan of Hungarian notation. Therefore, I wouldn’t prefix an instance variable with a m_ or a static with a s_.

    My Resume

    Here is my short resume. I put not too much effort into the analysis of CppDepend but more in establishing an automated process to create the Visual Studio solution as input for CppDepend. Regardless, I found immediately a few big issues which I’m going to fix. It’s quite comfortable to fix these issues because a double-click on the Error/Warning in CppDepend opens the source file in Visual Studio.

    Although I only scratched at the surface of CppDepend, the analysis of my concurrency source files impressed me. I will, therefore, invest in the future more time to better understand the various metrics of CppDepend and apply them to my other source files. My gut feeling is that I can draw many benefits from CppDepend.

     

     

     

     

    Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, moon, Philipp Lenk, Hobsbawm, and Charles-Jianye Chen.

    Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.

    My special thanks to Embarcadero
    My special thanks to PVS-Studio
    My special thanks to Tipi.build 
    My special thanks to Take Up Code
    My special thanks to SHAVEDYAKS

    Seminars

    I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

    Standard Seminars (English/German)

    Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

    • C++ – The Core Language
    • C++ – The Standard Library
    • C++ – Compact
    • C++11 and C++14
    • Concurrency with Modern C++
    • Design Pattern and Architectural Pattern with C++
    • Embedded Programming with Modern C++
    • Generic Programming (Templates) with C++
    • Clean Code with Modern C++
    • C++20

    Online Seminars (German)

    Contact Me

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *