构建系统政策

本文档详细介绍了设计原则和制定的具体技术决策 与 Fuchsia 构建工作方式有关的重要信息。 例如,这些原则适用于所有使用 Fuchsia build 的模式 无论是通过交互式工程工作流,还是通过 CI/CQ。

构建的目标和优先级

与所有系统一样,编译系统经常会面临多次冲突 要求。当发生冲突时,我们通常会寻求满足这些 优先级顺序:

  1. 满足由 Fuchsia 技术领导层确定的客户要求。
  2. 确保正确性:生成所需的输出。
  3. 促进可维护性:文档、完善的工程流程。
  4. 提高性能:以更低的费用执行相同的构建。

build 的所需属性

以下属性被视为适合此 build 的属性:

  • 封闭性 - build 是独立的,不影响外部因素 软件和配置,或受外部软件影响, 配置。
  • 可重复性和可再现性 - 基于同一源代码树的两个 build 确定性地产生相同的输出或结果。 可再现性可提高安全性和审核能力,并可简化 问题排查。
  • 高效 - 构建应只将时间花在与构建相关的工作上 并且必须力求最大程度减少对人力和基础设施成本的影响。
  • 可移植性 - build 应在所有受支持的 build 中生成一致的结果 托管平台

这些都是一种理想。 我们的目标是实现这些理想,并根据这些措施衡量取得的进展。

使用 Python 脚本作为构建操作

Python 脚本可以用作构建操作。

请遵循适用于 Python 的 Google 样式指南

Fuchsia 目前使用 Python 3.8。所有 Python 源代码均以 以下:

#!/usr/bin/env fuchsia-vendored-python

将 Shell 脚本作为构建操作

Shell 脚本可以用作构建操作。

对于能通过几个简单的选项来表示的任务,建议使用 Shell 脚本。 shell 命令。对于复杂的操作,最好使用其他语言。

请遵循 Google 编写 Shell 脚本的样式指南。 请使用 shellcheck 查找并更正常见的 shell 编程错误。

我们更倾向于使用 POSIX(又名 Bourne)Shell 脚本,以便在各种 托管平台 如果您维护的是现有的 Bash 脚本,请限制其功能 也可以考虑将脚本重写为 POSIX Shell 脚本。 如需检查您的脚本是否兼容 POSIX,您可以使用以下命令:

shellcheck --shell=sh

在 POSIX shell 上运行的脚本应以下列内容开头:

#!/bin/sh

明确要求使用 Bash 的脚本应以以下内容开头:

#!/bin/bash

迁移

构建系统可以协助执行迁移,例如 编译器功能、新工具或各种最佳实践的涌现。 旧版不良行为通常可以用依赖项表示 应用此行为的 config() 上。使用旧版工具或 要替换的模板可以被 group() 的依赖项捕获 目标。

签订方案

我们始终欢迎努力改善代码运行状况,但应该明确 在开始之前做好计划。只完成一半的迁移 势不可挡比完全不迁移更糟糕。

建立回归停止点

假设代码库每 8 个月就会增加一倍,并尽早运行 以防止引入旧版行为的新实例。修改者 建立回归停止,您就“被动”清理代码库 受其加倍率的约束,也就是说, 被动清理了一半代码库。

确保许可名单受 OWNERS 文件及其 POC 保护 被列为所有者。由于所有者由文件定义,因此可能为 最好将许可名单细分为不同的 BUILD.gn 文件。例如, config() 个与 Rust 相关的目标已提取到 //build/config/rust, 更好地管理OWNERS分配。

文档迁移 / 清理步骤

发布清晰的文档,说明迁移的性质以及如何迁移 以及如何执行相关的维护工作。这样,您的 迁移工作规模可进行扩展,并防止任何个人成为 正在进行的迁移工作,例如在处理请求不堪重负时 或因其他原因无法回答问题。

C++ 隐式转换视为正面示例。

简化和自动执行许可名单维护

许可名单很容易表示为 GN 目标的 visibility 名单。此操作会打开 进入自动分析之门,以及做出违反许可名单的更改 快速导致构建失败

将目标列入许可名单以采用要迁出的旧版行为时 使这些目标的所有者可以轻松进行简单的重构,例如 通过将基本目录列入许可名单,重命名其目录中的各个目标 而不是单个目标。

记录重新生成和删减许可名单的步骤,以便可以 由任何人执行

请参见下面的示例:

group("foo_allowlist") {
  #  ________  _________  ________  ________
  # |\   ____\|\___   ___\\   __  \|\   __  \
  # \ \  \___|\|___ \  \_\ \  \|\  \ \  \|\  \
  #  \ \_____  \   \ \  \ \ \  \\\  \ \   ____\
  #   \|____|\  \   \ \  \ \ \  \\\  \ \  \___|
  #     ____\_\  \   \ \__\ \ \_______\ \__\
  #    |\_________\   \|__|  \|_______|\|__|
  #    \|_________|
  # This is an allowlist of targets that use the deprecated "foo" tool.
  # As of April 2021 we no longer use "foo". Users should migrate to the new
  # "bar" tool as described in this guide:
  # https://fuchsia.dev/...
  #
  # To regenerate:
  # fx gn refs $(fx get-build-dir) //path/to:foo_allowlist | sed 's|\(.*\):.*|"\1/*",|' | sort | uniq
  #
  # To trim:
  # scripts/gn/trim_visibility.py --target="//path/to:foo_allowlist"
  visibility = [
    "//src/project1/*",
    "//src/project2/*",
    ...
  ]
}

然后在其他位置自动添加对已列入许可名单的目标的依赖项。

# Invoke the legacy foo tool.
# For new usage, please consider using the new bar tool instead!
# See:
# https://fuchsia.dev/...
# ...
template("foo") {
  action(target_name) {
    ...
    deps += [ "//build/foo:foo_allowlist" ]
  }
}

第三方可能不在服务范围内

Fuchsia 使用了大量第三方代码,这些代码不在范围内 Fuchsia 项目的相关人员。一般来讲,通常可以输入毯子 所有第三方代码的许可名单。

group("bar_allowlist") {
  ...
  visibility = [
    "//third_party/*",
    ...
  ]
}

根据更改的性质以及涉及的第三方代码, 可以在上游进行更改。请尽您所能地做出判断。