> For the complete documentation index, see [llms.txt](https://freebsd-journal-cn.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://freebsd-journal-cn.bsdcn.org/20160910-huan-ying-lai-dao-freebsd-11/freebsd-toolchain.md).

# FreeBSD 工具链

* 原文：[FreeBSD Toolchain](https://freebsdfoundation.org/wp-content/uploads/2016/10/FreeBSD-Toolchain.pdf)
* 作者：**Ed Maste**

与其他 BSD 发行版一样，FreeBSD 有基本系统的概念，即集成的内核和核心用户空间，由同一团队共同开发、测试和发布。用户空间包括 C 语言运行时、构建工具链、基本系统工具，以及一些第三方库和应用程序。工具链包括编译器和链接器，它们将源代码翻译为可执行对象，以及用于检查或修改这些对象的相关工具。

除基本系统外，还有一个通过 FreeBSD Ports 树和二进制软件包管理的第三方软件生态系统。Ports 树中有超过 26,000 个第三方软件包。

在其历史的大部分时间里，FreeBSD 依赖完整的 GNU 工具链套件，包括 GNU 编译器套件（GCC）编译器和 GNU binutils。它们在 1993 年到 2007 年间为 FreeBSD 项目服务良好，直到 GNU 项目转而以通用公共许可证第 3 版（GPLv3）发布其软件。与许可证第 2 版不同，GPLv3 对软件用户施加了若干新限制，FreeBSD 开发者和用户认为这些限制不可接受。因此，FreeBSD 中的 GNU 工具链未更新到新的上游版本，很快便过时了。

在那次过渡后不久，FreeBSD 项目中的若干开发者开始将 FreeBSD 工具链的组件更新为现代的、无版权限制的替代品。工具链的某些方面与架构相关，一般来说，下面描述的工具适用于 FreeBSD 的一级架构（Tier-1）。

## 编译器

LLVM 项目是一组模块化、可复用的组件集合，用于构建编译器和其他工具链工具。它最初是伊利诺伊大学的一个研究项目，后来发展成为一个生产级工具集，用于专有软件、开源软件和学术环境。Clang 是 LLVM 套件中包含的 C 和 C++ 编译器。

我们从 2009 年开始在 FreeBSD 中试验 Clang，最初以上游项目 Subversion 仓库的一个快照为起点。最初加入时，它作为一个选项提供，以方便测试和开发，但很长一段时间内并未启用为默认编译器。2014 年 1 月发布的 FreeBSD 10 中纳入了 Clang，作为 32 位和 64 位 Intel x86 架构的系统编译器（即安装为 **/usr/bin/cc**）。后来它成为 32 位 FreeBSD ARM 移植版的默认编译器。64 位 ARM 移植版从起步就以 Clang 作为系统编译器。

Clang 对 MIPS 和 PowerPC 架构有一定支持，但尚不能在这些架构上替代系统编译器；这些架构仍继续使用 GCC。

FreeBSD 11 包含 Clang 3.8.0，FreeBSD-CURRENT 中正在更新至 Clang 3.9.0。

## 链接器

链接器以编译器或汇编器生成的各个对象文件为输入，将它们链接为可执行二进制文件或库。迄今为止我们在 FreeBSD 中使用 GNU 链接器，最近一次更新是在 2011 年 2 月，版本为 2.17.50。该链接器缺少链接时优化和对某些调试特性的支持。

基本系统中的 GNU ld 还缺少对 AArch64（arm64）和 RISC-V 的支持，这两种 CPU 架构是最近加入 FreeBSD 的。目前为这些架构构建 FreeBSD 需要从 Ports 树安装链接器或作为软件包安装，此时会自动使用它。

LLVM 项目家族包含一个链接器：LLD。它是一个高性能链接器，支持 ELF、COFF 和 Mach-O。在可能的情况下，它保持与 GNU ld 等现有链接器的命令行和功能兼容性，但当严格兼容性妨碍性能或所需功能时，LLD 的作者不受其约束。

LLD 的 ELF 支持工作始于 2015 年 7 月，进展非常迅速；它目前在 LLVM 支持的若干架构上能自举，并包含构建 FreeBSD 基本系统所需的几乎所有功能。

与 GNU ld 相比，FreeBSD 中的 LLD 将提供 AArch64 及最终的 RISC-V 支持、全程序链接时优化（LTO）、对新的应用二进制接口（ABI）的支持、其他链接器优化、调试特性，以及快得多的链接时间。

如同早期对 Clang 的试验，LLD 将首先作为选项加入 FreeBSD，不会安装为系统链接器（**/usr/bin/ld**）。可通过在编译器命令行参数中添加 `-fuse-ld=lld`（例如通过变量 `CFLAGS`）来使用它。

我们随 Clang 3.9 更新一并纳入了 LLD 3.9，预计它将于 2016 年 10 月或 11 月在 FreeBSD-CURRENT 中可用。预计也会加入 FreeBSD 11.1。

## 二进制工具

工具链包含若干小型二进制工具，用于检查或修改对象文件、二进制文件和库。这些工具报告对象、二进制文件或库的信息，或转换对象的内容或格式。这些工具过去由 GNU binutils 提供。

ELF Tool Chain 项目维护基本编译工具和库的 BSD 许可实现，用于处理 ELF 对象文件和二进制文件以及 DWARF 调试信息。它最初是 FreeBSD 项目的一部分，但后来成为独立项目，以便与更广泛的开源社区协作。

在 FreeBSD 11 中，我们已迁移到 ELF Tool Chain 的 addr2line、c++filt、objcopy、nm、readelf、size、strip 和 strings 实现。libelf 和 libdwarf 库也来自 ELF Tool Chain。

ELF Tool Chain 还包含 FreeBSD 的 ar、brandelf 和 elfdump 工具的版本。如果它们将来获得引人注目的新特性或改进，我们将迁移到这些版本。

## 运行时库

工具链需要若干库来提供运行时支持。compiler-rt 库来自 LLVM 项目，包含若干组件。GCC 或 Clang 代码生成所需的低级目标特定钩子称为“builtins”。这些是执行编译器不会直接输出到对象代码中的操作的例程。

compiler-rt 包含 sanitizer 运行时，为 Clang 提供识别错误的软件行为的运行时支持。AddressSanitizer（asan）检测对堆、栈和全局变量的越界访问、释放后使用及相关错误，以及重复释放和无效释放。可通过在编译器命令行中添加 `-fsanitize=address` 来启用。

UndefinedBehaviourSanitizer（ubsan）捕获未定义行为，即语言未规定行为的操作。示例包括整数运算溢出（如加法和位移）、除以零以及使用未初始化的变量。命令行参数 `-fsanitize=undefined` 启用 ubsan。

Clang 在上游仓库中还包含其他 sanitizer，包括用于检测多线程应用程序数据竞争的 ThreadSanitizer 和用于检测未初始化读取的 MemorySanitizer。正在开展工作，使这些 sanitizer 在后续 FreeBSD 版本中随系统编译器可用。

对于 C++ 运行时支持，我们组合使用 PathScale 的 libcxxrt 来提供低级应用二进制接口（ABI）支持。这包括运行时类型信息（RTTI）、异常处理和线程安全的初始化器。C++ 标准库是 LLVM 的 libc++。

## 调试器

替代调试器同样来自 LLVM 项目：LLDB。与 LLVM 的其余部分一样，LLDB 作为一组可复用组件构建，并基于 LLVM 和 Clang 的其他部分。LLDB 可访问一个完整的 Clang 编译器，并将其用作表达式解析器。这为解释用户表达式提供了高保真度：LLDB 能够解析在被调试的原始源代码中有效的任何表达式。

FreeBSD 11 在 32 位和 64 位 ARM 架构以及 64 位 Intel（amd64）上包含 LLDB。

除基本系统中的 LLDB 外，GNU GDB 调试器可通过从 Ports 树构建或安装软件包来使用。它已更新，包含改进的线程支持和内核调试。通过简单的 `pkg install gdb` 命令即可使用 GDB 7.11.1。

## DTrace

FreeBSD 11 支持在用户空间中使用压缩类型格式（CTF）数据。这意味着当相应的可执行文件或库以 CTF 编译时，用户空间的函数边界跟踪（FBT）探针可以具有类型化参数。FreeBSD 基本系统构建基础设施支持通过 **/etc/src.conf** 文件中的设置以 CTF 编译。

FreeBSD 11 还在用户空间中新增对静态定义跟踪（STD）探针的支持。包含探针定义的 .d 文件可以包含在源文件列表中，构建基础设施会自动生成头文件，其中包含可在源文件中引用的探针宏。

## 未来工作

若干额外的工具链组件正在开发中，未来将在 FreeBSD 中可用。LLVM 提供代码覆盖工具 llvm-cov，它可以在类似于 GNU gcov 的模式下运行，并可与 Clang 基于插桩的性能分析配合使用。LLVM 还提供 OpenMP 运行时（libomp），这是一个用于共享内存多处理的应用编程接口（API）。

以 LLD 作为链接器后，GNU binutils 中仍剩两个工具：汇编器（as）和 objdump。目前没有替代 as 的候选。然而，在一级架构上构建 FreeBSD 基本系统实际上并不需要它：Clang 的集成汇编器用于构建汇编源文件。GNU as 可以直接移除，或者可以从集成汇编器构建与 GNU as 兼容的驱动。objdump 也不是基本系统构建所必需的，可以移除。LLVM 提供了 llvm-objdump，目前功能有限，但适时可能会成为可行的替代品。

FreeBSD 社区和上游 Clang/LLVM 项目正在持续推进，试图将 Clang、LLD 和 LLDB 套件带到仍在使用 GCC 的较低层级 FreeBSD 架构上。

***

**ED MASTE** 为 FreeBSD 基金会管理项目开发，并在剑桥大学计算机实验室担任工程支持职务。他也是选举产生的 FreeBSD Core Team 成员。除 FreeBSD 和 ELF Tool Chain 外，他还是 LLVM、QEMU 和 Open vSwitch 等其他若干开源项目的贡献者。他与妻子 Anna 和儿子 Pieter、Daniel 居住在加拿大基奇纳。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://freebsd-journal-cn.bsdcn.org/20160910-huan-ying-lai-dao-freebsd-11/freebsd-toolchain.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
