clang - Clang C、C++ 和 Objective-C 编译器

概要

clang [选项] 文件名 …

描述

clang 是一个 C、C++ 和 Objective-C 编译器,它包含预处理、解析、优化、代码生成、汇编和链接。根据传递的高级模式设置,Clang 会在进行完整链接之前停止。虽然 Clang 是高度集成的,但了解编译的各个阶段对于理解如何调用它很重要。这些阶段是

驱动程序

clang 可执行文件实际上是一个小型驱动程序,它控制编译器、汇编器和链接器等其他工具的整体执行。通常您不需要与驱动程序交互,而是透明地使用它来运行其他工具。

预处理

此阶段处理输入源文件的标记化、宏扩展、#include 扩展以及其他预处理器指令的处理。此阶段的输出通常被称为 “.i”(对于 C)、“.ii”(对于 C++)、“.mi”(对于 Objective-C)或 “.mii”(对于 Objective-C++)文件。

解析和语义分析

此阶段解析输入文件,将预处理器标记转换为解析树。一旦以解析树的形式存在,它就会应用语义分析来计算表达式的类型,以及确定代码是否格式良好。此阶段负责生成大多数编译器警告以及解析错误。此阶段的输出是“抽象语法树”(AST)。

代码生成和优化

此阶段将 AST 转换为低级中间代码(称为“LLVM IR”),最终转换为机器代码。此阶段负责优化生成的代码以及处理特定于目标的代码生成。此阶段的输出通常被称为 “.s” 文件或“汇编”文件。

Clang 还支持使用集成汇编器,其中代码生成器直接生成目标文件。这避免了生成 “.s” 文件以及调用目标汇编器的开销。

汇编器

此阶段运行目标汇编器将编译器的输出转换为目标目标文件。此阶段的输出通常被称为 “.o” 文件或“目标”文件。

链接器

此阶段运行目标链接器将多个目标文件合并为可执行文件或动态库。此阶段的输出通常被称为“a.out”、“.dylib”或“.so”文件。

Clang 静态分析器

Clang 静态分析器是一个工具,它通过代码分析扫描源代码以尝试查找错误。该工具使用 Clang 的许多部分,并且内置在同一个驱动程序中。有关如何使用静态分析器的更多详细信息,请参见 <https://clang-analyzer.llvm.org>。

选项

阶段选择选项

-E

运行预处理阶段。

-fsyntax-only

运行预处理、解析和语义分析阶段。

-S

运行之前的阶段以及 LLVM 生成和优化阶段以及特定于目标的代码生成,生成汇编文件。

-c

运行上述所有操作,以及汇编器,生成目标 “.o” 对象文件。

no stage selection option

如果没有指定阶段选择选项,则会运行上述所有阶段,并运行链接器将结果组合成可执行文件或共享库。

语言选择和模式选项

-x <language>

将后续输入文件视为具有类型语言。

-std=<standard>

指定要编译的语言标准。

C 语言支持的值为

c89
c90
iso9899:1990

ISO C 1990

iso9899:199409

ISO C 1990 附加修订案 1

gnu89
gnu90

ISO C 1990 带有 GNU 扩展

c99
iso9899:1999

ISO C 1999

gnu99

ISO C 1999 带有 GNU 扩展

c11
iso9899:2011

ISO C 2011

gnu11

ISO C 2011 带有 GNU 扩展

c17
iso9899:2017

ISO C 2017

gnu17

ISO C 2017 带有 GNU 扩展

默认的 C 语言标准为 gnu17,但在 PS4 上,它为 gnu99

C++ 语言支持的值为

c++98
c++03

ISO C++ 1998 附加修订案

gnu++98
gnu++03

ISO C++ 1998 附加修订案和 GNU 扩展

c++11

ISO C++ 2011 附加修订案

gnu++11

ISO C++ 2011 附加修订案和 GNU 扩展

c++14

ISO C++ 2014 附加修订案

gnu++14

