Skip to main content

已编译语言的 CodeQL 生成选项和步骤

了解 CodeQL 如何生成已编译的语言,包括 C/C++、C#、Go、Java、Kotlin、Rust 和 Swift 的可用生成模式和特定于语言的自动生成行为。

谁可以使用此功能?

具有写入访问权限的用户 if advanced setup is already enabled

Code scanning 可用于以下存储库类型:

  • GitHub.com 上的公共存储库
  • GitHub Team、GitHub Enterprise Cloud 或 GitHub Enterprise Server 上的组织拥有的存储库,已启用 GitHub Code Security

已编译语言的自动生成步骤

如果为 GitHub Actions 使用自托管运行器,则可能需要安装其他软件才能使用 autobuild 进程。 此外,如果你的仓库需要特定版本的构建工具,你可能需要手动安装它。 对于自托管运行器,应直接在运行器中安装依赖项。 我们针对这些语言提供了本文中每个 autobuild 节中 C/C++、C# 和Java的常见依赖项示例。 有关详细信息,请参阅“自托管运行程序”。

注意

如果你的工作流使用 language 矩阵,autobuild 会尝试生成矩阵中列出的每种编译语言。 如果不使用矩阵,则 autobuild 会尝试生成在存储库中具有最多源文件的受支持编译语言。 除 Go 以外,除非你提供明确的构建命令,否则你仓库中其他编译语言的分析将失败。

生成 C/C++

CodeQL 支持将生成模式 autobuildmanual 用于 C/C++ 代码。

C/C++ 的自动生成摘要

支持的系统类型系统名称
操作系统Windows、macOS 和 Linux
构建系统Windows:MSbuild 和生成脚本
Linux 和 macOS:Autoconf、Make、CMake、qmake、Meson、Waf、SCons、Linux Kbuild 和生成脚本
          `autobuild` 步骤的行为因运行提取的操作系统而异。

Windows自动检测

在Windows,autobuild步骤尝试使用以下方法自动检测 C/C++ 的合适生成方法:

  1. 对离根最近的解决方案 (MSBuild.exe) 或项目 (.sln) 文件调用 .vcxproj。 如果 autobuild 在顶层目录下的相同(最短)深度检测到多个解决方案或项目文件,它将尝试生成所有这些文件。
  2. 调用看起来像生成脚本的脚本:build.batbuild.cmdbuild.exe(按此顺序)。

Linux 和 macOS 自动检测

在 Linux 和 macOS 上,autobuild 步骤检查存储库中存在的文件,以确定使用的生成系统:

  1. 在根目录中查找构建系统。
  2. 如果未找到,则搜索子目录以查找含有 C/C++ 构建系统的唯一目录。
  3. 运行适当的命令来配置系统。

C/C++ 运行器要求

在 Ubuntu Linux 运行程序上,autobuild 可能会尝试自动安装检测到的配置和生成步骤所需的依赖项。 默认情况下,此行为在 GitHub 托管的运行程序上启用,并在自托管运行程序上禁用。 可以通过在环境中将 CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES 设置为 truefalse 来显式启用或禁用此功能。 有关定义环境变量的详细信息,请参阅“在变量中存储信息”。

对于自承载运行程序,除非启用了依赖项的自动安装,否则可能需要安装 gcc 编译器,并且特定项目可能还需要 clangmsvc 可执行文件的访问权限。 还需要安装项目所依赖的生成系统(例如 msbuildmakecmakebazel)和实用工具(例如 pythonperllexyacc)。 如果启用依赖项的自动安装,必须确保运行程序使用的是 Ubuntu,并且无需密码即可运行 sudo apt-get

Windows运行器要求powershell.exe位于PATH

生成 C#

CodeQL 支持将生成模式 noneautobuildmanual 用于 C# 代码。

为包含 C# 代码的存储库启用默认设置时,生成模式将自动设置为 none

C# 无生成

CodeQL 会还原依赖项并生成一些其他源文件,以便提供更准确的结果,然后再利用所有源文件和依赖项创建数据库。

使用多个启发和策略还原依赖项。 以下文件是主要信息来源:*.csproj*.slnnuget.configpackages.configglobal.jsonproject.assets.json

以下生成的源文件是可选的,但可显著提高 CodeQL 数据库的正确性:

  •         `global` 生成的 `using` 指令用来处理 MSbuild 的隐式 `using` 功能。
    
  • ASP.NET 核心视图文件,.cshtml 文件将转换为 .cs 文件。

