跳过正文

GCC 编译器 - 个人参考手册

Gnu Gcc Manual
目录
gnu-toolchain - 这篇文章属于一个选集。
§ 2: 本文

gcc 编译器个人参考手册。

GCC 代表 “GNU Compiler Collection”, 支持 C, C++, Objective-C, Objective-C++, Fortran, Ada, D 和 Go 语言。

GCC 语言无关的实现,如优化,以及为各种处理器生成机器码,称为 “back ends” ,GCC 语言相关的实现称为 “front end”。

调用 gcc 的三种方式(后两种方式一般用于交叉编译场景):

  1. gcc
  2. machine-gcc:如 x86_64-linux-gnu-gcc;
  3. machine-gcc-version:如 x86_64-linux-gnu-gcc-13;

阶段性编译:

  1. gcc -E file.c > file.i Preprocesses the source code.
  2. gcc -S file.i -o file.S Compiles preprocessed source to assembly code.
  3. gcc -c file.S -o file.o Assembles code into an object file,不进行链接
  4. gcc file.o -o file Links object files into an executable.

可以直接使用 gcc 完成编译预处理、汇编和链接,所以一般不需要手动调用 cpp、as、ld 命令。

GCC 参数
#

GCC 14 参数索引:Option-Index

gcc -v 显示 gcc 支持的 CPU 架构(Target)和编译 gcc 时的配置参数:

  • --build, --host, --target 分别指定编译 gcc 的 CPU 架构类型;
# ubunut 版本 gcc
alizj@ubuntu:~$ gcc -v
...
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=aarch64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-offload-targets=nvptx-none=/build/gcc-13-Nz4ro4/gcc-13-13.3.0/debian/tmp-nvptx/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=aarch64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04)

编译时加 -v 会打印详细的编译命令,同时也可以通过 -W 来为调用的其它命令添加 -v 参数::

  • -Wp,-v: 编译预处理详细参数;
  • -v:编译详情, cc1 编译器的执行详情
  • -Wa,-v: 汇编详情: 显示调用的 as 命令参数;
  • -Wl,-v: 链接详情,显示 collect2 调用 ld 的详情;

-v 和 –help 连用时除了打印 gcc 自身参数外,还打印它调用的命令,如 cpp、ld 的参数。

alizj@ubuntu:/Users/alizj/docs/lang/c$ gcc -g -v -Wp,-v -Wa,-v -Wl,-v array.c
Using built-in specs.
COLLECT_AS_OPTIONS='-v'
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/aarch64-linux-gnu/13/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=aarch64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-offload-targets=nvptx-none=/build/gcc-13-Nz4ro4/gcc-13-13.3.0/debian/tmp-nvptx/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=aarch64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04)

# cc1 是 cpp 包提供的预处理器
COLLECT_GCC_OPTIONS='-g' '-v' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a-'
 /usr/libexec/gcc/aarch64-linux-gnu/13/cc1 -quiet -v -imultiarch aarch64-linux-gnu -v array.c -quiet -dumpdir a- -dumpbase array.c -dumpbase-ext .c -mlittle-endian -mabi=lp64 -g -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -o /tmp/ccvkgXuK.s
GNU C17 (Ubuntu 13.3.0-6ubuntu2~24.04) version 13.3.0 (aarch64-linux-gnu)
	compiled by GNU C version 13.3.0, GMP version 6.3.0, MPFR version 4.2.1, MPC version 1.3.1, isl version isl-0.26-GMP
## cc1 内置编译预处理搜索头文件目录
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/aarch64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/aarch64-linux-gnu/13/include-fixed/aarch64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/aarch64-linux-gnu/13/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/aarch64-linux-gnu/13/include
 /usr/local/include
 /usr/include/aarch64-linux-gnu
 /usr/include
End of search list.

# 汇编 as 命令参数
COLLECT_GCC_OPTIONS='-g' '-v' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a-'
 as -v --gdwarf-5 -EL -mabi=lp64 -v -o /tmp/cc0XD2tu.o /tmp/ccvkgXuK.s