ISO C++ 2014 附加修订案和 GNU 扩展

c++17

ISO C++ 2017 附加修订案

gnu++17

ISO C++ 2017 附加修订案和 GNU 扩展

c++20

ISO C++ 2020 附加修订案

gnu++20

ISO C++ 2020 附加修订案和 GNU 扩展

c++23

ISO C++ 2023 附加修订案

gnu++23

ISO C++ 2023 附加修订案和 GNU 扩展

c++2c

C++2c 的工作草案

gnu++2c

C++2c 的工作草案,带有 GNU 扩展

默认的 C++ 语言标准为 gnu++17

OpenCL 语言支持的值为

cl1.0

OpenCL 1.0

cl1.1

OpenCL 1.1

cl1.2

OpenCL 1.2

cl2.0

OpenCL 2.0

默认的 OpenCL 语言标准为 cl1.0

CUDA 语言支持的值为

cuda

NVIDIA CUDA(tm)

-stdlib=<library>

指定要使用的 C++ 标准库;支持的选项是 libstdc++ 和 libc++。如果未指定,将使用平台默认值。

-rtlib=<library>

指定要使用的编译器运行时库;支持的选项是 libgcc 和 compiler-rt。如果未指定,将使用平台默认值。

-ansi

与 -std=c89 相同。

-ObjC, -ObjC++

将源输入文件分别视为 Objective-C 和 Object-C++ 输入。

-trigraphs

启用三字母词。

-ffreestanding

指示应为独立环境编译文件,而不是托管环境。请注意,假定独立环境将另外提供 memcpymemmovememsetmemcmp 实现,因为这些实现对于许多程序的有效代码生成是必需的。

-fno-builtin

禁用众所周知的库函数的特殊处理和优化,例如 strlen()malloc()

-fno-builtin-<function>

禁用特定库函数的特殊处理和优化。例如,-fno-builtin-strlen 删除对 strlen() 库函数的任何特殊处理。

-fno-builtin-std-<function>

禁用特定 C++ 标准库函数在命名空间 std 中的特殊处理和优化。例如,-fno-builtin-std-move_if_noexcept 删除对 std::move_if_noexcept() 库函数的任何特殊处理。

对于 C 标准库函数,C++ 标准库也在命名空间 std 中提供,请使用 -fno-builtin-<function> 而不是。

-fmath-errno

指示数学函数应被视为更新 errno

-fpascal-strings

启用对使用“\pfoo”的 Pascal 样式字符串的支持。

-fms-extensions

启用对 Microsoft 扩展的支持。

-fmsc-version=

设置 _MSC_VER。在 Windows 上,默认情况下,此值与当前安装的 cl.exe 版本相同,或为 1933。在其他情况下不设置。

-fborland-extensions

启用对 Borland 扩展的支持。

-fwritable-strings

使所有字符串文字默认可写。这将禁用字符串的唯一化和其他优化。

-flax-vector-conversions, -flax-vector-conversions=<kind>, -fno-lax-vector-conversions

允许对隐式向量转换使用宽松的类型检查规则。<kind> 的可能值

  • none: 不允许向量之间的隐式转换

  • integer: 允许相同总位宽的整数向量之间的隐式位转换

  • all: 允许相同总位宽的任何向量之间的隐式位转换

如果未指定,<kind> 默认设置为 integer

-fblocks

启用“块”语言特性。

-fobjc-abi-version=version

选择要使用的 Objective-C ABI 版本。可用的版本是 1(传统“脆弱”ABI)、2(非脆弱 ABI 1)和 3(非脆弱 ABI 2)。

-fobjc-nonfragile-abi-version=<version>

选择默认要使用的 Objective-C 非脆弱 ABI 版本。只有在启用非脆弱 ABI 时(通过 -fobjc-nonfragile-abi,或者因为它是在平台上默认启用的),才会将其用作 Objective-C ABI。

-fobjc-nonfragile-abi, -fno-objc-nonfragile-abi