将编译依赖项程序集名称、生成的源文件、 以及存储库中的源文件中的信息并用于创建 CodeQL 数据库。

C# 无生成分析的准确性

要在不生成完整代码的情况下创建 CodeQL 数据库,依赖还原依赖项并编译存储库中的源文件的能力。 如果在还原依赖项或编译源代码时遇到问题,则可能会影响 CodeQL 数据库和 code scanning 分析结果的准确性。

可以通过执行以下步骤来提高分析的准确性:

  • 提供公共 Internet 的访问权限或确保可访问专用 NuGet 源 。
  • 检查存储库是否需要同一 NuGet 依赖项的多个版本。 CodeQL 只能使用一个版本,并且在有多个版本时通常选择较新的版本。 此方法可能不适用于所有存储库。
  • 检查是否引用了多个版本的.NET,例如,net48net5.0netstandard1.6。 CodeQL 只能使用一个版本,这可能会影响准确性。
  • 避免与类名相冲突,否则可能会导致缺少方法调用目标,从而影响数据流分析。

C# 的自动生成摘要

支持的系统类型系统名称
操作系统Windows、macOS 和 Linux
构建系统.NET、MSBuild以及生成脚本

Windows自动检测

          `autobuild` 进程尝试使用以下方法自动检测适合 C# 的构建方法:
  1. 对离根最近的解决方案 (dotnet build) 或项目 (.sln) 文件调用 .csproj
  2. 对离根最近的解决方案或项目文件调用 MSBuild.exe。 如果 autobuild 在顶层目录下的相同(最短)深度检测到多个解决方案或项目文件,它将尝试生成所有这些文件。
  3. 调用看起来像生成脚本的脚本:build.batbuild.cmdbuild.exe(按此顺序)。

Windows上的 C# 运行程序要求

在自托管运行器上进行 .NET Core 应用程序开发时,需要 .NET SDK(对于 dotnet)。

对于.NET框架应用程序开发,需要Microsoft Build工具(适用于 msbuild)和 NuGet CLI(nuget)。

Windows运行器要求powershell.exe位于PATH

如果计划使用 build-mode: none 创建 CodeQL 数据库,则还需要提供对公共互联网的访问权限,或者必须确保能够访问专用 NuGet 源。

Linux 和 macOS 自动检测

  1. 对离根最近的解决方案 (dotnet build) 或项目 (.sln) 文件调用 .csproj
  2. 对离根最近的解决方案或项目文件调用 MSbuild。 如果 autobuild 在顶层目录下的相同(最短)深度检测到多个解决方案或项目文件,它将尝试生成所有这些文件。
  3. 调用看起来像生成脚本的脚本:buildbuild.sh(按此顺序)。

Linux 和 macOS 上的 C# 运行器要求

在自托管运行器上进行 .NET Core 应用程序开发时,需要 .NET SDK(对于 dotnet)。

对于 .NET Framework 应用程序开发,需要 Mono 运行时(运行 monomsbuildnuget)。

如果计划使用 build-mode: none 创建 CodeQL 数据库,则还需要提供对公共互联网的访问权限,或者必须确保能够访问专用 NuGet 源。

CodeQL 注入的用于进行手动构建的 C# 编译器标志

CodeQL 跟踪器通过拦截生成过程并将信息转发到相关的 CodeQL 语言提取器,来提取所有编译语言。 跟踪器将某些标志注入 C# 编译器调用中,以确保每个组件都已生成并包含在 CodeQL 数据库中,这可能会导致 C# 代码在 CodeQL 分析期间以与预期不同的方式生成。

/p:MvcBuildViews=true

如果此选项设置为 true,ASP.NET model-view-controller (MVC) 项目中的视图将预编译为生成过程的一部分,这有助于捕获错误并提高性能。 跟踪器注入此标志,以确保 CodeQL 找到并突出显示可能涉及通过这些视图生成的代码的数据流的安全问题。 有关详细信息,请参阅 Microsoft Learn 中的向 MVC 应用程序添加视图

/p:UseSharedCompilation=false

将此选项设置为 false 会禁用共享编译功能,这可能会导致生成时间变慢。 当/p:UseSharedCompilation=false指定时,msbuild 会启动一个编译器服务器进程,所有编译都将由该单个进程完成。 但是,CodeQL 跟踪器依赖于检查新创建进程的参数。

