We use SQ Enterprise edition.
How does SQ handle conditional compiled code? For example, we may have a file that is included in all three flavors of the COM (let’s say it’s called MyFile.cpp), however, inside MyFile.cpp we may have code like this:
…some code here for the COMv3 only…
…some code here for COMv1 & COMv2
Our Makefile for the COMv3 would pass in a #define (-DoCOMv3) which tells the compiler to include the first chunk of code above. If 'COMv3 is not defined (i.e., the Makefile does not pass in ‘-DoCOMv3’) then the second chunk of code is compiled.
Can SQ handle traversing the proper code path based on if it’s scanning for COMv1 , COMv2 or COMv3 ?
Minor point: I believe you want “-DCOMv3”, not “-DoCOMv3”. But the overall question still stands: How does SQ handle conditional compiled code?
We do analyze the code in the configuration that you define in your makefile. The main purpose of the build wrapper or the compilation database is to determine this information. So if your build defines
COMv3, the code will be analyzed with
COMv3 defined too.
I’m not totally sure, but you seem to say that in your codebase, the same file should be analyzed several with different macro definitions. If I misunderstood this point, you can skip the rest of this message. Otherwise, there can be different situations:
- A .cpp file is compiled several times in a single project with different
#define (this is not a really common situation, but seems to match best what you described):
In that case, the file will only be analyzed once, in the configuration that first appeared in the build wrapper file or the compilation database
- A header is included is different translation units, with different context and different
In that case, the file will be analyzed several times, for each translation unit and in the context of that translation unit. The result will be the union of the individual results. Which means that you could have violations in both the “then” and the “else” part of a
#if, each coming from a different context
- You have one project that is build in different contextes, with different options. It is similar to the first case, except that the different build of the same .cpp are not intended to be mixed in the same final program, but live in different
parallel universes binaries.
Right now, this case is not supported very well, and you have to use workarounds to make it work. If this is the situation you are in, feel free to ask for more details. We have an open feature request for this situation (https://portal.productboard.com/sonarsource/3-sonarqube/c/315-analyze-multiple-code-variants), you can upvote it if you want.
Hope this helps…
Hi. Thanks for the info. (BTW, Zia and I work together – I had sent him the question initially, and he posted it here.)
We have several different embedded boards that are similar but different (our older rev 1 board that uses a certain processor; a newer rev 2 board that uses a different processor with different endian-ness; etc).
We have different build environments (e.g., a build environment to compile code for the rev 1 processor; another build environment to compile code for the rev 2 processor; etc). Typically we have one dedicated build machine for each environment (to avoid have the development environments step on each other).
To avoid having so much duplicate code, many of these boards share the same code base, which is accessible by all the build machines.
The (generated at build time) Makefiles for the different environments use “-Dxxxx” to cause chunks of code to be included or excluded depending on which build environment is being used.
BTW, I’m one of the engineers who is familiar with the embedded build environment, however, I’m brand new to SQ (that’s Zia’s responsibility). I will reread your reply several times to absorb exactly what you’re saying.
In the meantime, could you please enlighten me as to how SQ finds the Makefile(s) for a given project? My understanding from Zia is that SQ pulls code from our source code repository and then scans the code. If this is the case, then there really isn’t a Makefile to scan as the Makefiles get generated at compile time by our development tools (Workbench, Eclipse, etc).
So it looks like you’re situation matches the third bullet of my previous answer.
About your question, we don’t directly read makefiles. I will assume that you are using the build wrapper, and not the compilation database (@Zia will probably be able to confirm if this assumption was right).
In that case, the analysis process is the following:
- Your CI pulls code from the repository
- Your CI builds the code, but with the build wrapper tool that monitors everything that happens during this build (it monitors the command lines used to launch the compiler, so is works no matter which build system you are using)
- We start analyzing, using the configuration for each translation unit that was generated by the build wrapper.
I hope this clarifies the process. Otherwise, more documentation is available, and you can ask me complementary questions.
Thanks for the info. I will follow-up with Zia about how SQ works in our environment.
Take care, and have a great day.