构建自动化系统的支持
Make及其变体
Coco还可以在不修改项目的情况下为项目生成代码覆盖率信息。原理是将CoverageScanner编译器包装器的路径添加到PATH变量,并使用COVERAGESCANNER_ARGS
环境变量设置仪表化参数。要激活仪表化,COVERAGESCANNER_ARGS
中必须有--cs-on
。如果没有这种情况,CoverageScanner将完全禁用。
注意:变量COVERAGESCANNER_ARGS
应该只在本地设置,例如在脚本或命令行中。如果全局设置,它将影响每个构建。
GNU Make
在UNIX®系统上,按照以下步骤使用GNU Make生成项目进行配置
export PATH=/opt/SquishCoco/wrapper/bin:$PATH export COVERAGESCANNER_ARGS=--cs-on make clean make
对于macOS,将第一行替换为
export PATH=/opt/SquishCoco/wrapper:$PATH
Microsoft NMake
要使用NMake生成的项目进行配置
set PATH=%SQUISHCOCO%\visualstudio;%PATH% set COVERAGESCANNER_ARGS=--cs-on nmake clean nmake
Microsoft MSBuild
要对使用MSBuild生成的项目进行配置
set PATH=%SQUISHCOCO%\visualstudio;%PATH% set COVERAGESCANNER_ARGS=--cs-on msbuild /p:UseEnv=true myproject.sln /t:ReBuild
CMake
使用预加载脚本的仪表化
以下方法在所有简单情况下应能用于设置CMake项目的代码覆盖率。
存在一个通用文件,例如squishcoco.cmake,和特定设置文件(例如squishcoco-gcc.cmake),该文件指定编译器。然后使用类似于以下命令行配置项目时包含设置文件
cmake <other options> -Csquishcoco-gcc.cmake
然后,项目针对代码覆盖率进行配置。
如果缺少编译器的设置文件,可以通过修改现有文件之一来创建它。
squishcoco.cmake文件
文件
请将以下文件保存为 "squishcoco.cmake
" 在您的源代码根目录。更改第一行,以便包含您需要的选项。选项列表必须是一个带有空格分隔的引号字符串。如果没有选项,则启用覆盖率。
此文件不能单独使用(除Qt Creator外),必须从编译器设置文件中包含(见下文)。
set(coverage_flags "--cs-mcdc --cs-no-assignments") // Set your own options foreach(var IN ITEMS CMAKE_C_COMPILER CMAKE_CXX_COMPILER) if(NOT DEFINED ${var}) message(FATAL_ERROR "Variable ${var} must be defined.") endif() endforeach() set(CMAKE_C_FLAGS_INIT "${coverage_flags}" CACHE STRING "Coverage flags for the C compiler." FORCE) set(CMAKE_CXX_FLAGS_INIT "${coverage_flags}" CACHE STRING "Coverage flags for the C++ compiler." FORCE) set(CMAKE_EXE_LINKER_FLAGS_INIT "${coverage_flags}" CACHE STRING "Coverage flags for the linker." FORCE) set(CMAKE_SHARED_LINKER_FLAGS_INIT "${coverage_flags}" CACHE STRING "Coverage flags to link shared libraries." FORCE) set(CMAKE_STATIC_LINKER_FLAGS_INIT "${coverage_flags}" CACHE STRING "Coverage flags to link static libraries." FORCE) if (DEFINED ENV{SQUISHCOCO}) set(cocopath $ENV{SQUISHCOCO}) else() find_file(cocopath SquishCoco PATHS "$ENV{HOME}" /opt/ "/Applications" REQUIRED NO_DEFAULT_PATH ) endif() if(CMAKE_HOST_APPLE) set(wrapperdir "${cocopath}/") elseif(CMAKE_HOST_UNIX) set(wrapperdir "${cocopath}/bin/") elseif(MINGW) set(wrapperdir "${cocopath}\\bin\\") else() set(wrapperdir "${cocopath}\\" ) endif() get_filename_component(c_compiler ${CMAKE_C_COMPILER} NAME) find_program(code_coverage_c_compiler cs${c_compiler} PATHS ${wrapperdir} NO_DEFAULT_PATH) set(CMAKE_C_COMPILER "${code_coverage_c_compiler}" CACHE FILEPATH "CoverageScanner wrapper for C compiler" FORCE) get_filename_component(cxx_compiler ${CMAKE_CXX_COMPILER} NAME) find_program(code_coverage_cxx_compiler cs${cxx_compiler} PATHS ${wrapperdir} NO_DEFAULT_PATH) set(CMAKE_CXX_COMPILER "${code_coverage_cxx_compiler}" CACHE FILEPATH "CoverageScanner wrapper for C++ compiler" FORCE) if(DEFINED CMAKE_LINKER) get_filename_component(linker_prog ${CMAKE_LINKER} NAME) find_program(code_coverage_linker cs${linker_prog} PATHS ${wrapperdir} NO_DEFAULT_PATH) set(CMAKE_LINKER "${code_coverage_linker}" CACHE FILEPATH "CoverageScanner wrapper for linker" FORCE) elseif(${c_compiler} STREQUAL "cl.exe") # special case for Visual Studio find_program(code_coverage_linker "cslink.exe" PATHS ${wrapperdir} NO_DEFAULT_PATH) set(CMAKE_LINKER "${code_coverage_linker}" CACHE FILEPATH "CoverageScanner wrapper for linker" FORCE) endif() if(DEFINED CMAKE_AR) get_filename_component(ar_prog ${CMAKE_AR} NAME) find_program(code_coverage_ar cs${ar_prog} PATHS ${wrapperdir} NO_DEFAULT_PATH) set(CMAKE_AR "${code_coverage_ar}" CACHE FILEPATH "CoverageScanner wrapper for ar" FORCE) endif() mark_as_advanced( cocopath code_coverage_c_compiler code_coverage_cxx_compiler code_coverage_linker code_coverage_ar )
文件 squishcoco-gcc.cmake
此文件需要用于使用 GCC 的事前编译。它必须与 squishcoco.cmake 在同一目录下。
set(CMAKE_C_COMPILER gcc) set(CMAKE_CXX_COMPILER g++) set(CMAKE_AR ar) set(CMAKE_LINKER gcc) include(squishcoco.cmake)
文件 squishcoco-clang.cmake
此文件需要用于使用 Clang 的事前编译。它必须与 squishcoco.cmake 在同一目录下。
set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_AR ar) set(CMAKE_LINKER clang) include(squishcoco.cmake)
文件 squishcoco-visualstudio.cmake
此文件需要用于使用微软 Visual C/C++ 的事前编译。它必须与 squishcoco.cmake 在同一目录下。
set(CMAKE_C_COMPILER cl) set(CMAKE_CXX_COMPILER cl) set(CMAKE_LINKER link) include(squishcoco.cmake)
Windows 下的误导性 CMake 输出
至少在版本 3.20 以及在 Windows 下运行时,CMake 会有误导性的输出
C:\cmake -C\somepath\squishcoco-visualstudio.cmake -- Building for: Visual Studio 16 2019 -- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.22631. -- The C compiler identification is MSVC 19.29.30154.0 -- The CXX compiler identification is MSVC 19.29.30154.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done
该输出表明项目仍在使用原始编译器(cl.exe
),而不是包装器,但事实并非如此:配置了 squishcoco-visualstudio.cmake
的项目实际上生成了仪器化代码。
当您对项目是否使用 Coco 编译存疑时,查看 CMakeCache.txt
。如果它包含此类行,
//CoverageScanner wrapper for C++ compiler CMAKE_CXX_COMPILER:FILEPATH=C:/Program Files/squishcoco/cscl.exe
则表示使用了 Coco 包装器并启用了仪器化。
创建自己的设置文件
通过这些示例,应能够轻松自定义其他编译器的设置文件。只需设置所使用的程序名称,而不是它们的完整路径。变量 CMAKE_AR
仅用于 GCC 类型的编译器,如 GCC、Clang 或许多用于交叉编译的编译器。
使用工具链文件进行仪器化
注意: 这是一个较旧的方法,只有在没有使用工具链文件的情况下才有效。为了应对仍然需要这种情况,将其保留在文档中。
当 Coco 与 CMake 一起使用时,变更部分取决于用于编译的工具链。我们首先描述添加新构建类型的方法,该类型与工具链无关,然后介绍针对微软® Visual Studio® 和 GNU GCC 的附加变更。
为仪器化编译添加新的构建类型
第一步与所使用的工具链无关。其目的是声明用于指定仪器化编译的 CMake 变量。在 CMake 中,这是通过声明一个 构建类型 来实现的,我们在这里将其称为 COVERAGE
。
为此,将以下行添加到 CMakeLists.txt
文件中。第一行中的变量 COVERAGE_FLAGS
指定了 CoverageScanner 命令行选项。将其值更改为符合您的要求。只有 --cs-on
必须始终存在。
SET(COVERAGE_FLAGS "--cs-on --cs-count") SET(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_RELEASE} ${COVERAGE_FLAGS}" CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE ) SET(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_RELEASE} ${COVERAGE_FLAGS}" CACHE STRING "Flags used by the C compiler during coverage builds." FORCE ) SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${COVERAGE_FLAGS}" CACHE STRING "Flags used for linking binaries during coverage builds." FORCE ) SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${COVERAGE_FLAGS}" CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE ) SET( CMAKE_STATIC_LINKER_FLAGS_COVERAGE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} ${COVERAGE_FLAGS}" CACHE STRING "Flags used by the static libraries linker during coverage builds." FORCE ) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE CMAKE_SHARED_LINKER_FLAGS_COVERAGE CMAKE_STATIC_LINKER_FLAGS_COVERAGE COMPILE_DEFINITIONS_COVERAGE )
这些命令将 Release
构建类型的编译器和链接器标志添加到其中。如果您想使用其他构建类型的标志,请将此代码中的后缀 _RELEASE
替换为另一个构建类型的名称,例如 _DEBUG
。
Microsoft Visual Studio
在 Visual Studio 中,我们需要将新的 Coverage
构建类型设置为对 IDE 可见。为此,我们向基于您发布配置的 CMakeSettings.json
中的 configurations
列表添加一个项目。
{ "configurations": [ "_comment" : "other configurations here... ", { "name": "CodeCoverage-x64-Release", "generator": "Ninja", "configurationType": "Release", "buildRoot": "${projectDir}\\out\\build\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}", "cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE=cl.cmake -DCMAKE_BUILD_TYPE=COVERAGE", "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x64_x64" ], "variables": [] } ] }
这里的重要细节是 cmakeCommandArgs
,它告诉 cmake 使用 cl.cmake
工具链文件,并使用 COVERAGE
构建类型。其他参数/变量可以复制或根据另一个工作配置进行自定义。
使用 Microsoft NMake 进行编译
在用 NMake 编译的项目中
- 创建一个工具链定义文件
cl.cmake
,用于替换编译器和链接器,用它们的 CoverageScanner 包装器代替。例如
# this one is important SET(CMAKE_SYSTEM_NAME Windows) # specify the cross compiler FILE(TO_CMAKE_PATH "$ENV{SQUISHCOCO}/visualstudio" SQUISHCOCO) SET(CMAKE_C_COMPILER ${SQUISHCOCO}/cl.exe CACHE FILEPATH "CoverageScanner wrapper" FORCE) SET(CMAKE_CXX_COMPILER ${SQUISHCOCO}/cl.exe CACHE FILEPATH "CoverageScanner wrapper" FORCE) SET(CMAKE_LINKER ${SQUISHCOCO}/link.exe CACHE FILEPATH "CoverageScanner wrapper" FORCE)
- 创建一个 Makefile 项目。将工具链设置为 CoverageScanner 包装器,并将构建模式设置为
COVERAGE
。例如
cmake.exe -DCMAKE_TOOLCHAIN_FILE=cl.cmake -DCMAKE_BUILD_TYPE=COVERAGE \ -G "NMake Makefiles" <i>path of cmake project</i>
- 使用
nmake
构建项目。
使用 GNU GCC 进行编译
以下操作必须在用 gcc
编译的项目中执行
- 创建一个工具链定义文件
gcc.cmake
,用它们的 CoverageScanner 包装器替换编译器和链接器。例如
find_program(CODE_COVERAGE_GCC gcc PATHS /opt/SquishCoco/wrapper/bin "$ENV{HOME}/SquishCoco/wrapper/bin" NO_DEFAULT_PATH ) find_program(CODE_COVERAGE_GXX g++ PATHS /opt/SquishCoco/wrapper/bin "$ENV{HOME}/SquishCoco/wrapper/bin" NO_DEFAULT_PATH ) find_program(CODE_COVERAGE_AR ar PATHS /opt/SquishCoco/wrapper/bin "$ENV{HOME}/SquishCoco/wrapper/bin" NO_DEFAULT_PATH ) # specify the cross compiler SET(CMAKE_C_COMPILER "${CODE_COVERAGE_GCC}" CACHE FILEPATH "CoverageScanner wrapper" FORCE) SET(CMAKE_CXX_COMPILER "${CODE_COVERAGE_GXX}" CACHE FILEPATH "CoverageScanner wrapper" FORCE) SET(CMAKE_LINKER "${CODE_COVERAGE_GXX}" CACHE FILEPATH "CoverageScanner wrapper" FORCE) SET(CMAKE_AR "${CODE_COVERAGE_AR}" CACHE FILEPATH "CoverageScanner wrapper" FORCE)
- 创建一个 Makefile 项目。将工具链设置为 CoverageScanner 包装器,并将构建模式设置为
COVERAGE
。例如
cmake -DCMAKE_TOOLCHAIN_FILE=gcc.cmake -DCMAKE_BUILD_TYPE=COVERAGE \ -G "Unix Makefiles" <i>path of cmake project</i>
- 使用
make
构建项目。
Qt 框架
注意:较新的 Qt 版本也支持 CMake 作为其构建系统。CMake 章节中的说明也适用于 Qt 项目。
qmake
qmake
是一个工具,Qt 通过使用所谓的 项目文件 以平台无关的方式生成 makefile。它也被 Qt Creator 使用。
默认情况下,qmake
选择用于编译的程序。我们可以通过将一些声明放入 qmake
项目文件来使用 Coco 包装器。这可以通过将一些声明放入 qmake
项目文件来完成。由于需要以带有和不带覆盖率的方式来构建项目,所以新的定义必须放在一个作用域中。作用域是指可以在需要时激活的 qmake
项目文件中的一个区域。
以下列表显示了一个名为 CoverageScanner
的作用域模板,这对于大多数项目通常足够。
CodeCoverage { COVERAGE_OPTIONS = QMAKE_CFLAGS += $$COVERAGE_OPTIONS QMAKE_CXXFLAGS += $$COVERAGE_OPTIONS QMAKE_LFLAGS += $$COVERAGE_OPTIONS QMAKE_CC=cs$$QMAKE_CC QMAKE_CXX=cs$$QMAKE_CXX QMAKE_LINK=cs$$QMAKE_LINK QMAKE_LINK_SHLIB=cs$$QMAKE_LINK_SHLIB QMAKE_AR=cs$$QMAKE_AR QMAKE_LIB=cs$$QMAKE_LIB }
我们在这里还设置了变量 QMAKE_LINK_SHLIB
和 QMAKE_AR
,它们包含链接共享库和生成归档的命令。此外,您可以使用 COVERAGE_OPTIONS
来设置 coveragescanner
命令行选项(请参阅 选项列表)以自定义项目。空值 COVERAGE_OPTIONS
也可以使用,并会导致默认的探测。
在小型项目中,将 CodeCoverage
作用域复制到所有的配置文件中,即以 .pro
结尾的文件。实际上,只需将这些插入到真正编译代码的文件中,而不是只包含其他文件的文件即可。如果项目较大,它通常有一个包含所有配置的常见设置的文件,然后这就是唯一一次插入 CodeCoverage
作用域的最方便的地方。
默认情况下,新的探测作用域是禁用的。要在构建的项目中启用代码覆盖率,只需在用 qmake
配置时将作用域的名称添加到 CONFIG
变量中即可
$ qmake CONFIG+=CodeCoverage
moc
元对象编译器(moc)为从QObject派生的每个类生成一些方法。例如,翻译函数tr
,所有信号的开源代码,类型转换操作符qt_cast
……为了使用Qt框架对代码进行插桩而不是moc生成的代码,CoverageScanner提供了命令行选项--cs-qt3
用于Qt3和--cs-qt4
用于Qt4至Qt6。它们默认启用。
在这种情况下
Q_OBJECT
宏不再进行插桩。- 所有信号都会进行插桩,以跟踪它们的发送。
- 用于信号/槽机制的粘合代码不会进行插桩。
- 在Qt4中,
Q_FOREACH
宏的代码不会进行插桩。
qbs
要将Coco与Qt构建套件(qbs
)一起使用,请将其设置为一个工具链。然后,您可以使用此工具链为所有qbs
项目。
要将Coco设置为一个工具链,请执行以下命令
qbs setup-toolchains --type gcc /opt/SquishCoco/bin/csgcc csgcc
对于基于Unix的操作系统,需要一些额外的配置步骤
qbs config profiles.csgcc.cpp.archiverPath /opt/SquishCoco/bin/csar qbs config profiles.csgcc.cpp.linkerName csg++ qbs config profiles.csgcc.cpp.nmPath /opt/SquishCoco/bin/csgcc-nm
然后,csgcc
工具链也可以用作Qt项目的基准配置文件
qbs setup-qt /opt/Qt/bin/qmake qt-csgcc qbs config profiles.qt-csgcc.baseProfile csgcc
SCons
要使用Coco与SCons
- 将Coco的包装器(
csgcc
、cscl
等)的路径添加到PATH环境变量。PATH环境变量应设置为能够执行Coco包装器。 - 将
CC
、AR
和LINK
变量设置为相应的Coco包装器。例如:当使用Microsoft Visual Studio编译器时,将CC
设置为cscl.exe
,将LINK
设置为cslink.exe
,将AR
设置为cslib.exe
。注意:不要使用到编译器包装器的绝对文件路径,因为某些版本的SCons不能正确处理文件名中的空格。
- 将代码覆盖率设置添加到变量
CCFLAGS
、ARFLAGS
和LINKFLAGS
中,以排除插桩示例文件。
以下是一个可用于Visual Studio命令行工具的代码片段
import os from os.path import pathsep env = Environment() # Add the path of Squish Coco compiler wrapper env[ 'ENV' ][ 'PATH' ] = os.environ[ 'SQUISHCOCO' ] + pathsep + env[ 'ENV' ][ 'PATH' ] # TEMP variable need to be defined env[ 'ENV' ][ 'TEMP' ] = os.environ[ 'TEMP' ] env[ 'ENV' ][ 'INCLUDE' ] = os.environ[ 'INCLUDE' ] # Set the compiler to Squish Coco wrappers env[ 'CC' ] = 'cs' + env[ 'CC' ] ; env[ 'AR' ] = 'cs' + env[ 'AR' ] ; env[ 'LINK' ] = 'cs' + env[ 'LINK' ] ; # Code coverage settings coverageflags = [ '--cs-count' ] env[ 'CCFLAGS' ] = env[ 'CCFLAGS' ] + coverageflags ; env[ 'ARFLAGS' ] = env[ 'ARFLAGS' ] + coverageflags ; env[ 'LINKFLAGS' ] = env[ 'LINKFLAGS' ] + coverageflags ;
要正确设置构建环境,您必须从Visual Studio的开发者提示(通过开始菜单可用)或构建环境选择提供的Coco控制台开始构建。
Coco v7.2.0©2024 Qt公司有限公司。
Qt及其相应标志是Qt公司在芬兰和/或其他国家的商标。所有其他商标都是其各自所有者的财产。