欢迎访问Sonar Source中文网站!
语言选择: ∷ 

在 C++ 中使用多个代码变体

发布时间:2023-08-04浏览次数:68

作为 C 或 C++ 开发人员,您可能会以多种不同的方式构建源代码。至少,大多数开发人员分别构建所谓的“调试”和“发布”版本(或优化和非优化版本)。但也许您还构建跨平台,例如 Windows、Linux 和 macOS?或者也许您仍然支持 32 位架构以及 64 位架构?如果您使用嵌入式系统,您可能会针对许多不同的处理器。或者也许您只是维护一个可以针对不同错误处理机制(异常、错误代码等)进行配置的库?还有更多的可能性——当然还有它们之间的所有排列。根据您的项目的性质,您可能会或可能不会控制正在使用的排列。无论如何,我们将每个可能的构建配置称为“代码变体”。


通常,大多数源代码对于所有变体都是通用的,但预处理器通常用于有条件地编译或编译特定部分。当然,经过后处理的源代码会有所不同。但是,作为 C++,即使公共部分的含义也可能不同!事实上,即使没有预处理器,含义也可能改变。例如,对象的大小可能因架构而异,甚至仅由于打包和对齐配置而异。任何这些变化都可能影响分析结果。例如,Sonar 的规则S1238关心作为参数传递的对象的大小。

以前是如何支持的?

显然,应该分析所有或至少关键的代码变体。虽然这一点早已被认识到,但直到最近我们的支持更多地只是一种解决方法,而不是一流的功能。变体可以被独立扫描——但结果也是独立的。因此,例如,如果您将问题标记为“无法修复”,则必须对每个变体执行此操作。有几种方法可以缓解这些问题,但没有一种方法非常令人满意。


因此,我们现在添加了对多代码变体的一流支持,并且我们很高兴地说,从 SonarQube 10.1 开始提供此支持。

新功能如何运作?

我们仍将对每个变体进行全面分析。但现在设置起来更容易、更具表现力 - 而且更重要的是 - 结果以聚合视图显示,解决了我们之前遇到的所有问题!让我们通过一个例子来看看它的实际效果。


想象一下,您有一个主要在 64 位架构的 Linux 上运行的项目,使用 GCC 构建。我们有调试和发布版本,因此已经有两个变体。但它也可以使用 clang 构建,此外,32 位版本作为发行包的一部分发布。


现在,所有这些配置选项的叉积为我们提供了八种可能的代码变体。然而,并非所有这些都有趣,我们可能只能关注其中的四个:

  • 主要: GCC,64 位,发行版

  • 调试: GCC,64 位,调试

  • Clang: clang,64 位,调试

  • 32: GCC,32 位,版本


粗体名称是我们引用各个变体的方式。我们需要做的第一件事是让 SonarQube 知道这些名称,我们通过定义属性:sonar.cfamily.variants.names来获得值:Main, Debug, Clang, 32


sonar.projectKey=xxxxxxxxxxxxxxxxxxx
sonar.cfamily.variants.names=Main, Debug, Clang, 32


接下来,我们需要提供每个变体的配置。我们以与单个变体相同的方式执行此操作:使用构建包装器或提供编译数据库文件但是,配置(build-wrapper-dump.json 或compilationdb.json)应放置在以变体名称(例如Main)命名的目录中,该目录本身位于属性指定的目录下sonar.cfamily.variants.dir因此,例如,如果sonar.cfamily.variants.dir有该值,/Users/philnash/Dev/MyProject/bw-out则应写入第一个构建配置 json 文件,/Users/philnash/Dev/MyProject/bw-out/Main/依此类推。


MyProject
 |- bw-out
 |   |- Main
 |   |- Debug
 |   |- Clang
 |   |- 32
 |- …


在撰写本文时指出一个限制非常重要。与往常一样,构建配置 json 文件必须在进行分析的计算机上生成。因此,如果您正在为不同的平台或架构进行构建,则必须进行某种交叉编译才能使其工作。在某些情况下,这可能看起来不方便,甚至不可能实现。但做出这种权衡使我们现在可以发布此功能。支持多台机器在未来是可行的,但本身就是一项艰巨的任务。为了帮助我们了解此限制的影响,请告知我们这是否对您构成障碍。


这也意味着您可能无法并行运行这些构建 - 例如使用 GitHub Actions 的矩阵策略 - 因为这通常会发生在不同的(虚拟)机器上 - 或者至少是隔离的环境中。必须在运行分析步骤之前生成所有构建配置。


有了这两件事(…names属性和将配置文件放置在相应的子目录中),我们现在可以像往常一样启动分析 - 只是现在需要更长的时间,因为它正在执行四次分析,而不是仅仅一次。

怎么办?

SonarQube 的屏幕截图显示每个问题的不同数量的代码变体

好吧,当第一次查看分析结果时,它可能与正常(单变量)分析没有太大不同。但是,如果仔细观察,您会看到每个问题都有一个新字段,指示有多少变体受到影响。在我们的例子中,如果问题与变体无关,那么我们预计会看到此处显示“4 个变体”。但如果数量较少,那么 - 宾果游戏!- 设置多个代码变体的所有努力都得到了回报 - 我们刚刚发现了一个特定于变体的问题。


您还可以在侧栏中过滤问题以关注特定变体 - 例如,如果您想关注 32 位变体。

SonarQube 的屏幕截图显示代码变体过滤器列表


此外,例如,如果某个问题被标记为“无法修复”,那么现在这适用于存在该问题的所有变体。


拥有多个代码变体是丰富的 C++ 的一部分。现在可以更轻松地分析这些变体并确保它们得到应有的关注。

常问问题

如果我分析多个变体,是否会影响项目的 LOC?
以多种变体进行分析的文件仅计算一次。因此,您应该看到的唯一影响是之前是否跳过了某个文件,而现在至少在其中一个变体中考虑了该文件。


多个代码变体是否与缓存兼容?
是的。


SonarCloud 是否支持多种代码变体?
在撰写本文时还没有。这正在考虑之中。如果您对此感兴趣,告诉我们。


多个代码变体与代码覆盖率兼容吗?
您可以在具有多个代码变体的分析中获得覆盖率信息,但您只能为整个分析提交一份覆盖率报告。这意味着您必须选择最有意义的变体用于覆盖率信息,或者自己做一些工作来合并覆盖率报告,然后再提交。


微信扫码微信扫码 关注我们

  • 24小时咨询热线180-210-69380

  • 移动电话180-210-69380

Copyright © 2022 All Rights Reserved. 地址:上海市浦东新区崮山路538号808 苏ICP123456 XML地图