/p:EmitCompilerGeneratedFiles=true

将此选项设置为 true 会在生成过程中发出编译器生成的文件。 此选项会导致编译器生成其他源文件,用于支持改进的正则表达式支持、序列化和 Web 应用程序视图生成等功能。 这些生成的项目通常不会被编译器写入磁盘,但是将选项设置为 true 会强制将文件写入磁盘,从而使提取程序能够处理这些文件。

对于某些旧项目以及使用 .sqlproj 文件的项目,可能会发现注入的 /p:EmitCompilerGeneratedFiles=true 属性导致出现msbuild意外问题。 有关此问题的故障排除信息,请参阅 C# 编译器意外失败

生成 Go

CodeQL 支持适用于 Go 代码的生成模式 autobuildmanual

Go 的自动生成摘要

支持的系统类型系统名称
操作系统Windows、macOS 和 Linux
构建系统Go 模块、dep 和 Glide,以及生成脚本,包括 Makefiles 和 Ninja 脚本

Go 自动检测

          `autobuild` 过程尝试在提取所有 `.go` 文件之前自动检测安装 Go 存储库所需的依赖项的合适方法:
  1. 调用 makeninja./build./build.sh(按该顺序),直到其中一个命令成功,后续 go list ./... 也成功,这表示已安装所需的依赖项。
  2. 如果这些命令都没有成功,请查找 go.modGopkg.tomlglide.yaml,并分别运行 go get(除非正在使用供应商)、dep ensure -vglide install 以尝试安装依赖项。
  3. 最后,如果未找到这些依赖项管理器的配置文件,请重新排列适合添加到 GOPATH 的存储库目录结构,并使用 go get 安装依赖项。 提取完成后,目录结构恢复为正常。
  4. 提取存储库中的所有 Go 代码,类似于运行 go build ./...

注意

如果使用默认设置,系统将查找 go.mod 文件以自动安装兼容版本的 Go 语言。如果您使用的是没有 Internet 访问权限的自托管运行程序,则可以手动安装兼容版本的 Go。

Go 的提取程序选项

默认情况下,测试代码(以 _test.go 结尾的文件中的代码)不会被分析。 可以在使用 CodeQL CLI 时通过选项 --extractor-option extract_tests=true 替代此内容,也可以通过将环​​境变量 CODEQL_EXTRACTOR_GO_OPTION_EXTRACT_TESTS 设置为 true 来替代此内容。

此外,默认情况下,从 CodeQL Go 分析中排除 vendor 目录。 可以通过在使用 CodeQL CLI 时传递 --extractor-option extract_vendor_dirs=true选项,或者通过将环​​境变量 CODEQL_EXTRACTOR_GO_OPTION_EXTRACT_VENDOR_DIRS 设置为 true 来覆盖此内容。

构建Java和Kotlin

CodeQL 支持以下生成模型:

  • Java:noneautobuildmanual
  • Kotlin:autobuildmanual

首次为存储库启用默认设置时,如果仅检测到Java代码,则生成模式设置为 none。 如果检测到 Kotlin 或 Java 和 Kotlin 代码的组合,则生成模式设置为 autobuild

如果稍后将 Kotlin 代码添加到使用生成模式的 none 存储库,CodeQL 分析将报告一条警告消息,说明不支持 Kotlin。 需要禁用默认设置并重新启用它。 重新启用默认设置后,生成模式将更改为 autobuild,以便可以分析这两种语言。 或者,可以更改为高级设置。 有关详细信息,请参阅“警告:检测到项目中有 X 个 Kotlin 文件,需经过构建才能进行处理。”。

Java 无生成

CodeQL 将尝试运行 Gradle 或 Maven,以提取准确的依赖项信息(但不会启动构建过程),然后从所有现有的Java文件中创建数据库。 查询每个根 Maven 或 Gradle 项目文件(上级目录中不存在任何生成脚本的生成脚本)以获取依赖项信息,如果发生冲突,则首选最新的依赖项版本。 有关运行 Maven 或 Gradle 的运行程序要求的信息,请参阅 Java 的运行程序要求

Java 无生成分析的准确性

在以下情况下,在没有生成的情况下创建 CodeQL Java 数据库可能会产生比使用 autobuild 或手动生成步骤更不准确的结果:

  • 无法查询 Gradle 或 Maven 生成脚本以获取依赖项信息,依赖项猜测(基于Java包名称)不准确。
  • 存储库通常在生成过程中生成代码。 如果 CodeQL 数据库是使用其他模式创建的,则会对此进行分析。

