clang命令

978 阅读12分钟

前言

Clang是一个C,C++和Objective-C编译器,它包含了预处理、语法与词法分析、优化、中间代码生成、汇编和链接。根据传递的参数设置,Clang将会在停止之前做一个完整的链接。其可执行文件实际上是一个小的驱动程序,它控制其他工具(如编译器、汇编器和链接器)的整体执行。通常情况下,您不需要与驱动程序交互,但可以透明地使用它来运行其他工具。

编译的5个阶段

虽然Clang是高度集成的,但是它的编译其实是分5个阶段进行的。

1.预处理

这个阶段处理输入源文件的标记化、宏展开、#include展开和其他预处理器指令的处理。这一阶段的输出通常称为“”。i"(对于C), "。ii"(对于c++), "。mi”(用于Objective-C),或“。mii”(用于objective - c++)文件。

2.语法和词法分析

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

3.中间代码生成和优化

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

Clang还支持使用集成汇编器,其中代码生成器直接生成目标文件。这样就避免了生成.S文件和调用目标汇编程序。

4.汇编

此阶段运行目标汇编程序,将编译器的输出转换为目标对象文件。这一阶段的输出通常称为.O文件或“对象”文件。

5.链接

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

命令参数

1.编译阶段选项

1.1 指定编译阶段选项

  • -E 运行预处理器阶段
  • -fsyntax-only 运行预处理器、解析器和类型检测阶段
  • -S 运行预处理器、解析器和类型检测阶段、LLVM生成和优化阶段以及特定于目标的代码生成,生成一个程序集文件。
  • -c 运行上述所有阶段,再加上汇编,生成一个目标”.o "文件。

1.2 不指定编译阶段选项

如果不指定编译阶段选项参数,那么默认将会执行所有阶段,并运行链接器将结果组合到可执行库或共享库中。

2.语言选择和模式选项

  • -x <language> 将后面输入文件视为具有类型语言。

  • -std=<standard> 指定要编译的语言标准
    支持的c语言标准有如下:
    ISO C 1990: c89 c90 iso9899:1990
    ISO C 1990 with amendment 1: iso9899:199409
    ISO C 1990 with GNU extensions: gnu89gnu90
    ISO C 1999: c99iso9899:1999
    ISO C 1999 with GNU extensions: gnu99
    ISO C 2011: c11iso9899:2011
    ISO C 2011 with GNU extensions: gnu11
    ISO C 2017: c17iso9899:2017
    ISO C 2017 with GNU extensions: gnu17
    默认的C语言标准是gnu17,但在PS4上是gnu99
    支持的C++语言标准有如下:
    ISO C++ 1998 with amendments: c++98c++03
    ISO C++ 1998 with amendments and GNU extensions:gnu++98gnu++03
    ISO C++ 2011 with amendments:c++11\
    ISO C++ 2011 with amendments and GNU extensions:gnu++11
    ISO C++ 2014 with amendments:c++14\
    ISO C++ 2014 with amendments and GNU extensions:gnu++14
    ISO C++ 2017 with amendments:c++17
    ISO C++ 2017 with amendments and GNU extensions:gnu++17
    Working draft for ISO C++ 2020:c++2a
    Working draft for ISO C++ 2020 with GNU extensions:gnu++2a
    默认支持的OpenCL语言标准是: gnu++14.
    支持的OpenCL语言标准有如下:
    OpenCL 1.0:cl1.0
    OpenCL 1.1:cl1.1
    OpenCL 1.2:cl1.2
    OpenCL 2.0:cl2.0
    默认支持的OpenCL语言标准是: cl1.0

  • -stdlib=<library> 指定要使用的c++标准库;支持的选项有libstdc++和libc++。如果未指定,将使用平台默认值。

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

  • -ansi 指定c语言标准为**c89*O

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

  • -trigraphs 启动三字符组,在预处理阶段将三字符组替换为单字符,例如:??=替换为#

  • -ffreestanding 指示该文件为独立环境(而非投管环境)编译,这里假设独立环境将提供memcpymemmovememsetmemcmp的实现。因为很多程序都需要使用这些代码。

  • -fno-builtin 禁用内置函数的特殊处理和优化,例如strlen()和malloc函数。

  • -fmath-errno 指示数学函数应被视为更新 errno。

  • -fpascal-strings 启用pascal风格的字符串支持

  • -fms-extensions 启用对Microsoft扩展的支持

  • -fmsc-version 设置 _MSC_VER,在window上默认为1300,否则不设置

  • -fborland-extensions 启动对Borland扩展的支持

  • -fwriteable-strings 将所有字符串文本默认为可写的,这将禁用字符串唯一性和优化

  • -flax-vector-conversions,-flax-vector-conversions=<kind>,-fno-lax-vector-conversions 允许隐式向量转换使用松散的类型检查规则。
    <kind>可用的值:
    none:向量之间不允许隐式转换;
    integer:允许在整体位宽相同的整数向量之间隐式位转换;
    all:允许在具有相同整体位宽的任何向量之间隐式位转换;
    如果<kind>未指定,则默认为整数。

  • -fblocks 启用“Blocks”语言功能。

  • -fobjc-abi-version=version 选择Objective-C ABI版本, 有效可用版本为1 (旧式“脆弱”ABI) 2(非脆弱ABI 1),和3(非脆弱ABI 2);非脆弱 ABI 是指无需重新编译所有子类即可向类添加实例变量的能力。

  • -fobjc-nonfragile-abi-version=<version> 选择默认使用的Objective-C非脆弱ABI,只有当非脆弱ABI被启用时(-fobjc-nonfragile-abi),这个才能生效。

  • -fojbc-nonfragile-abi,-fno-objc-nonfragile-abi,分别是启动和禁止Objcitve-C 非脆弱ABI。

