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

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

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

GitHub 托管运行程序始终使用 `autobuild` 要求的软件运行。
如果将自托管运行程序用于 GitHub Actions，可能需要安装其他软件才能使用 `autobuild` 进程。 此外，如果你的仓库需要特定版本的构建工具，你可能需要手动安装它。

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

## 生成 C/C++

CodeQL 支持 `none`、`autobuild` 或 `manual` 的 C/C++ 代码生成模式。

为包含 C/C++ 代码的存储库启用默认设置时，生成模式将自动设置为 `none`。

### C/C++ 无构建

CodeQL 将通过源文件扩展名推断 C/C++ 编译单元。 对于找到的每个源文件，编译标志和包含路径都通过检查代码库来推断，而无需使用工作生成命令。

#### C/C++无生成分析的准确性

若在未进行构建的情况下创建 CodeQL C/C++ 数据库，生成的结果在某些情况下可能不如使用 `autobuild` 或手动构建步骤那样准确；例如，如果：

* 代码在很大程度上依赖于现有标头中不可用的自定义宏/定义
* 代码库具有许多外部依赖项

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

* 将自定义宏和定义放置在头文件中，并在相关源文件中包含这些头文件。
* 确保外部依赖项（标头）在系统包含目录或工作区中可用
* 在目标平台上运行提取。 例如，选择一个 Windows 运行器来分析 Windows 项目，以便访问特定于平台的头文件和编译器

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

| 支持的系统类型 | 系统名称                                                                                                 |
| ------- | ---------------------------------------------------------------------------------------------------- |
| 操作系统    | Windows、macOS 和 Linux                                                                                |
| 构建系统    | Windows：MSBuild 和构建脚本<br/>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.bat*、*build.cmd* 和 *build.exe*（按此顺序）。

### Linux 和 macOS 自动检测

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

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

#### C/C++ 运行器要求

