Analyzing a header-only C++ library

Hi there. First things first:

  • ALM used: GitHub
  • CI system used: GitHub Actions
  • Languages of the repository: C++

I am developing a header-only C++ library and I want to analyze it using a free tier account at SonarCloud. I should say that I am also using a very similar configuration in another project where things work perfectly but the critical difference is that the other project has translation units of its own, that is, it is not a header-only library.

My problem is that SonarCloud apparently does not support analysis of pure headers isolated from the translation units they are included into. If I use the most straightforward configuration like this (the command line is broken into several lines for clarity here; authentication options not shown):

sonar-scanner
--define sonar.sources=include
--define sonar.cfamily.gcov.reportsPath=.
--define sonar.cfamily.cache.enabled=false
--define sonar.cfamily.threads=1
--define sonar.cfamily.build-wrapper-output=.

Then I get the obvious error:

The “build-wrapper-dump.json” file was found but 0 C/C++/Objective-C files were analyzed.

Okay, that is clear; indeed, there are no .cpp files under include/. Upon reading the docs on “Narrowing the scope” I modified the invocation as follows:

sonar-scanner
--define sonar.sources=include,tests/integration,tests/unit,tests/util
--define sonar.inclusions=include
--define sonar.cfamily.gcov.reportsPath=.
--define sonar.cfamily.cache.enabled=false
--define sonar.cfamily.threads=1
--define sonar.cfamily.build-wrapper-output=.

The sonar-scanner reported success but the web UI says that the project contains zero lines of code.

How do I invoke sonar-scanner correctly for a header-only project considering that I don’t want to analyze my tests?

Thanks!


Edit: I also tried this which failed with “0 C++ files were analyzed”:

sonar-scanner
--define sonar.sources=include
--define sonar.tests=tests/integration,tests/unit,tests/util
--define sonar.cfamily.gcov.reportsPath=.
--define sonar.cfamily.cache.enabled=false
--define sonar.cfamily.threads=1
--define sonar.cfamily.build-wrapper-output=.

I seem to have found a configuration that works:

sonar-scanner
--define sonar.sources=include,tests/unit,tests/integration
--define sonar.issue.ignore.allfile=a1,a2
--define sonar.issue.ignore.allfile.a1.fileRegexp='^#include.*catch\.hpp[>"]$'
--define sonar.issue.ignore.allfile.a2.fileRegexp='^auto main\([^)]*\) -> int$'
--define sonar.coverage.exclusions="tests/**/*"
--define sonar.cpd.exclusions="tests/**/*"
--define sonar.cfamily.gcov.reportsPath=.
--define sonar.cfamily.cache.enabled=false
--define sonar.cfamily.threads=1
--define sonar.cfamily.build-wrapper-output=.
--define sonar.branch.name="${GITHUB_REF##*/}"

The idea is that I declared the tests as project sources (sonar.sources), and then disabled rule checking (sonar.issue.ignore.allfile), coverage measurement (sonar.coverage.exclusions), and duplication detection (sonar.cpd.exclusions) on them.

I understood that this should have been enough to get things to work but for an unknown reason I also had to explicitly set the branch name via sonar.branch.name. Until I did that, SonarCloud could not discover more than one header file (of three) and more than one test file (of a dozen). I don’t think there should be any connection between setting the branch name and the ability to discover source files but that’s what I’m seeing.