3.编译目标选项

Clang支持交叉编译,这是其设计的固有部分。根据您的Clang版本的配置方式,它可能支持许多交叉编译器,也可能只支持一个本机目标。

  • -arch <architecture> 指定编译目标架构
  • -mmacos-version-min=<version> 为macOS构建时,请指定应用程序支持的最低版本。
  • -miphoneos-version-min=<version> 为iPhone OS构建时,请指定应用程序支持的最低版本。
  • -print-supported-cpus, 打印给定目标(通过—target=<architecture>或-arch <architecture>指定)支持的处理器列表。如果未指定目标架构,则使用系统默认目标架构。
  • -march=? 生成可以使用架构?中可用指令的代码。
  • -mtune=? 针对微架构?进行优化,但不更改 ABI 或对可用指令做出假设。
  • -mcpu=? 同时指定 -march=?和-mtune=?,但可以被这两个选项覆盖。支持的值通常与-mtune=?相同。 体系结构名称是从?推断出来的

4.中间代码生成选项

  • -O0, -O1, -O2, -O3, -Ofast, -Os, -Oz, -Og, -O, -O4 指定要使用的优化级别:
    -O0 表示“无优化”:此级别编译速度最快,生成的编译代码最多(可执行文件最大)。
    -O1 介于-O0与-O2之间
    -O2 中等程度优化
    -O3 与-O2相似,不同之处在于它可以使程序执行越快但是代码更多一点。
    -Ofast 启用 -O3 中的所有优化以及其他可能违反严格遵守语言标准的激进优化。
    -Os 与-O2相似,但是额外优化了代码大小。
    -Oz 与-Os相似,但是进一步优化了代码大小
    -Og 与-O1相似,在未来的版本中,这个选项可能会禁用不同的优化,以提高可调试性。
    -O 等于-O1
    -O4 目前相当于-O3\

  • -g,-gline-tables-only,-gmodules 控制调试信息输出。注意,Clang调试信息在-O0时工作最好。如果指定了多个以-g开头的选项,最后一个优先:-g生成调试信息。
    -g 生成调试信息
    -gline-tables-only 只生成行表调试信息。这允许使用内联信息进行符号化回溯,但不包括关于变量、它们的位置或类型的任何信息。
    -gmodules 生成包含Clang模块或预编译头中定义的类型的外部引用的调试信息,而不是将冗余的调试类型信息发送到每个对象文件中。该选项透明地将Clang模块格式切换为对象文件容器,该对象文件容器将Clang模块与调试信息一起保存。当编译使用Clang模块或预编译头文件的程序时,该选项会生成完整的调试信息,编译时间更快,目标文件更小。
    在构建用于分发到其他机器的静态库时,不应使用此选项,因为调试信息将包含对构建库中的目标文件所在机器上的模块缓存的引用。

  • -fstandalone-debug -fno-standalone-debug Clang支持许多优化,以减少二进制文件中调试信息的大小。它们的工作基于调试类型信息可以分散到多个编译单元的假设。例如,Clang不会为模块不需要的类型发出类型定义,可以用前向声明替换。此外,Clang只会在包含该类虚表的模块中发出动态c++类的类型信息。
    -fstandalone-debug选项会关闭这些优化。这在使用不附带调试信息的第三方库时非常有用。这是Darwin默认设置。请注意,对于程序根本没有引用的类型,Clang永远不会发出类型信息。

  • -fexceptions 允许生成展开信息。这允许通过Clang编译的堆栈帧抛出异常。在x86-64中默认是开启的。

  • -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编译。

5.驱动选项

  • --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-stats,-save-stats=cwd,-save-stats=obj 将内部代码生成(LLVM)统计数据保存到当前目录(-save-stats/"-save-stats=cwd")或输出文件目录("-save-state=obj")中的一个文件中。
  • integrated-as,-no-integrated-as 分别用于启用和禁用集成汇编程序的使用。默认情况下,集成汇编程序是否打开取决于目标。
  • -time 对单个命令进行计时。
  • -ftime-report 打印每个编译阶段时许摘要。
  • -v 显示运行和使用详细信息

6.诊断选项

-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用户手册。

7.预处理选项

  • -D<macroname>=<value> 在预处理源文件之前,将隐式的#define添加到预定义缓冲区中。
  • U<macroname> 在预处理源文件之前,将隐式的#undef添加到预定义缓冲区中。
  • -include <filename> 将隐式 #include 添加到预定义缓冲区中,该缓冲区在预处理源文件之前读取。
  • -I<directory> 将指定的目录添加到包含文件的搜索路径。
  • -F<directory> 将指定的目录添加到框架包含文件的搜索路径中
  • -nostdinc 不要在标准系统目录或编译器内置目录中搜索包含文件。
  • -nostdlibinc 不要在标准系统目录中搜索包含文件,而是要搜索编译器内置的包含目录。
  • -nobuiltininc 不要在clang的内置目录中搜索包含文件。