# 链接 wrapper collect2 的命令行参数,内部调用 ld
GNU assembler version 2.42 (aarch64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.42
COMPILER_PATH=/usr/libexec/gcc/aarch64-linux-gnu/13/:/usr/libexec/gcc/aarch64-linux-gnu/13/:/usr/libexec/gcc/aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../lib/:/lib/aarch64-linux-gnu/:/lib/../lib/:/usr/lib/aarch64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-g' '-v' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a.'
 /usr/libexec/gcc/aarch64-linux-gnu/13/collect2 -plugin /usr/libexec/gcc/aarch64-linux-gnu/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/aarch64-linux-gnu/13/lto-wrapper -plugin-opt=-fresolution=/tmp/ccZXDhqQ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu --as-needed -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -EL -maarch64linux --fix-cortex-a53-843419 -pie -z now -z relro /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/Scrt1.o /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crti.o /usr/lib/gcc/aarch64-linux-gnu/13/crtbeginS.o -L/usr/lib/gcc/aarch64-linux-gnu/13 -L/usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu -L/usr/lib/gcc/aarch64-linux-gnu/13/../../../../lib -L/lib/aarch64-linux-gnu -L/lib/../lib -L/usr/lib/aarch64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/aarch64-linux-gnu/13/../../.. -v /tmp/cc0XD2tu.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/aarch64-linux-gnu/13/crtendS.o /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crtn.o
collect2 version 13.3.0

# collect 2 调用的 ld 命令
/usr/bin/ld -plugin /usr/libexec/gcc/aarch64-linux-gnu/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/aarch64-linux-gnu/13/lto-wrapper -plugin-opt=-fresolution=/tmp/ccZXDhqQ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu --as-needed -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -EL -maarch64linux --fix-cortex-a53-843419 -pie -z now -z relro /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/Scrt1.o /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crti.o /usr/lib/gcc/aarch64-linux-gnu/13/crtbeginS.o -L/usr/lib/gcc/aarch64-linux-gnu/13 -L/usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu -L/usr/lib/gcc/aarch64-linux-gnu/13/../../../../lib -L/lib/aarch64-linux-gnu -L/lib/../lib -L/usr/lib/aarch64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/aarch64-linux-gnu/13/../../.. -v /tmp/cc0XD2tu.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/aarch64-linux-gnu/13/crtendS.o /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crtn.o
GNU ld (GNU Binutils for Ubuntu) 2.42
COLLECT_GCC_OPTIONS='-g' '-v' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a.'

C 版本
#

-std:指定 C 语言版本: c90 c89 c99 c11 c17 c18 c23,gnu89 gnu90 gnu11 gnu17 gnu18 gnu23;

未指定 -std 参数时,clang 使用 C99 标准,gcc 使用 gnu17 标准,Linux kernel 使用 gnu11 标准。

如果只使用 C 标准特性,可以在指定 c99/c23 等 C 标准的同时,指定 -pedantic 或 -pedantic-errors 参数,这时 GNU 扩展或 GCC builtin 函数将不能再使用,使用 GNU C 扩展时将发送警告或出错。

-ansi 等效于 -std=c90 或 -std=c++98,它关闭了 GNU C 扩展, 只使用 ISO C 标准特性,如 asm/extension/inline/typeof 等关键字不可用, 但是编译器内置的带有前后下划线的名称可用, 如 __asm__/__extension__/__inline__/__typeof__

参考: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Standards.html

调试
#

示例:

# Includes debugging information in the executable.
gcc -g file.c -o file
# Includes extensive debugging information with optimizations.
gcc -g3 file.c -o file
# Disables stack protection mechanisms.
gcc -fno-stack-protector file.c
# Prints compilation commands and version information.
gcc -v file.c
# Omits the frame pointer in the generated code.
gcc -fomit-frame-pointer file.c

# Strips symbol table and debugging info from the executable.
gcc -s file.c -o file
# Includes debugging information in the executable.
gcc -g file.c -o file

开启了 -g 或 -ggdb 选项后, 才在 ELF 文件中包含调试信息,后续 gdb 使用该信息进行调试。

调试信息和符号表不是一回事, 符号表是默认都会带的, 除非后续用 strip 命令来删除。

  • -g: Generate source-level debug information. Produce debugging information in the operating system’s native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information.

  • -ggdb:生成 gdb 使用的调试信息,自动选择格式(如 DWARF);

  • -gdwarf,-gdwarf-{version}, version 可以是 version may be either 2, 3, 4 or 5,对于 linux 默认是 5, Version 5 requires GDB 8.0 or higher.

  • -gbtf Request BTF debug information. BTF is the default debugging format for the eBPF target.

  • -glevel:request debugging information and also use level to specify how much information. The default level is 2. 特殊的 g0 表示 produces no debug information at all. Thus, -g0 negates -g.

优化
#

示例:

# Disables optimizations for easier debugging.
gcc -O0 file.c -o file
# Enables basic optimizations.
gcc -O1 file.c -o file
# Optimizes code for speed.
gcc -O2 file.c -o file
# Aggressively optimizes code for speed.
gcc -O3 file.c -o file
# Optimizes code for size.
gcc -Os file.c -o file
# Generates code for profile-guided optimization.
gcc -fprofile-generate file.c -o file
# Uses profiling data to optimize the code.
gcc -fprofile-use file.c -o file_optimized

默认不开启优化,等效于-O0,优化级别:

  • -O0 Reduce compilation time and make debugging produce the expected results. This is the default.
  • -O1:Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large function.
  • -O2 Optimize even more. GCC performs nearly all supported optimizations that do not involve a space‐speed tradeoff.
  • -O3 Optimize yet more. -O3 turns on all optimizations specified by -O2 and also turns on the following optimization flags
  • -Os Optimize for size. -Os enables all -O2 optimizations except those that often increase code size:
  • -Ofast Disregard strict standards compliance. -Ofast enables all -O3 optimizations.
  • -Og Optimize debugging experience.
  • -Oz Optimize aggressively for size rather than speed.

只要开启了优化,默认就会开启 -fomit-frame-pointer, 如果要明确支持 FP 则需要添加参数: -fno-omit-frame-pointer

另外一个和 stack unwiding 相关的参数是 --enable-frame-pointer

警告
#

示例:

# Enables all commonly used compiler warnings.
gcc -Wall file.c
# Treats all compiler warnings as errors.
gcc -Werror file.c

良好的开发习惯是在编译时指定如下参数: -std=c23 -Wall -Wextra -Wpedantic

只检查语法,不做其它处理:

  • -fsyntax-only: Check the code for syntax errors, but don’t do anything beyond that.

只使用 ISO C/C++ 规范定义(使用 -std 来指定版本,如 -std=gnu99 -Wpedantic),警告或拒绝 GNU C 等语言扩展。

  • -Wpedantic : 使用语言扩展时警告。但对于双下划线开头的扩展,如 __inline__/__asm__ 等不告警。
  • -pedantic : 拒绝所有语言扩展(编译出错)。
  • -pedantic-errors

警告:

  • -Wdeprecated : Enable warnings for deprecated constructs and define __DEPRECATED
  • -W<warning> : Enable the specified warning
    • -Wall : This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros
    • -Wextra : This enables some extra warning flags that are not enabled by -Wall
    • -Werror : Make all warnings into errors.
    • -Werror=* : Make the specified warning into an error
    • -Wfatal-errors : This option causes the compiler to abort compilation on the first error occurred rather than trying to keep going and printing further error messages.
  • -w : Suppress all warnings

profiling
#

  • -pg Generate extra code to write profile information suitable for the analysis program prof (for -p) or gprof (for -pg).
  • -p: Generate extra code to write profile information suitable for the analysis program prof (for -p) or gprof (for -pg).
  • -fprofile-arcs
  • –coverage -ftest-coverage: This option is used to compile and link code instrumented for coverage analysis.
$ gcc -Wall -c -pg collatz.c
$ gcc -Wall -pg collatz.o

$ gprof a.out
Flat profile:
Each sample counts as 0.01 seconds.
% cumul. self self total
time seconds seconds calls us/call us/call name
68.59 2.14 2.14 62135400 0.03 0.03 step
31.09 3.11 0.97 499999 1.94 6.22 nseq
0.32 3.12 0.01 main

$ gcc -Wall -fprofile-arcs -ftest-coverage cov.c
$ gcov cov.c
88.89% of 9 source lines executed in file cov.c
Creating cov.c.gcov

预处理
#

示例:

# Adds a directory to the list of include file search paths.
gcc -I /path/to/include file.c -o file

# Defines a macro for use in the source code.
gcc -DMACRO file.c

# Generates Makefile dependencies for the source file.
gcc -MM file.c

cpp 包提供了 cc1 命令,gcc 调用它来执行预处理(gcc -E),单独的 cpp 程序是为了兼容性。

  • /usr/libexec/gcc/aarch64-linux-gnu/13/cc1

只运行预处理:-E: Only run the preprocessor 使用 GCC 内建的预处理器

指定传给预处理器程序 cpp 的参数:

  • -Xpreprocessor ; Pass to the preprocessor
  • -Wp,; Pass the comma separated arguments in to the preprocessor

指定预处理器查找头文件时的目录:

  • -I Add directory to the end of the list of include search paths
  • -iquote Add directory to QUOTE include search path
  • -isystem Add directory to SYSTEM include search path
  • -isystem-after Add directory to end of the SYSTEM include search path
  • -idirafter Add directory to AFTER include search path
  • -isysroot : 默认为 /, 指定查找系统 glibc 标准库头文件的根目录,如 <directory>/usr/include
    • 可以通过编译器的 –sysroot 参数指定。
  • -iwithprefix dir -iwithprefixbefore dir

If begins with ‘=’ or $SYSROOT, then the ‘=’ or $SYSROOT is replaced by the sysroot prefix; see –sysroot and -isysroot.

-iquote 只适用于 #include “header.h” 的查找。其它适用于两种类型的头文件查找。

定义 macro 常量,在所有源文件中生效:

  • -D name: 定义 macro name, 值默认为 1;
  • -D =:Define to (or 1 if omitted)

撤销以前定义的 macro name,等效于在头文件中使用 #undef name :

  • -U name: Cancel any previous definition of name, either built in or provided with a -D option.

在所有源文件前添加指定的 file,例如 -include stdio.h : 等效为在源文件前添加了 #incldue <stdio.h> 指令:

  • -include file: Process file as if #include “file” appeared as the first line of the primary source file.

-pthread: Define additional macros required for using the POSIX threads library.

编译
#

-S: 编译后不执行汇编,输出的文件名后缀是 .s,内容是汇编代码;

$ gcc -Wall -S hello.i

$ cat hello.s
    .file "hello.c"
    .section .rodata
.LC0:
    .string "Hello, world!\n"
    .text
.globl main
    .type main, @function
main:
    pushl %ebp
    movl %esp, %ebp
    subl $8, %esp
    andl $-16, %esp
    movl $0, %eax
    subl %eax, %esp
    movl $.LC0, (%esp)
    call printf
    movl $0, %eax
    leave
    ret
    .size main, .-main
    .ident "GCC: (GNU) 3.3.1"

编译是从 C 源文件生成汇编文件(.s) 的过程。

架构相关
#

示例:

# Compiles code for a 32-bit architecture.
gcc -m32 file.c
# Compiles code for a 64-bit architecture.
gcc -m64 file.c
# Optimizes code for the build machine's CPU architecture.
gcc -march=native file.c -o file
# Enables AVX instructions in the generated code.
gcc -mavx file.c -o file
# Uses x87 FPU registers instead of SSE instructions.
gcc -mno-sse file.c

通用选项:

  • -mabi=abi # 默认lp64,其它:ilp32
  • -mcpu=processor[+extension…] # 例如 cortex-a710
  • -march=architecture[+extension…] # 例如 armv9.5-a 或 armv9.4-a, cpa, lut, faminmax 或 -march=i686+sse4+vmx

aarch64 选项: -mbig-endian -mlittle-endian

汇编
#

汇编: 从汇编源文件(.s)生成对象文件(ELF 格式的 .o 文件)的过程;

gcc 调用 binutil 包提供的汇编器命令 as。

-c: Only run preprocess, compile, and assemble steps 只运行预处理、编译和汇编,不进行链接,结果是 object 文件;

$ gcc -v -Wall array.c
...
COLLECT_GCC_OPTIONS='-v' '-Wall' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a-'
 as -v -EL -mabi=lp64 -o /tmp/ccbzmPYo.o /tmp/ccUcSjmL.s
GNU assembler version 2.42 (aarch64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.42

指定传给汇编器的参数:

  • -Wa, Pass the comma separated arguments in to the assembler
  • -Xassembler Pass to the assembler

指定传给 clang 编译器的参数:

  • -Xclang Pass to clang -cc1
  • –target= Generate code for the given target

clang 编译器支持交叉编译,通过 –target 传递目标架构的类型。但是 gcc 一般不支持交叉编译,需要指定特定前缀的 gcc 工具链,如 aarch64-linux-gnu-gcc.

编译生成位置无关代码和可执行程序:

  • -fpic -fPIC
  • -fpie -fPIE

链接
#

示例:

# Links the executable with the specified shared library.
gcc file.c -o file -lcppfile
# Links the static library into an executable.
gcc -o res main.c libhello.a
# Prints the full path of the specified library.
gcc -print-file-name=libc.so
# Adds a directory to the list of library search paths.
gcc -L /path/to/lib file.c -o file -lmylib
# Links all object files from the specified archive.
gcc -o file -Wl,--whole-archive lib.a -Wl,--no-whole-archive other.o

当指定以下参数时将不执行链接: -c(编译)/-S(汇编)/-E(预处理)

指定使用的链接器类型(默认为 bfd,gold 为较新的 ELF only 链接器但因缺乏维护,新版本的 binutils 已经去掉了):

  • -fuse-ld=bfd
  • -fuse-ld=gold
  • -fuse-ld=lld
  • -fuse-ld=mold

链接的库或目录:

  • -L Add directory to library search path
  • -llibrary:链接 liblibrary.a 或 liblibrary.so, 如果两个都存在, 优先动态库, 除非指定 -static
  • -o Write output to

glibc 头文件和库文件根目录:

  • –sysroot= Use as the root directory for headers

常见的使用 –sysroot 的常见是交叉编译,它指定 gcc 链接可执行程序使用的系统 glibc 库和头文件的根目录,例如在 fedora 40 x86_64 架构上交叉编译 aarch64 架构二进制,需要单独安装 aarch64 架构的 glibc 头文件和静态库:

  • 指定的 –sysroot 参数会传给编译预处理的参数 -isysroot

传递给链接器的参数:

  • -Wl, Pass the comma separated arguments in to the linker

  • -Xlinker Pass to the linker

  • -z Pass -z to the linker

  • -pie: Produce a dynamically linked position independent executable on targets that support it。一般需要和 -fpie 或 -fPIE 连用

  • -pthread:链接 POSIX thread

  • -r -rdynamic

  • -s : Remove all symbol table and relocation information from the executable. 移除符号表+debug_XX 调试符号表

  • -S: 移除调试符号表

  • -static -static-pie -static-libgcc -static-libstdc++ 静态链接。

  • -shared -shared-libgcc -symbolic 动态链接(默认优先),需要和 -fpic 或 -fPIC 连用。

  • -nostartfiles -nodefaultlibs -nolibc

  • -nostdlib -nostdlib++ 这些选项告诉 gcc 在链接时不要使用标准库(如 glic) 和 gcc 提供的 C 程序启动文件(如 crt0.o),即不自动链接 C 库和其它启动代码。一般用于嵌入式开发、内核开发或自定义运行环境。

  • 例如嵌入式系统的 bare metal 工具链 riscv64-unkonwn-elf-gcc 不需要链接 gcc 和 C 标准库,这时一般需要使用 -T 来指定自定义链接脚本,其中包含程序的执行入口 entry。

https://img.opsnull.com/blog/20250201221143138-gcc-qemu.png

  • -e entry –entry=entry

  • -u symbol -z keyword

移除符号表:

  • -s: Remove all symbol table and relocation information from the executable.

指定链接脚本:

  • -T script: Use script as the linker script

添加运行时动态链接库搜索路径到二进制中:

  • 在构建(链接阶段)时,通过 -rpath 参数指定动态库搜索路径(写入到了可执行文件 ELF .dynamic 段的 DT_RPATH 或 DT_RUNPATH,通过 readelf -d 可查询)。

静态和动态库
#

# Compiles source to object file.
gcc -c hello.c -o hello.o
# Creates a static library from object file.
ar -cvq libhello.a hello.o

# Generates position-independent code for shared libraries.
gcc -c -fPIC -o hello.o hello.c
# Creates a shared library from object file.
gcc -shared -o libhello.so hello.o

# Links the executable with a shared or static library.
gcc -o res main.c -L. -lhello

开发者选项
#

示例:

gcc -dumpversion 	Prints the GCC version.
gcc -dM -E - < /dev/null 	Prints all predefined macros.
gcc -Q --help=target 	Lists all target-specific options.
gcc -Q --help=optimizers 	Lists all optimization options.

gcc -no-pie file.c 	Disables position-independent executables.
gcc -nostdinc file.c 	Does not search standard include directories.
gcc -fdump-tree-all hello.c 	Dumps abstract syntax tree information.
gcc test.c -o test -Wa,-adhln=test.s -g -fverbose-asm -masm=intel 	Generates assembly with embedded source code lines.

-dletters -dumpspecs -dumpmachine -dumpversion -dumpfullversion -fcallgraph-info[=su,da]

-fdump-lang-all -fdump-lang-switch -fdump-lang-switch-options

-print-file-name=library -print-libgcc-file-name -print-multi-directory -print-multi-lib -print-multi-os-directory -print-prog-name=program -print-search-dirs -Q -print-sysroot -print-sysroot-headers-suffix

❯ gcc-14  -dumpmachine
aarch64-apple-darwin24

❯ gcc-14  -dumpversion
14

❯ gcc-14  -fdump-lang-all
gcc-14: fatal error: no input files
compilation terminated.

❯ gcc-14 -print-sysroot
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

❯ ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/
bin/  include/  lib/  libexec/  share/

❯ ls  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/std*.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stddef.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h

❯ ls -l /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/lib[cm].tbd
lrwxr-xr-x 1 root 13 Dec 13 15:21 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libc.tbd -> libSystem.tbd
lrwxr-xr-x 1 root 13 Dec 13 15:21 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libm.tbd -> libSystem.tbd

环境变量
#

GCC 使用的环境变量:https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Environment-Variables.html

预处理时搜索头文件路径:

  • CPATH/C_INCLUDE_PATH/CPLUS_INCLUDE_PATH/OBJC_INCLUDE_PATH:
    • Each variable’s value is a list of directories separated by a special character, much like PATH, in which to look for header files
    • CPATH specifies a list of directories to be searched as if specified with -I, but after any paths given with -I options on the command line. This environment variable is used regardless of which language is being preprocessed.

gcc 动态链接时查找的库路径(类似 PATH ,是冒号分割):

  • LIBRARY_PATH: (but directories specified with -L come first) 注意不是 LD_LIBRARY_PATH,后者是运行动态链接的二进制时查找动态库路径。

注: gcc 不使用 CC、CXX 等环境变量。

参考
#

  1. https://mohitmishra786.github.io/reversingBits/
gnu-toolchain - 这篇文章属于一个选集。
§ 2: 本文

相关文章

C 预处理器-个人参考手册
·
Gnu Cpp Manual
这是我个人的 C 预处理器参考手册文档。
链接器 ld
·
Gnu Ld Manual
Go CGO 程序静态编译链接
Cgo Go Compile Gcc
本文先介绍 Go CGO 的概念和应用场景,以项目用到的 mattn/go-sqlite3 为例,介绍 CGO 程序的静态链接实现方案,其中涉及到动态链接的问题分析、 ubunut/centos 系统的静态编译环境搭建,CGO 静态编译遇到的问题和解决方案,最终生成最小化系统环境依赖的静态链接二进制。
使用 musl 交叉编译和静态链接
·
Cgo Go Compile Gcc Musl
本文介绍了使用轻量化 libc 库 musl 进行交叉编译生成多架构二进制的方案,最终实现在 x86_64 编译机器上能同时构建出静态链接的 x86_64 和 aarch64 二进制的目标,大大简化了多套构建脚本的开发和维护成本。