With great power comes great configuration

by g. ann campbell|

    We've got an ambitious vision for the C/C++ plugin this year. To fulfill it, we started with some under-the-cover improvements to the parser and the internal data model. Those improvements were really just a means to an end, but they've had the effect of markedly improving our ability to parse and analyze C and C++ code.

    Unfortunately, they came with a downside: a higher analysis configuration burden. For instance, in order to correctly expand macros in the code (and we can, now), we need to know what the macro means. Which means that the macro definition needs to be passed in to the analysis.

    Just contemplating the configuration update required for a single large system made me queasy, and I wasn't the only one. So we set the main plugin aside for a little while this spring and wrote a build wrapper, which will eavesdrop on the tool of your choice (e.g. Make or MSBuild) to gather all the extra configuration data for you.



    The build wrapper supports the Clang, GCC and MSVC compilers, and is available in 32-bit and 64-bit versions for Windows and Linux and a 64-bit version is available for OS X. Using it couldn't be simpler. You drop it somewhere on your machine (make sure it's executable on 'nix systems), and prepend your build command with it:


    build-wrapper --out-dir [output directory] make


    Of course, it needs to be a full build that the wrapper is eavesdropping on, so ideally this command would have come after a make clean. And for MsBuild it would be something like:


    build-wrapper --out-dir [output directory] msbuild /t:rebuild [other options]


    The output directory is where the build wrapper writes its data files, creating the directory if it doesn't exist. Currently, the build wrapper simply adds its files to the specified directory, but that behavior could change in the future (E.G. someday it might start by issuing rm [output directory]/*).

    The build wrapper writes two files: build-wrapper.log and build-wrapper-dump.json. The .log file is just that - a log that Support may ask for if you ever contact them with questions. The .json file is the one that's actually used during analysis. This screenshot of the build-wrapper-dump.json from my Linux build of CMake should give you an idea what these files look like:



    I'm only posting a brief screenshot because the full file is 43,614 lines long (plus a blank line at the end). I'm not saying that all the information in the file is absolutely required for analysis, but it would have taken me a very long time to identify and specify the pieces that are.

    Once the build is complete, and your .json file is written, it's time to kick off a SonarQube analysis. But first you'll need to tell SonarQube where to find all that extra configuration data the build wrapper just logged. In your sonar-project.properties add the following:

    sonar.cfamily.build-wrapper-output=[output directory]


    I end up with a properties file that's only six lines long (including whitespace), and SonarQube has everything it needs to analyze my project:

    sonar.projectKey=cmake-linux-clang
    sonar.projectName=CMake Linux CLang build
    sonar.projectVersion=1.0

    sonar.sources=Source
    sonar.cfamily.build-wrapper-output=build


    If you haven't used the build-wrapper on your C/C++ projects yet, you should give it a try and let us know how it goes. Hopefully, it will help you drastically improve the quality of your analyses while dramatically decreasing the configuration.

    But you won't have to tell people it was easy.