启用使用 Objective-C 非脆弱 ABI。在将其作为默认 ABI 的平台上,可以使用 -fno-objc-nonfragile-abi 禁用它。

目标选择选项

Clang 完全支持交叉编译,这是其设计中固有的部分。根据 Clang 版本的配置方式,它可能支持多个交叉编译器,或者可能只支持本地目标。

-arch <architecture>

指定要为其构建的体系结构(Mac OS X 特定)。

-target <architecture>

指定要为其构建的体系结构(所有平台)。

-mmacos-version-min=<version>

在为 macOS 构建时,指定应用程序支持的最低版本。

-miphoneos-version-min

在为 iPhone OS 构建时,指定应用程序支持的最低版本。

--print-supported-cpus

打印给定目标支持的处理器列表(通过 --target=<architecture>-arch <architecture> 指定)。如果没有指定目标,则将使用系统默认目标。

-mcpu=?, -mtune=?

充当 --print-supported-cpus 的别名。

-mcpu=help, -mtune=help

充当 --print-supported-cpus 的别名。

-march=<cpu>

指定 Clang 应该为特定处理器家族成员及其更高版本生成代码。例如,如果您指定 -march=i486,则编译器被允许生成在 i486 及更高版本的处理器上有效的指令,但这些指令可能在更早的版本上不存在。

--print-enabled-extensions

打印为由 –target-march-mcpu 值组合指定的 target 启用的扩展列表。目前,此选项仅在 AArch64 和 RISC-V 上支持。在 RISC-V 上,此选项还会打印出已启用扩展的 ISA 字符串。

--print-supported-extensions

打印对架构的每个 CPU 目标支持的所有扩展列表(通过 --target=<architecture>-arch <architecture> 指定)。如果没有指定目标,则将使用系统默认目标。目前,此选项仅在 AArch64 和 RISC-V 上支持。

代码生成选项

-O0, -O1, -O2, -O3, -Ofast, -Os, -Oz, -Og, -O, -O4

指定要使用的优化级别

-O0 表示“无优化”:此级别编译速度最快,并生成最易于调试的代码。

-O1 介于 -O0-O2 之间。

-O2 中等的优化级别,它启用了大多数优化。

-O3-O2 相似,但它还启用了执行时间更长或可能生成更大代码的优化(试图使程序运行得更快)。

-Ofast 启用来自 -O3 的所有优化,以及可能违反语言标准严格合规性的其他激进优化。这在 Clang 19 中已弃用,并发出警告,建议使用 -O3 结合 -ffast-math,如果需要非标准数学行为。目前还没有移除时间表;目的是阻止使用 -Ofast,因为优化标志的意外行为会导致正确代码的可观察行为发生变化。

-Os 类似于 -O2,但增加了优化以减小代码大小。

-Oz 类似于 -Os(以及 -O2),但进一步减小了代码大小。

-Og 类似于 -O1。在未来的版本中,此选项可能会禁用不同的优化以提高可调试性。

-O 等效于 -O1.

-O4 及更高版本

目前等效于 -O3

-g, -gline-tables-only, -gmodules

控制调试信息输出。请注意,Clang 调试信息在 -O0 下效果最佳。当指定多个以 -g 开头的选项时,最后一个选项将生效。

-g 生成调试信息。

-gline-tables-only 只生成行表调试信息。这允许使用内联信息对回溯进行符号化,但不会包含有关变量、其位置或类型的任何信息。

-gmodules 生成包含对 Clang 模块或预编译头文件中定义的类型的外部引用的调试信息,而不是将冗余的调试类型信息发射到每个目标文件中。此选项会将 Clang 模块格式透明地切换到包含 Clang 模块和调试信息的.o 文件容器。在编译使用 Clang 模块或预编译头的程序时,此选项会生成完整的调试信息,编译速度更快,目标文件也更小。

在构建用于分发到其他机器的静态库时不应使用此选项,因为调试信息将包含对库中目标文件构建所在机器上的模块缓存的引用。