在 Ubuntu Linux 运行程序上，`autobuild` 可能会尝试自动安装检测到的配置和生成步骤所需的依赖项。 默认情况下，此行为在GitHub托管运行程序上启用，并在自承载运行程序上禁用。 可以通过在环境中将 `CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES` 设置为 `true` 或 `false` 来显式启用或禁用此功能。 有关定义环境变量的详细信息，请参阅“[在变量中存储信息](/zh/actions/how-tos/write-workflows/choose-what-workflows-do/use-variables#defining-environment-variables-for-a-single-workflow)”。

对于自承载运行程序，除非启用了依赖项的自动安装，否则可能需要安装 `gcc` 编译器，并且特定项目可能还需要 `clang` 或 `msvc` 可执行文件的访问权限。 还需要安装项目所依赖的生成系统（例如 `msbuild`、`make`、`cmake`、`bazel`）和实用工具（例如 `python`、`perl`、`lex` 和 `yacc`）。
如果启用依赖项的自动安装，必须确保运行程序使用的是 Ubuntu，并且无需密码即可运行 `sudo apt-get`。

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

## 生成 C\#

CodeQL 支持 C# 代码的生成模式 `none`、`autobuild` 或 `manual`。

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

### C# 无生成

CodeQL 在从所有源文件和依赖项创建数据库之前，还原依赖项并生成一些附加的源文件，以便提供更准确的结果。

使用多个启发和策略还原依赖项。 以下文件是主要信息来源：`*.csproj`、`*.sln`、`nuget.config`、`packages.config`、`global.json` 和`project.assets.json`。
如果为组织定义了专用 NuGet 源，则也会使用此项，请参阅[对专用注册表的代码扫描默认设置访问权限](/zh/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries#code-scanning-default-setup-access-to-private-registries)和[确定代码扫描默认设置是否使用了任何专用注册表](/zh/code-security/reference/code-scanning/code-scanning-logs#diagnostic-information-for-private-package-registries)。

以下生成的源文件是可选的，但会显著增加数据库的正确性 CodeQL ：

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

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

#### C# 无生成分析的准确性

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

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

* 提供公共 Internet 访问权限或确保提供专用 NuGet 源访问权限，请参阅[对专用注册表的代码扫描默认设置访问权限](/zh/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries#code-scanning-default-setup-access-to-private-registries)。
* 检查存储库是否需要同一 NuGet 依赖项的多个版本。
  CodeQL 只能使用一个版本，通常选择有多个版本的较新版本。 此方法可能不适用于所有存储库。
* 检查是否引用了多个版本的.NET，例如，`net48`、`net5.0` 和 `netstandard1.6`。
  CodeQL 只能使用一个版本，这可能会影响准确性。
* 避免与类名相冲突，否则可能会导致缺少方法调用目标，从而影响数据流分析。

### C# 的自动构建摘要

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

#### Windows自动检测

`autobuild` 进程尝试使用以下方法自动检测适合 C# 的构建方法：

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

#### Windows上的 C# 运行程序要求

对于在自主托管的运行器上进行 .NET Core 应用程序开发，.NET SDK 是必要的（对于 `dotnet`）。

对于.NET框架应用程序开发，需要Microsoft Build工具（适用于 `msbuild`）和 NuGet CLI（`nuget`）。

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

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

#### Linux 和 macOS 自动检测

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

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

对于在自主托管的运行器上进行 .NET Core 应用程序开发，.NET SDK 是必要的（对于 `dotnet`）。

对于 .NET Framework 应用程序开发，需要 Mono 运行时（运行 `mono`、`msbuild` 或 `nuget`）。

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

### CodeQL 为手动构建注入的 C# 编译器标志

CodeQL 追踪器通过拦截构建过程并将信息转发到相关的 CodeQL 语言提取器, 从而实现所有编译语言的提取。 跟踪程序在 C# 编译器调用的过程中传递某些标志，以确保每个组件都生成并包含在 CodeQL 数据库中，这可能会导致 C# 代码以不同于 CodeQL 分析期间您所期望的方式生成。

#### `/p:MvcBuildViews=true`

如果此选项设置为 `true`，ASP.NET model-view-controller （MVC） 项目中的视图将预编译为生成过程的一部分，这有助于捕获错误并提高性能。 跟踪程序注入此标志，以确保 CodeQL 能够查找并清楚地突出显示可能涉及通过这些视图生成代码的数据流的安全问题。 有关详细信息，请参阅 Microsoft Learn 中的[向 MVC 应用程序添加视图](https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/introduction/adding-a-view)。

#### `/p:UseSharedCompilation=false`

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

#### `/p:EmitCompilerGeneratedFiles=true`

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

对于某些旧项目以及使用 `.sqlproj` 文件的项目，可能会发现注入的 `/p:EmitCompilerGeneratedFiles=true` 属性导致出现`msbuild`意外问题。 有关此问题的故障排除信息，请参阅 [C# 编译器意外失败](/zh/code-security/reference/code-scanning/troubleshoot-analysis-errors/c-sharp-compiler-unexpectedly-failing)。

## 生成 Go

CodeQL 支持 Go 代码的构建模式 `autobuild` 或 `manual`。

### Go 的自动生成摘要

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

### Go 自动检测

`autobuild` 过程尝试在提取所有 `.go` 文件之前自动检测安装 Go 存储库所需的依赖项的合适方法：

1. 调用 `make`、`ninja`、`./build` 或 `./build.sh`（按该顺序），直到其中一个命令成功，后续 `go list ./...` 也成功，这表示已安装所需的依赖项。
2. 如果这些命令都没有成功，请查找 `go.mod`、`Gopkg.toml` 或 `glide.yaml`，并分别运行 `go get`（除非正在使用供应商）、`dep ensure -v` 或 `glide install` 以尝试安装依赖项。
3. 最后，如果未找到这些依赖项管理器的配置文件，请重新排列适合添加到 `GOPATH` 的存储库目录结构，并使用 `go get` 安装依赖项。 提取完成后，目录结构恢复为正常。
4. 提取存储库中的所有 Go 代码，类似于运行 `go build ./...`。

> \[!NOTE]
> 如果使用默认设置，它将查找文件 `go.mod` 以自动安装兼容版本的 Go 语言。

### Go 的提取程序选项

默认情况下，测试代码（以 `_test.go` 结尾的文件中的代码）不会被分析。 你可以在使用`--extractor-option extract_tests=true`时通过选项CodeQL CLI来覆盖此选项，或者将环境变量`CODEQL_EXTRACTOR_GO_OPTION_EXTRACT_TESTS`设置为`true`。

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

## 构建Java和Kotlin

CodeQL 支持以下生成模式。

* Java：`none`、`autobuild` 或 `manual`
* Kotlin：`autobuild` 或 `manual`

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

如果稍后将 Kotlin 代码添加到使用生成模式的 `none` 存储库， CodeQL 则分析报告一条警告消息，说明不支持 Kotlin。 需要禁用默认设置并重新启用它。 重新启用默认设置后，生成模式将更改为 `autobuild`，以便可以分析这两种语言。 或者，可以更改为高级设置。 有关详细信息，请参阅“[警告：检测到项目中有 X 个 Kotlin 文件，需经过构建才能进行处理。](/zh/code-security/reference/code-scanning/troubleshoot-analysis-errors/kotlin-detected-in-no-build)”。

### Java 无生成

CodeQL将尝试运行 Gradle 或 Maven 以提取准确的依赖项信息（但不调用生成），然后再从存在的所有Java文件创建数据库。 查询每个根 Maven 或 Gradle 项目文件（上级目录中不存在任何生成脚本的生成脚本）以获取依赖项信息，如果发生冲突，则首选最新的依赖项版本。 有关运行 Maven 或 Gradle 的运行程序要求的信息，请参阅 [Java 的运行程序要求](#runner-requirements-for-java)。

如果为组织定义了专用 Maven 注册表，则也会使用此注册表，请参阅 [代码扫描对专用注册表的默认设置访问权限](/zh/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries#code-scanning-default-setup-access-to-private-registries) ，并确定 [代码扫描默认设置是否使用了任何专用注册表](/zh/code-security/reference/code-scanning/code-scanning-logs#diagnostic-information-for-private-package-registries)。

#### Java 无生成分析的准确性

若在未构建的情况下创建 CodeQL Java 数据库，则在以下情况下生成的结果可能不如使用 `autobuild` 或手动构建步骤那样准确：

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

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

* 提供公共 Internet 访问权限或确保提供专用工件存储库访问权限，请参阅[对专用注册表的代码扫描默认设置访问权限](/zh/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries#code-scanning-default-setup-access-to-private-registries)。
* 检查存储库是否需要同一依赖项的多个版本。
  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 变量中（以便可以找到 `java` 和 `javac`）。

* 如果运行程序将用于分析需要多个版本的存储库Java，则需要安装相应的 JDK 版本，并且可以通过 `toolchains.xml` 文件指定。 这是 Apache Maven 通常使用的配置文件，该文件允许指定工具的位置、工具的版本以及使用这些工具所需的任何其他配置。 有关详细信息，请参阅 Apache Maven 文档中的[工具链使用指南](https://maven.apache.org/guides/mini/guide-using-toolchains.html)。

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

* `mvn` （Apache Maven）
* `gradle` （Gradle）
* `ant` （Apache Ant）

还需要安装项目所依赖的生成系统（例如 `make`、`cmake`、`bazel`）和实用工具（例如 `python`、`perl`、`lex` 和 `yacc`）。

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

## 构建 Rust

CodeQL 支持 Rust 代码的生成模式 `none` 。

### 没有 Rust 的构建

CodeQL 使用 `rust-analyzer` 来编译和运行构建脚本（`build.rs` 文件）以及编译宏代码，但不启动完整的构建过程。 数据库是从存在的所有 Rust 文件创建的。 必须存在`Cargo.toml`或`rust-project.json`文件。

### Rust 的执行环境要求

Rust 分析需要安装 `rustup` 和 `cargo`。

## 生成 Swift

CodeQL 支持 Swift 代码的构建模式 `autobuild` 或 `manual`。

### Swift 的自动生成摘要

| 支持的系统类型 | 系统名称  |
| ------- | ----- |
| 操作系统    | macOS |
| 构建系统    | Xcode |

`autobuild` 进程尝试从 Xcode 项目或工作区生成最大目标。

Swift 代码扫描默认使用 macOS 运行器。
由于GitHub托管的 macOS 运行程序比 Linux 和 Windows 运行程序更昂贵，建议仅构建要分析的代码。 有关 GitHub 托管运行器定价的详细信息，请参阅 [GitHub Actions计费](/zh/billing/concepts/product-billing/github-actions)。

Code scanning Swift 代码不受属于 Actions Runner Controller（ARC）的运行器支持，因为 ARC 运行器仅使用 Linux，而 Swift 需要 macOS 运行器。 但是，你可以混合使用 ARC 运行器和自托管 macOS 运行器。 有关详细信息，请参阅“[操作运行器控制器](/zh/actions/concepts/runners/actions-runner-controller)”。

### 在 CodeQL 分析工作流程 中自定义 Swift 编译

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

可以将 `archive` 和 `test` 选项传递给 `xcodebuild`。 但是，建议使用标准 `xcodebuild` 命令，因为这种方法应该最快，并且应该是 CodeQL 成功扫描所需的全部内容。

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