可以通过执行以下步骤来提高分析的准确性:

  • 提供公共 Internet 的访问权限或确保可访问专用项目存储库 。
  • 检查存储库是否需要同一依赖项的多个版本。 CodeQL 只能使用一个版本,并且在有多个版本时通常选择较新的版本。 此方法可能不适用于所有存储库。
  • 检查不同源Java文件是否需要多个版本的 JDK API。 当看到多个版本时,CodeQL 将使用任何生成脚本所需的最高版本。 这可能意味着一些需要较低版本 JDK 的文件将被部分分析。 例如,如果某些文件需要 JDK 8,但在一个或多个生成脚本中发现需要 JDK 17,则 CodeQL 将使用 JDK 17。 任何需要 JDK 8 且无法使用 JDK 17 生成的文件都将被部分分析。
  • 避免与类名冲突(例如,多个文件定义 org.myproject.Test),否则可能会导致缺少方法调用目标,从而影响数据流分析。

Java的自动生成摘要

支持的系统类型系统名称
操作系统Windows、macOS 和 Linux (无限制)
构建系统Gradle、Maven 和 Ant

Java的自动检测

          `autobuild` 过程尝试通过应用此策略来确定Java代码库的生成系统:
  1. 在根目录中搜索构建文件。 先后检查 Gradle、Maven 和 Ant 构建文件。
  2. 运行找到的第一个构建文件。 如果 Gradle 和 Maven 文件都存在,则使用 Gradle 文件。
  3. 否则,在根目录的直接子目录中搜索构建文件。 如果只有一个子目录包含构建文件,则运行该子目录中标识的第一个文件(使用与 1 相同的首选项)。 如果多个子目录包含构建文件,则报告错误。

Java的运行程序要求

如果使用自托管运行器,则需要确保已安装所需版本的 Java。

  • 如果运行程序将用于分析需要单个版本的Java的存储库,则需要安装相应的 JDK 版本,并且需要存在于 PATH 变量中(以便可以找到 javajavac)。

  • 如果运行程序将用于分析需要多个版本的存储库Java,则需要安装相应的 JDK 版本,并且可以通过 toolchains.xml 文件指定。 这是 Apache Maven 通常使用的配置文件,该文件允许指定工具的位置、工具的版本以及使用这些工具所需的任何其他配置。 有关详细信息,请参阅 Apache Maven 文档中的工具链使用指南

一系列Java项目可能需要以下可执行文件,并且应该存在于 PATH 变量中,但它们在所有情况下都并不重要:

  •         `mvn` (Apache Maven)
    
  •         `gradle` (Gradle)
    
  •         `ant` (Apache Ant)
    

还需要安装项目所依赖的生成系统(例如 makecmakebazel)和实用工具(例如 pythonperllexyacc)。

Windows运行器要求powershell.exe位于PATH

生成 Swift

CodeQL 支持适用于 Swift 代码的生成模式 autobuildmanual

Swift 的自动生成摘要

支持的系统类型系统名称
操作系统macOS
构建系统Xcode
          `autobuild` 进程尝试从 Xcode 项目或工作区生成最大目标。

Swift 代码扫描默认使用 macOS 运行器。

属于 Actions Runner Controller (ARC) 的运行器不支持 Swift 代码的 Code scanning,因为 ARC 运行器仅使用 Linux,且 Swift 需要 macOS 运行器。 但是,你可以混合使用 ARC 运行器和自托管 macOS 运行器。 有关详细信息,请参阅“Actions运行器控制器”。

在 CodeQL 分析工作流程

中自定义 Swift 编译

          `xcodebuild` 和 `swift build` 都支持 Swift 内部版本。 我们建议在生成期间仅锁定一个体系结构。 例如,对于 `ARCH=arm64`,则为 `xcodebuild`,或对于 `--arch arm64`,则为 `swift build`。

可以将 archivetest 选项传递给 xcodebuild。 但是,建议使用标准 xcodebuild 命令,因为它应该是最快的命令,并且应该是 CodeQL 成功扫描所需的全部命令。

对于 Swift 分析,在生成 CodeQL 数据库之前,必须始终显式安装通过 CocoaPods 或 Carthage 管理的依赖项。