-fstandalone-debug -fno-standalone-debug

Clang 支持许多优化以减小二进制文件中调试信息的大小。它们基于以下假设:调试类型信息可以分布在多个编译单元中。例如,Clang 不会为模块不需要的类型发射类型定义,而是可以用前向声明替换它们。此外,Clang 只会为包含类 vtable 的模块中的动态 C++ 类发射类型信息。

-fstandalone-debug 选项会关闭这些优化。当使用没有调试信息的第三方库时,这很有用。这是 Darwin 上的默认值。请注意,Clang 永远不会为程序根本不引用的类型发射类型信息。

-feliminate-unused-debug-types

默认情况下,Clang 不会为程序中定义但未使用过的类型发射类型信息。要保留这些未使用的类型的调试信息,可以使用否定选项 -fno-eliminate-unused-debug-types

-fexceptions

允许异常通过 Clang 编译的堆栈帧抛出(在许多目标上,这将为可能抛出异常的函数启用展开信息)。对于大多数目标,C++ 默认情况下启用此选项。

-ftrapv

生成代码以捕获整数溢出错误。有符号整数溢出在 C 中是未定义的。使用此标志,将生成额外的代码来检测此情况并在发生时中止。

-fvisibility

此标志设置默认可见性级别。

-fcommon, -fno-common

此标志指定没有初始化器的变量获得公共链接。可以使用 -fno-common 禁用此选项。

-ftls-model=<model>

将用于线程局部变量的默认线程局部存储 (TLS) 模型设置为使用。有效值为:“global-dynamic”、“local-dynamic”、“initial-exec” 和 “local-exec”。默认值为 “global-dynamic”。可以使用 tls_model 属性覆盖默认模型。如果可能,编译器将尝试选择更有效的模型。

-flto, -flto=full, -flto=thin, -emit-llvm

生成适合链接时优化的 LLVM 格式的输出文件。当与 -S 一起使用时,这会生成 LLVM 中间语言汇编文件,否则这会生成 LLVM 位码格式的目标文件(这些文件可能会根据阶段选择选项传递给链接器)。

-flto 的默认值为 “full”,其中 LLVM 位码适合于单片链接时优化 (LTO),链接器将所有此类模块合并成一个组合模块以进行优化。使用 “thin” 时,将改为调用 ThinLTO 编译。

注意

在 Darwin 上,当使用 -flto 以及 -g 并在单独的步骤中进行编译和链接时,您还需要在链接步骤中传递 -Wl,-object_path_lto,<lto-filename>.o 以指示 ld64 链接器不要删除在链接时优化期间生成的临时目标文件(如果编译和链接在单个步骤中完成,Clang 会自动将此标志传递给链接器)。这允许调试可执行文件以及使用 dsymutil(1) 生成 .dSYM 捆绑包。

驱动程序选项

-###

打印(但不运行)要为此次编译运行的命令。

--help

显示可用选项。

-Qunused-arguments

对于未使用的驱动程序参数不发出任何警告。

-Wa,<args>

将 args 中以逗号分隔的参数传递给汇编器。

-Wl,<args>

将 args 中以逗号分隔的参数传递给链接器。

-Wp,<args>

将 args 中以逗号分隔的参数传递给预处理器。

-Xanalyzer <arg>

将 arg 传递给静态分析器。

-Xassembler <arg>

将 arg 传递给汇编器。

-Xlinker <arg>

将 arg 传递给链接器。

-Xpreprocessor <arg>

将 arg 传递给预处理器。

-o <file>

将输出写入文件。

-print-file-name=<file>

打印文件的完整库路径。

-print-libgcc-file-name

打印当前使用的编译器运行时库(“libgcc.a”或“libclang_rt.builtins.*.a”)的库路径。

-print-prog-name=<name>

打印 name 的完整程序路径。

-print-search-dirs

打印用于查找库和程序的路径。

-save-temps

保存中间编译结果。

-save-stats, -save-stats=cwd, -save-stats=obj

将内部代码生成(LLVM)统计信息保存到当前目录中的文件(-save-stats/”-save-stats=cwd”)或输出文件目录(“-save-state=obj”)。

您也可以使用环境变量来控制统计信息的报告。将 CC_PRINT_INTERNAL_STAT 设置为 1 将启用此功能,报告以 JSON 格式输出到 stdout。

CC_PRINT_INTERNAL_STAT_FILE 设置为文件路径将使其以 JSON 格式将统计信息报告到给定文件。

注意,-save-stats 优先于 CC_PRINT_INTERNAL_STATCC_PRINT_INTERNAL_STAT_FILE

-integrated-as, -no-integrated-as

分别用于启用和禁用集成汇编器的使用。集成汇编器默认是否开启取决于目标。

-time

计时单个命令。

-ftime-report

打印每个编译阶段的计时摘要。

-v

显示要运行的命令并使用详细输出。

诊断选项

-fshow-column, -fshow-source-location, -fcaret-diagnostics, -fdiagnostics-fixit-info, -fdiagnostics-parseable-fixits, -fdiagnostics-print-source-range-info, -fprint-source-range-info, -fdiagnostics-show-option, -fmessage-length

这些选项控制 Clang 如何打印有关诊断(错误和警告)的信息。有关更多信息,请参阅 Clang 用户手册。

预处理器选项

-D<macroname>=<value>

在预处理源文件之前读取的预定义缓冲区中添加一个隐式 #define。

-U<macroname>

在预处理源文件之前读取的预定义缓冲区中添加一个隐式 #undef。

-include <filename>

在预处理源文件之前读取的预定义缓冲区中添加一个隐式 #include。

-I<directory>

将指定的目录添加到包含文件的搜索路径。

-F<directory>

将指定的目录添加到框架包含文件的搜索路径。

-nostdinc

不要搜索标准系统目录或编译器内置目录以查找包含文件。

-nostdlibinc

不要搜索标准系统目录以查找包含文件,但要搜索编译器内置包含目录。

-nobuiltininc

不要搜索 clang 的内置目录以查找包含文件。

-nostdinc++

不要搜索系统 C++ 标准库目录以查找包含文件。

-fkeep-system-includes

仅与 -E 一起使用。不要将“系统”头文件的预处理内容复制到输出;相反,保留 #include 指令。这可以大大减少 -E 生成的文本量,这在尝试生成“小”的可重现测试用例时很有用。

但是,此选项不能保证可重现性。如果包含的源代码定义了影响系统头文件行为的预处理器符号(例如,_XOPEN_SOURCE),-E 的操作将删除该定义,从而可能改变包含头文件的语义。此外,使用不同版本的系统头文件(尤其是不同版本的 STL)可能会导致不同的行为。始终通过单独编译预处理文件来验证它。

环境

TMPDIR, TEMP, TMP

这些环境变量按顺序检查,用于查找在编译过程中使用的临时文件的写入位置。

CPATH

如果存在此环境变量,则将其视为一个分隔的路径列表,这些路径将添加到默认系统包含路径列表中。分隔符是平台相关的分隔符,与 PATH 环境变量中使用的分隔符相同。

环境变量中的空组件将被忽略。

C_INCLUDE_PATH, OBJC_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJCPLUS_INCLUDE_PATH

这些环境变量指定了额外的路径,与 CPATH 相同,这些路径仅在处理适当的语言时使用。

MACOSX_DEPLOYMENT_TARGET

如果未指定 -mmacos-version-min,则默认部署目标将从此环境变量中读取。此选项仅影响 Darwin 目标。

错误

如需报告错误,请访问 <https://github.com/llvm/llvm-project/issues/>。大多数错误报告应包含预处理源文件(使用 -E 选项)和编译器的完整输出,以及用于重现错误的信息。

参见

as(1), ld(1)