交叉编译是指编译器能生成和它执行环境不同的 CPU 架构的二进制,例如在 arm64 机器上编译出在 x86_64 机器上运行的二进制。
本文分别以常用的 ubuntu aarch64 和 fedora 40 x86_64 编译环境为例,介绍这两个问题的解决方案。
target triplet #
格式:“cpu-vendor-os”, 其中 os 可以是 system 或 kernel-system。
- cpu:一般使用 uname -m 命令来获取,如 arm64 CPU 使用的是 aarch64, arm32 CPU 使用的是 arm。
- vendor:一般为 pc(windows 硬件)、apple(苹果硬件)、unknown(未知、通用);
- kernel:linux、none(不带内核的裸机程序)
- system:
- gnu:通用的,使用 GNU ABI,链接 glibc;
- gnueabi:一般是 arm32 在用,使用 GNU EAPI,链接 glibc;
- gnueabihf:一般是 arm32 在用,使用 GNU EABI(嵌入式 ABI 接口),链接 glibc,使用硬件浮点 (hard-float);
- musl:链接一个专为嵌入式系统设计的轻量级 C 库 musl ,目标是提供与 glibc 相似的功能,但占用更少的资源。常用的场景是实现 libc 库的静态链接, 以解决运行时机器上的 glibc 缺失或版本太老的问题;
- elf:不适用内核和操作系统的裸机程序;
triplet 示例:
## arm64(ARMv8 及以上处理器,默认硬件浮点计算)
aarch64-apple-darwin
aarch64-unknown-linux-gnu # 使用 GNU ABI 和链接 glibc 《-- 主流
aarch64-unknown-linux-gnu_ilp32
aarch64-unknown-linux-musl
aarch64-unknown-none # 不使用内核和 glibc,如逻辑 elf 程序
aarch64-none-elf:用于裸机(无操作系统)的 64 位 ARM 开发,遵循 ELF 格式。
## arm32 (ARMv7 及以前的处理器)
arm-unknown-linux-gnueabi # 链接 glibc
arm-unknown-linux-gnueabihf # hf 表示硬件浮点 hard-float 《-- 主流
arm-unknown-linux-musleabi # 链接 musl
arm-unknown-linux-musleabihf
x86_64-unknown-linux-gnu 《-- 主流
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-linux-none
gcc 工具链一般是只支持编译生成特定架构的二进制,而不能生成其它架构的二进制。
使用 gcc -dumpmachine
命令查看支持的 triplet:
alizj@ubuntu:~$ gcc -dumpmachine
aarch64-linux-gnu
Ubuntu、RedHat 系统支持安装多套交叉编译工具链,它们使用不同的 target-triplet 和目录结构来区分:
- 如 x86_64-unknown-linux-gnu-gcc 能生成 x86_64 架构的二进制,它也会自动调用 x86_64-unknown-linux-gnu- 前缀的其它命令。
- /usr/x86_64-unknown-linux-gnu 作为该交叉编译工具链的第二目录层次,下面的 bin、lib 等保存该架构的 binutils 命令、头文件、libc 标准库、gcc 命令和库等。
对于 autoconf、make、go build 等命令,可以通过 CC 环境变量来指定使用的工具链,或 –host=aarch64-linux-gnu 来指定架构前缀。
例如,当交叉编译时,configure 会查找带有 target triplet 前缀的工具,如 compilers, linkers, assemblers,如指定运行编译产物的 –host=aarch64-linux-gnu 时,使用的 C 编译器是 aarch64-linux-gnu-gcc,pkg-config 是 aarch64-linux-gnu-pkg-config,这样可以避免找到了错误类型的工具链。
cpp:预处理器 #
相关包:
alizj@ubuntu:~$ apt list |grep cpp |grep installed |grep -v x86
cpp-13-aarch64-linux-gnu/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
cpp-13/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
cpp-aarch64-linux-gnu/noble,now 4:13.2.0-7ubuntu1 arm64 [installed,automatic]
cpp/noble,now 4:13.2.0-7ubuntu1 arm64 [installed,automatic]
提供 cpp/cpp-13/aarch64-linux-gnu-cpp-13 命令,以及 gcc -E 自动调用的 cc1 程序。
alizj@ubuntu:~$ dpkg -L cpp
...
/usr/bin/cpp
...
alizj@ubuntu:~$ dpkg -L cpp-13
...
/usr/bin/cpp-13
...
alizj@ubuntu:~$ dpkg -L cpp-13-aarch64-linux-gnu
...
/usr/bin/aarch64-linux-gnu-cpp-13
...
/usr/libexec/gcc/aarch64-linux-gnu/13/cc1
alizj@ubuntu:~$ dpkg -L cpp-aarch64-linux-gnu
...
/usr/bin/aarch64-linux-gnu-cpp
gcc 编译器使用的是内置的预处理器(gcc -E
)通过 cc1 来进行预处理,独立 cpp 命令是历史兼容性场景。
gcc:编译器 #
相关包:
alizj@ubuntu:~$ apt list --installed |grep gcc |grep arm64 |grep -v x86-64
gcc-13-aarch64-linux-gnu/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
gcc-13-base/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
gcc-13/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
gcc-14-base/noble-updates,noble-security,now 14.2.0-4ubuntu2~24.04 arm64 [installed]
gcc-aarch64-linux-gnu/noble,now 4:13.2.0-7ubuntu1 arm64 [installed,automatic]
gcc-doc/noble,now 4:13.2.0-7ubuntu1 arm64 [installed]
gcc/noble,now 4:13.2.0-7ubuntu1 arm64 [installed,automatic]
libgcc-13-dev/noble-updates,noble-security,now 13.3.0-6ubuntu2~24.04 arm64 [installed,automatic]
libgcc-s1/noble-updates,noble-security,now 14.2.0-4ubuntu2~24.04 arm64 [installed]
提供:
/usr/bin/gcc 和 /usr/bin/aarch64-linux-gnu-*
等二进制;/usr/lib/gcc/aarch64-linux-gnu/13
和/usr/libexec/gcc/aarch64-linux-gnu/13
: 包含 GCC 自身的头文件、库文件和调用的二进制。
二进制链接关系:gcc -> gcc-13 -> aarch64-linux-gnu-gcc-13
alizj@ubuntu:~$ ls -l /usr/bin/gcc
lrwxrwxrwx 1 root root 6 Jan 31 2024 /usr/bin/gcc -> gcc-13
alizj@ubuntu:~$ ls -l /usr/bin/gcc-13
lrwxrwxrwx 1 root root 24 Sep 4 22:44 /usr/bin/gcc-13 -> aarch64-linux-gnu-gcc-13
alizj@ubuntu:~$ ls -l /usr/bin/aarch64-linux-gnu-gcc-13
-rwxr-xr-x 1 root root 990040 Sep 4 22:44 /usr/bin/aarch64-linux-gnu-gcc-13
alizj@ubuntu:~$ dpkg -L gcc
...
/usr/bin/c89-gcc
/usr/bin/c99-gcc
/usr/lib/bfd-plugins
...
/usr/bin/gcc
/usr/bin/gcc-ar # 打包为静态库
/usr/bin/gcc-nm # 解析 ELF 符号
/usr/bin/gcc-ranlib # 为静态库生成索引
/usr/bin/gcov
/usr/bin/gcov-dump
/usr/bin/gcov-tool
/usr/bin/lto-dump
/usr/lib/bfd-plugins/liblto_plugin.so
alizj@ubuntu:~$ dpkg -L gcc-13
...
/usr/bin/gcc-13
/usr/bin/gcc-ar-13
/usr/bin/gcc-nm-13
/usr/bin/gcc-ranlib-13
/usr/bin/gcov-13
/usr/bin/gcov-dump-13
/usr/bin/gcov-tool-13
/usr/bin/lto-dump-13
...
alizj@ubuntu:~$ dpkg -L gcc-aarch64-linux-gnu
...
/usr/bin/aarch64-linux-gnu-gcc
/usr/bin/aarch64-linux-gnu-gcc-ar
/usr/bin/aarch64-linux-gnu-gcc-nm
/usr/bin/aarch64-linux-gnu-gcc-ranlib
/usr/bin/aarch64-linux-gnu-gcov
/usr/bin/aarch64-linux-gnu-gcov-dump
/usr/bin/aarch64-linux-gnu-gcov-tool
/usr/bin/aarch64-linux-gnu-lto-dump
...
alizj@ubuntu:~$ dpkg -L gcc-13-aarch64-linux-gnu
...
/usr/bin/aarch64-linux-gnu-gcc-13
/usr/bin/aarch64-linux-gnu-gcc-ar-13
/usr/bin/aarch64-linux-gnu-gcc-nm-13
/usr/bin/aarch64-linux-gnu-gcc-ranlib-13
/usr/bin/aarch64-linux-gnu-gcov-13
/usr/bin/aarch64-linux-gnu-gcov-dump-13
/usr/bin/aarch64-linux-gnu-gcov-tool-13
/usr/bin/aarch64-linux-gnu-lto-dump-13
...
/usr/lib/gcc/aarch64-linux-gnu/13
/usr/lib/gcc/aarch64-linux-gnu/13/libgomp.spec
/usr/lib/gcc/aarch64-linux-gnu/13/libhwasan_preinit.o
/usr/lib/gcc/aarch64-linux-gnu/13/libitm.spec
/usr/lib/gcc/aarch64-linux-gnu/13/libsanitizer.spec
/usr/lib/gcc/aarch64-linux-gnu/13/plugin
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcc1plugin.so.0.0.0
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcp1plugin.so.0.0.0
...
# /usr/libexec/gcc 保存 gcc 调用的内部命令和库
/usr/libexec/gcc/aarch64-linux-gnu
/usr/libexec/gcc/aarch64-linux-gnu/13
/usr/libexec/gcc/aarch64-linux-gnu/13/collect2
/usr/libexec/gcc/aarch64-linux-gnu/13/liblto_plugin.so
/usr/libexec/gcc/aarch64-linux-gnu/13/lto-wrapper
/usr/libexec/gcc/aarch64-linux-gnu/13/lto1
...
/usr/lib/gcc/aarch64-linux-gnu/13/libcc1.so
/usr/lib/gcc/aarch64-linux-gnu/13/liblto_plugin.so
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcc1plugin.so
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcc1plugin.so.0
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcp1plugin.so
/usr/lib/gcc/aarch64-linux-gnu/13/plugin/libcp1plugin.so.0
/usr/share/doc/gcc-13-aarch64-linux-gnu
# libgcc-13-dev 包提供了 gcc 提供的内建函数实现的动态库、静态库以及对应头文件,
# 它们会被链接到 C 程序中,提供了 main 函数前后逻辑:
alizj@ubuntu:~$ dpkg -L libgcc-13-dev
...
# C 启动例程,调用 main 函数
/usr/lib/gcc/aarch64-linux-gnu/13/crtbegin.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtbeginS.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtbeginT.o
# C 结束例程,main 返回后执行
/usr/lib/gcc/aarch64-linux-gnu/13/crtend.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtendS.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtfastmath.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtoffloadbegin.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtoffloadend.o
/usr/lib/gcc/aarch64-linux-gnu/13/crtoffloadtable.o
# GCC 相关头文件
/usr/lib/gcc/aarch64-linux-gnu/13/include
/usr/lib/gcc/aarch64-linux-gnu/13/include/backtrace.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/float.h
...
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdalign.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdarg.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdatomic.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdbool.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stddef.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdfix.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdint-gcc.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdint.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/stdnoreturn.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/syslimits.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/unwind.h
/usr/lib/gcc/aarch64-linux-gnu/13/include/varargs.h
# GCC 自身使用的库
/usr/lib/gcc/aarch64-linux-gnu/13/libasan.a
/usr/lib/gcc/aarch64-linux-gnu/13/libasan_preinit.o
/usr/lib/gcc/aarch64-linux-gnu/13/libatomic.a
/usr/lib/gcc/aarch64-linux-gnu/13/libbacktrace.a
/usr/lib/gcc/aarch64-linux-gnu/13/libgcc.a
/usr/lib/gcc/aarch64-linux-gnu/13/libgcc_eh.a
/usr/lib/gcc/aarch64-linux-gnu/13/libgcc_s.so
/usr/lib/gcc/aarch64-linux-gnu/13/libgcov.a
/usr/lib/gcc/aarch64-linux-gnu/13/libgomp.a
/usr/lib/gcc/aarch64-linux-gnu/13/libhwasan.a
/usr/lib/gcc/aarch64-linux-gnu/13/libitm.a
/usr/lib/gcc/aarch64-linux-gnu/13/liblsan.a
/usr/lib/gcc/aarch64-linux-gnu/13/liblsan_preinit.o
/usr/lib/gcc/aarch64-linux-gnu/13/libssp_nonshared.a
/usr/lib/gcc/aarch64-linux-gnu/13/libtsan.a
/usr/lib/gcc/aarch64-linux-gnu/13/libtsan_preinit.o
/usr/lib/gcc/aarch64-linux-gnu/13/libubsan.a
/usr/lib/gcc/aarch64-linux-gnu/13/libasan.so
/usr/lib/gcc/aarch64-linux-gnu/13/libatomic.so
/usr/lib/gcc/aarch64-linux-gnu/13/libgomp.so
/usr/lib/gcc/aarch64-linux-gnu/13/libhwasan.so
/usr/lib/gcc/aarch64-linux-gnu/13/libitm.so
/usr/lib/gcc/aarch64-linux-gnu/13/liblsan.so
/usr/lib/gcc/aarch64-linux-gnu/13/libtsan.so
/usr/lib/gcc/aarch64-linux-gnu/13/libubsan.so
/usr/share/doc/libgcc-13-dev
gcc 内置了内部二进制搜索路径,以及 gcc 和 glibc 库的搜索路径,它们都是和 target triplet 相关的,所以系统可以按照多个 triplet 的编译工具链和 glibc 库,而不会相互混淆:
alizj@ubuntu:~$ gcc -print-search-dirs
install: /usr/lib/gcc/aarch64-linux-gnu/13/
programs: =/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/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/
libraries: =/usr/lib/gcc/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/../lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../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/13/:/lib/aarch64-linux-gnu/:/lib/../lib/:/usr/lib/aarch64-linux-gnu/13/:/usr/lib/aarch64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../:/lib/:/usr/lib/
binutils:汇编&链接和二进制工具 #
安装的包:
alizj@ubuntu:~$ apt list --installed binutils*
binutils-aarch64-linux-gnu/noble-updates,noble-security,now 2.42-4ubuntu2.3 arm64 [installed,automatic]
binutils-common/noble-updates,noble-security,now 2.42-4ubuntu2.3 arm64 [installed,automatic]
binutils-x86-64-linux-gnu/noble-updates,noble-security,now 2.42-4ubuntu2.3 arm64 [installed,automatic]
binutils/noble-updates,noble-security,now 2.42-4ubuntu2.3 arm64 [installed,automatic]
binutils-dev/noble-updates,noble-security 2.42-4ubuntu2.3 arm64
提供的二进制工具,它们可以对 ELF 文件进行操作:
- as:汇编器;
- ld/ld.bfd/ld.gold :链接器及链接脚本;
- gprof/gprofng/addr2line
- ar:静态库惯例工具
- elfedit/readelf/ranlib
- objcopy/objdump/nm/addr2line
- size/strings/strip
binutils 还提供了 bfd 头文件和库文件,用于解析、反汇编 ELF 文件。
alizj@ubuntu:~$ dpkg -L binutils|sort
...
/usr/bin/addr2line
/usr/bin/ar
/usr/bin/as
/usr/bin/c++filt
/usr/bin/dwp
/usr/bin/elfedit
/usr/bin/gold
/usr/bin/gp-archive
/usr/bin/gp-collect-app
/usr/bin/gp-display-html
/usr/bin/gp-display-src
/usr/bin/gp-display-text
/usr/bin/gprof
/usr/bin/gprofng
/usr/bin/ld
/usr/bin/ld.bfd
/usr/bin/ld.gold
/usr/bin/nm
/usr/bin/objcopy
/usr/bin/objdump
/usr/bin/ranlib
/usr/bin/readelf
/usr/bin/size
/usr/bin/strings
/usr/bin/strip
# 链接器
/usr/lib/compat-ld
/usr/lib/compat-ld/ld
/usr/lib/gold-ld
/usr/lib/gold-ld/ld
...
alizj@ubuntu:~$ dpkg -L binutils-aarch64-linux-gnu | sort
/.
/usr
/usr/bin
/usr/bin/aarch64-linux-gnu-addr2line
/usr/bin/aarch64-linux-gnu-ar
/usr/bin/aarch64-linux-gnu-as
/usr/bin/aarch64-linux-gnu-c++filt
/usr/bin/aarch64-linux-gnu-dwp
/usr/bin/aarch64-linux-gnu-elfedit
/usr/bin/aarch64-linux-gnu-gold
/usr/bin/aarch64-linux-gnu-gp-archive
/usr/bin/aarch64-linux-gnu-gp-collect-app
/usr/bin/aarch64-linux-gnu-gp-display-html
/usr/bin/aarch64-linux-gnu-gp-display-src
/usr/bin/aarch64-linux-gnu-gp-display-text
/usr/bin/aarch64-linux-gnu-gprof
/usr/bin/aarch64-linux-gnu-gprofng
/usr/bin/aarch64-linux-gnu-ld
/usr/bin/aarch64-linux-gnu-ld.bfd
/usr/bin/aarch64-linux-gnu-ld.gold
/usr/bin/aarch64-linux-gnu-nm
/usr/bin/aarch64-linux-gnu-objcopy
/usr/bin/aarch64-linux-gnu-objdump
/usr/bin/aarch64-linux-gnu-ranlib
/usr/bin/aarch64-linux-gnu-readelf
/usr/bin/aarch64-linux-gnu-size
/usr/bin/aarch64-linux-gnu-strings
/usr/bin/aarch64-linux-gnu-strip
...
/usr/lib/aarch64-linux-gnu/bfd-plugins
/usr/lib/aarch64-linux-gnu/bfd-plugins/libdep.so
# 各种架构的链接脚本
/usr/lib/aarch64-linux-gnu/ldscripts
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64elf32b.x
...
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linuxb.xwe
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linux.x
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linux.xbn
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linux.xc
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linux.xce
/usr/lib/aarch64-linux-gnu/ldscripts/aarch64linux.xd
...
/usr/lib/aarch64-linux-gnu/ldscripts/stamp
...
# bfd 头文件和 libbfd 库文件
alizj@ubuntu:~$ dpkg -L binutils-dev | sort
...
/usr/include/ansidecl.h
/usr/include/bfd.h
/usr/include/bfdlink.h
/usr/include/collectorAPI.h
/usr/include/ctf-api.h
/usr/include/ctf.h
/usr/include/diagnostics.h
/usr/include/dis-asm.h
/usr/include/libcollector.h
/usr/include/libfcollector.h
/usr/include/plugin-api.h
/usr/include/sframe-api.h
/usr/include/sframe.h
/usr/include/symcat.h
...
/usr/lib/aarch64-linux-gnu/libbfd.a
/usr/lib/aarch64-linux-gnu/libbfd_pic.a
/usr/lib/aarch64-linux-gnu/libbfd.so
/usr/lib/aarch64-linux-gnu/libctf.a
/usr/lib/aarch64-linux-gnu/libctf-nobfd.a
/usr/lib/aarch64-linux-gnu/libctf-nobfd.so
/usr/lib/aarch64-linux-gnu/libctf.so
/usr/lib/aarch64-linux-gnu/libgprofng.a
/usr/lib/aarch64-linux-gnu/libgprofng.so
/usr/lib/aarch64-linux-gnu/libopcodes.a
/usr/lib/aarch64-linux-gnu/libopcodes_pic.a
/usr/lib/aarch64-linux-gnu/libopcodes.so
/usr/lib/aarch64-linux-gnu/libsframe.a
/usr/lib/aarch64-linux-gnu/libsframe.so
binutils 提供两种类型链接器: bfd(默认) 和 gold,另外两种常用的链接器分别是 lld 和 mold。
alizj@lima-dev2:~$ dpkg -S /usr/bin/ld*
binutils: /usr/bin/ld
binutils: /usr/bin/ld.bfd
binutils: /usr/bin/ld.gold
libc-bin: /usr/bin/ld.so
libc-bin: /usr/bin/ldd
alizj@ubuntu:~$ ls -l /usr/bin/ld
lrwxrwxrwx 1 root root 20 Aug 7 18:15 /usr/bin/ld -> aarch64-linux-gnu-ld
alizj@ubuntu:~$ ls -l /usr/bin/aarch64-linux-gnu-ld
lrwxrwxrwx 1 root root 24 Aug 7 18:15 /usr/bin/aarch64-linux-gnu-ld -> aarch64-linux-gnu-ld.bfd
alizj@ubuntu:~$ ls -l /usr/bin/aarch64-linux-gnu-ld.bfd
-rwxr-xr-x 1 root root 1710520 Aug 7 18:15 /usr/bin/aarch64-linux-gnu-ld.bfd
gcc 和 binutils 都提供了 ar/nm 等二进制工具,但前缀不同,系统默认使用的是 binutils 提供的版本:
alizj@ubuntu:~$ dpkg -S /usr/bin/aarch64-linux-gnu-*nm*
gcc-aarch64-linux-gnu: /usr/bin/aarch64-linux-gnu-gcc-nm
gcc-13-aarch64-linux-gnu: /usr/bin/aarch64-linux-gnu-gcc-nm-13
binutils-aarch64-linux-gnu: /usr/bin/aarch64-linux-gnu-nm
alizj@ubuntu:~$ which ar
/usr/bin/ar
alizj@ubuntu:~$ ls -l /usr/bin/ar
lrwxrwxrwx 1 root root 20 Aug 7 18:15 /usr/bin/ar -> aarch64-linux-gnu-ar
alizj@ubuntu:~$ dpkg -S /usr/bin/aarch64-linux-gnu-ar
binutils-aarch64-linux-gnu: /usr/bin/aarch64-linux-gnu-ar
libc 和动态链接器 #
libc 涉及的包:
- libc-bin:提供 ldd 动态库链接器,locale、tzselect 等国际化支持;
- libc-dev-bin:仅提供 gencat 命令;
- libc-devtools:提供 memusage、mtrace、sprof 等不常用的内存分析命令;
- libc6-dbg: libc 库 debuginfo 调试符号;
- libc6-dev: libc 库标准头文件和 libc.a 静态库文件;
- libc6:glibc 库;
- linux-libc-dev:提供给 libc 使用的内核头文件
alizj@ubuntu:~$ sudo apt list |grep libc |grep installed |grep -v x86 |grep -v amd64
glibc-source/noble-updates,noble-security,noble-updates,noble-security,now 2.39-0ubuntu8.3 all [installed]
libc-bin/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed]
libc-dev-bin/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed,automatic]
libc-devtools/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed,automatic]
libc6-dbg/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed]
libc6-dev/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed,automatic]
libc6/noble-updates,noble-security,now 2.39-0ubuntu8.3 arm64 [installed]
linux-libc-dev/noble-updates,noble-security,now 6.8.0-52.53 arm64 [installed,automatic]
glibc 是架构相关的,位于 /usr/lib/
glibc 标准头文件位于 /usr/include/aarch64-linux-gnu 和 /usr/include 目录下;
root@lima-dev2:/home/alizj.linux# dpkg -L libc6
# libc 动态链接器配置
/etc/ld.so.conf.d
/etc/ld.so.conf.d/aarch64-linux-gnu.conf
# 架构相关的 libc 库目录
/lib/aarch64-linux-gnu
/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 #动态链接器
/lib/aarch64-linux-gnu/libBrokenLocale.so.1
/lib/aarch64-linux-gnu/libanl.so.1
# GNU glibc 库
/lib/aarch64-linux-gnu/libc.so.6
/lib/aarch64-linux-gnu/libc_malloc_debug.so.0
/lib/aarch64-linux-gnu/libdl.so.2
/lib/aarch64-linux-gnu/libm.so.6
/lib/aarch64-linux-gnu/libmemusage.so
/lib/aarch64-linux-gnu/libmvec.so.1
/lib/aarch64-linux-gnu/libnsl.so.1
/lib/aarch64-linux-gnu/libnss_compat.so.2
/lib/aarch64-linux-gnu/libnss_dns.so.2
/lib/aarch64-linux-gnu/libnss_files.so.2
/lib/aarch64-linux-gnu/libnss_hesiod.so.2
/lib/aarch64-linux-gnu/libpcprofile.so
/lib/aarch64-linux-gnu/libpthread.so.0
/lib/aarch64-linux-gnu/libresolv.so.2
/lib/aarch64-linux-gnu/librt.so.1
/lib/aarch64-linux-gnu/libthread_db.so.1
/lib/aarch64-linux-gnu/libutil.so.1
alizj@lima-dev2:~$ dpkg -L libc6-dev
...
/usr/include/aarch64-linux-gnu/a.out.h
/usr/include/aarch64-linux-gnu/bits
/usr/include/aarch64-linux-gnu/bits/a.out.h
/usr/include/aarch64-linux-gnu/bits/argp-ldbl.h
/usr/include/aarch64-linux-gnu/bits/atomic_wide_counter.h
/usr/include/aarch64-linux-gnu/bits/wchar2.h
/usr/include/aarch64-linux-gnu/bits/wctype-wchar.h
/usr/include/aarch64-linux-gnu/bits/wordsize.h
/usr/include/aarch64-linux-gnu/bits/xopen_lim.h
/usr/include/aarch64-linux-gnu/fpu_control.h
/usr/include/aarch64-linux-gnu/gnu
/usr/include/aarch64-linux-gnu/gnu/lib-names-lp64.h
/usr/include/aarch64-linux-gnu/gnu/lib-names.h
/usr/include/aarch64-linux-gnu/gnu/libc-version.h
/usr/include/aarch64-linux-gnu/gnu/stubs-lp64.h
/usr/include/aarch64-linux-gnu/gnu/stubs.h
/usr/include/aarch64-linux-gnu/ieee754.h
/usr/include/aarch64-linux-gnu/sys
/usr/include/aarch64-linux-gnu/sys/acct.h
/usr/include/aarch64-linux-gnu/sys/auxv.h
/usr/include/aarch64-linux-gnu/sys/bitypes.h
/usr/include/aarch64-linux-gnu/sys/cdefs.h
/usr/include/aarch64-linux-gnu/sys/dir.h
#...
/usr/include/aio.h
/usr/include/aliases.h
/usr/include/alloca.h
/usr/include/fcntl.h
/usr/include/features-time64.h
/usr/include/features.h
/usr/include/wchar.h
/usr/include/wctype.h
/usr/include/wordexp.h
...
/usr/lib/aarch64-linux-gnu/Mcrt1.o
/usr/lib/aarch64-linux-gnu/Scrt1.o
/usr/lib/aarch64-linux-gnu/audit
/usr/lib/aarch64-linux-gnu/audit/sotruss-lib.so
/usr/lib/aarch64-linux-gnu/crt1.o
/usr/lib/aarch64-linux-gnu/crti.o
/usr/lib/aarch64-linux-gnu/crtn.o
/usr/lib/aarch64-linux-gnu/gcrt1.o
/usr/lib/aarch64-linux-gnu/grcrt1.o
/usr/lib/aarch64-linux-gnu/libBrokenLocale.a
/usr/lib/aarch64-linux-gnu/libanl.a
/usr/lib/aarch64-linux-gnu/libc.a # glibc 静态库和动态库
/usr/lib/aarch64-linux-gnu/libc.so
/usr/lib/aarch64-linux-gnu/libc_nonshared.a
/usr/lib/aarch64-linux-gnu/libdl.a
/usr/lib/aarch64-linux-gnu/libg.a
/usr/lib/aarch64-linux-gnu/libm-2.38.a
/usr/lib/aarch64-linux-gnu/libm.a
/usr/lib/aarch64-linux-gnu/libm.so
/usr/lib/aarch64-linux-gnu/libmcheck.a
/usr/lib/aarch64-linux-gnu/libmvec.a
/usr/lib/aarch64-linux-gnu/libpthread.a
/usr/lib/aarch64-linux-gnu/libpthread_nonshared.a
/usr/lib/aarch64-linux-gnu/libresolv.a
/usr/lib/aarch64-linux-gnu/librt.a
/usr/lib/aarch64-linux-gnu/libutil.a
/usr/lib/aarch64-linux-gnu/rcrt1.o
/usr/lib/aarch64-linux-gnu/libBrokenLocale.so
/usr/lib/aarch64-linux-gnu/libanl.so
/usr/lib/aarch64-linux-gnu/libc_malloc_debug.so
/usr/lib/aarch64-linux-gnu/libmvec.so
/usr/lib/aarch64-linux-gnu/libnss_compat.so
/usr/lib/aarch64-linux-gnu/libnss_hesiod.so
/usr/lib/aarch64-linux-gnu/libresolv.so
/usr/lib/aarch64-linux-gnu/libthread_db.so
root@lima-dev2:/home/alizj.linux# dpkg -L libc-bin
/.
/etc
/etc/bindresvport.blacklist
/etc/gai.conf
/etc/ld.so.conf
/etc/ld.so.conf.d
/etc/ld.so.conf.d/libc.conf # libc 动态库加载配置
/sbin
/sbin/ldconfig # 动态加载配置命令
/sbin/ldconfig.real
/usr
/usr/bin
/usr/bin/getconf
/usr/bin/getent
/usr/bin/iconv
/usr/bin/ldd # 打印动态库对象的依赖
/usr/bin/locale # 国际化
/usr/bin/localedef
/usr/bin/pldd
/usr/bin/tzselect
/usr/bin/zdump
/usr/lib/locale # locale 数据库
/usr/lib/locale/C.utf8
/usr/lib/locale/C.utf8/LC_ADDRESS
/usr/lib/locale/C.utf8/LC_COLLATE
/usr/lib/locale/C.utf8/LC_CTYPE
/var/cache/ldconfig # 动态链接器缓存
/usr/bin/ld.so # 动态链接器
# linux-libc-dev: glibc 使用的内核头文件
root@lima-dev2:/home/alizj.linux# dpkg -L linux-libc-dev
/.
/usr
/usr/include
/usr/include/aarch64-linux-gnu # 架构相关的头文件
/usr/include/aarch64-linux-gnu/asm
/usr/include/aarch64-linux-gnu/asm/auxvec.h
/usr/include/aarch64-linux-gnu/asm/bitsperlong.h
/usr/include/aarch64-linux-gnu/asm/bpf_perf_event.h
/usr/include/aarch64-linux-gnu/asm/byteorder.h
/usr/include/aarch64-linux-gnu/asm/errno.h
/usr/include/aarch64-linux-gnu/asm/fcntl.h
/usr/include/aarch64-linux-gnu/asm/hwcap.h
/usr/include/aarch64-linux-gnu/asm/ioctl.h
/usr/include/aarch64-linux-gnu/asm/ioctls.h
/usr/include/aarch64-linux-gnu/asm/ipcbuf.h
#...
/usr/include/aarch64-linux-gnu/asm/unistd.h
/usr/include/asm-generic # 架构无关(通用)的头文件
/usr/include/asm-generic/auxvec.h
/usr/include/asm-generic/bitsperlong.h
/usr/include/asm-generic/bpf_perf_event.h
#...
/usr/include/asm-generic/unistd.h
/usr/include/drm
/usr/include/drm/amdgpu_drm.h
/usr/include/drm/armada_drm.h
/usr/include/drm/drm.h
/usr/include/linux # 通用内核头文件
/usr/include/linux/acct.h
/usr/include/linux/xilinx-v4l2-controls.h
/usr/include/linux/zorro.h
/usr/include/linux/zorro_ids.h
#...
libc 库类型 #
libc 库封装了所有 POSIX 系统调用,是用户程序与 Kernel 的接口,在编译 glibc 时,需要提供对应版本的内核头文件。
libc 库有多种实现类型:
- glibc:通用;
- musl libc:也是通用的 libc,但是更轻量,在轻量化容器镜像中得到广泛应用:https://musl.libc.org/
- uClibc/uClibc-ng:嵌入式优化的 libc 库:https://uclibc-ng.org/
- newlib:嵌入式优化的 libc 库:https://sourceware.org/newlib/
交叉编译工具链 #
ubuntu aarch64 -> x86_64 交叉静态编译 #
根据经验,ubuntu 对多架构交叉编译的支持比 centos、fedora 更成熟,后者需要 hack gcc 交叉编译工具链的 sysroot 参数。
在 ubuntu aarch64 架构机器上交叉编译出 x86_64 架构静态二进制方案:
# arm64 虚机上,为 CGO 程序交叉编译生成 amd64 程序报错
$ GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -o myagent ./cmd/
runtime/cgo
gcc: error: unrecognized command-line option '-m64'
# 这是由于安装的 ubuntu 安装的 gcc 只支持编译生成 arm64 架构的二进制,而不支持交叉编译生成 amd64 架构的二进制。
# 启用多架构
$ sudo dpkg --add-architecture amd64
# 添加 amd64 架构源
$ cat /etc/apt/sources.list
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu noble-security main restricted universe multiverse
# 安装 amd64 架构的 libc 库
sudo apt update
sudo apt install libc6:amd64
# 安装可以生成 amd64 架构的 gcc 交叉编译工具链
$ sudo apt install gcc-x86-64-linux-gnu
$ file /usr/bin/x86_64-linux-gnu-gcc
/usr/bin/x86_64-linux-gnu-gcc: symbolic link to x86_64-linux-gnu-gcc-13
$ file /usr/bin/x86_64-linux-gnu-gcc-13
/usr/bin/x86_64-linux-gnu-gcc-13: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=ad41a19a0955b7e6770ad00ff5cd9b97999b2f0e, for GNU/Linux 3.7.0, stripped
# 启用 CGO 的情况下,交叉编译静态链接成功
$ CC=x86_64-linux-gnu-gcc GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -tags 'osusergo netgo sqlite_omit_load_extension no_dynamic_plugins' -o myagent -ldflags=" -extldflags '-static'" ./cmd/
fedora 40 x86_64 -> aarch64 交叉静态编译 #
类似的,以 fedora40 x86_64 编译环境为例(CentOS、RHEL 类似),如果要编译出 arm64 架构的静态二进制,需要先安装 gcc-aarch64 编译工具链,在 go build 时使用 CC 环境变量来指定使用该工具链。
同时还要安装 sysroot-aarch64-fc40-glibc 包,它为交叉编译提供了 glibc 标准库头文件和静态 glibc 库支持(大坑,卡了很久才解决),通过 CGO_LDFLAGS 环境变量的 –sysroot 参数传递给交叉编译工具链,参考:
- https://cloud.tencent.com/developer/article/1851733
- https://stackoverflow.com/questions/77462229/cross-compile-from-centos-7-to-raspberry-pi-2b-cant-get-libc-and-system-inclu
yum install -y glibc-devel glibc-static gcc
# 在 x86_64 环境中,可以直接编译出 x86_64 架构二进制
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -tags 'osusergo netgo sqlite_omit_load_extension no_dynamic_plugins' -o myagent -ldflags=" -extldflags '-static'" ./cmd/
# 交叉编译 arm64 架构的二进制失败,这是由于 x86_64 gcc 不支持汇编 arm64 指令
[root@d8e784ed1d22 bp-agent]# GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -tags 'osusergo netgo sqlite_omit_load_extension no_dynamic_plugins' -buildmode=exe -o bp-agent -ldflags=" -extldflags '-static'" ./cmd/
# runtime/cgo
gcc_arm64.S: Assembler messages:
gcc_arm64.S:30: Error: no such instruction: `stp x29,x30,[sp,'
gcc_arm64.S:34: Error: operand size mismatch for `mov'
gcc_arm64.S:36: Error: no such instruction: `stp x19,x20,[sp,'
gcc_arm64.S:39: Error: no such instruction: `stp x21,x22,[sp,'
gcc_arm64.S:42: Error: no such instruction: `stp x23,x24,[sp,'
gcc_arm64.S:45: Error: no such instruction: `stp x25,x26,[sp,'
gcc_arm64.S:48: Error: no such instruction: `stp x27,x28,[sp,'
gcc_arm64.S:52: Error: operand size mismatch for `mov'
gcc_arm64.S:53: Error: operand size mismatch for `mov'
gcc_arm64.S:54: Error: operand size mismatch for `mov'
gcc_arm64.S:56: Error: no such instruction: `blr x20'
gcc_arm64.S:57: Error: no such instruction: `blr x19'
gcc_arm64.S:59: Error: no such instruction: `ldp x27,x28,[sp,'
gcc_arm64.S:62: Error: no such instruction: `ldp x25,x26,[sp,'
gcc_arm64.S:65: Error: no such instruction: `ldp x23,x24,[sp,'
gcc_arm64.S:68: Error: no such instruction: `ldp x21,x22,[sp,'
gcc_arm64.S:71: Error: no such instruction: `ldp x19,x20,[sp,'
gcc_arm64.S:74: Error: no such instruction: `ldp x29,x30,[sp],'
# 安装支持交叉编译的 arm64 架构的编译工具链
yum install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu gcc-c++-aarch64-linux-gnu;
# 编译失败,提示找不到 stdlib.h 库
[root@d8e784ed1d22 bp-agent]# CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -tags 'osusergo netgo sqlite_omit_load_extension no_dynamic_plugins' -o myagent -ldflags=" -extldflags '-static'" ./cmd/
# runtime/cgo
_cgo_export.c:3:10: fatal error: stdlib.h: No such file or directory
3 | #include <stdlib.h>
| ^~~~~~~~~~
compilation terminated.
# 查看 aarch64-linux-gnu-gcc 编译器配置参数
[root@d8e784ed1d22 bp-agent]# aarch64-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/aarch64-linux-gnu/14/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../gcc-14.1.1-20240508/configure --bindir=/usr/bin --build=x86_64-redhat-linux-gnu --datadir=/usr/share --disable-decimal-float --disable-dependency-tracking --disable-gold --disable-libgcj --disable-libgomp --disable-libmpx --disable-libquadmath --disable-libssp --disable-libunwind-exceptions --disable-shared --disable-silent-rules --disable-sjlj-exceptions --disable-threads --with-ld=/usr/bin/aarch64-linux-gnu-ld --enable-__cxa_atexit --enable-checking=release --enable-gnu-unique-object --enable-initfini-array --enable-languages=c,c++ --enable-linker-build-id --enable-lto --enable-nls --enable-obsolete --enable-plugin --enable-targets=all --exec-prefix=/usr --host=x86_64-redhat-linux-gnu --includedir=/usr/include --infodir=/usr/share/info --libexecdir=/usr/libexec --localstatedir=/var --mandir=/usr/share/man --prefix=/usr --program-prefix=aarch64-linux-gnu- --sbindir=/usr/sbin --sharedstatedir=/var/lib --sysconfdir=/etc --target=aarch64-linux-gnu --with-bugurl=http://bugzilla.redhat.com/bugzilla/ --with-gcc-major-version-only --with-isl --with-newlib --with-plugin-ld=/usr/bin/aarch64-linux-gnu-ld --with-sysroot=/usr/aarch64-linux-gnu/sys-root --with-system-libunwind --with-system-zlib --without-headers --enable-gnu-indirect-function --with-linker-hash-style=gnu
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 14.1.1 20240507 (Red Hat Cross 14.1.1-1) (GCC)
# --with-sysroot=/usr/aarch64-linux-gnu/sys-root 目录为空:
[root@d8e784ed1d22 bp-agent]# ls /usr/aarch64-linux-gnu/bin/
ar as ld ld.bfd nm objcopy objdump ranlib readelf strip
[root@d8e784ed1d22 bp-agent]# ls /usr/aarch64-linux-gnu/sys-root/
[root@d8e784ed1d22 bp-agent]#
# 安装 aarch64 对应的 sysroot 包 sysroot-aarch64-fc40-glibc.noarch,它提供了交叉编译所需的 glibc 头文件和静态库
[root@d8e784ed1d22 bp-agent]# yum install sysroot-aarch64-fc40-glibc.noarch
[root@d8e784ed1d22 bp-agent]# ls /usr/aarch64-redhat-linux/sys-root/fc40/usr/
include lib lib64
# 使用 CGO_CFLAGS 环境变量为交叉编译 gcc 指定 --sysroot 参数,来使用安装的 aarch64 的 glibc 头文件和静态库,
# 同时使用 CC 环境变量指定使用该工具链来编译 CGO 链接的 C 程序
[root@d8e784ed1d22 bp-agent]# CC=aarch64-linux-gnu-gcc CGO_CFLAGS="-g -O2 --sysroot=/usr/aarch64-redhat-linux/sys-root/fc40" CGO_LDFLAGS="-g -O2 --sysroot=/usr/aarch64-redhat-linux/sys-root/fc40" GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -x -tags 'osusergo netgo sqlite_omit_load_extension no_dynamic_plugins' -o myagent -ldflags=" -extldflags '-static'" ./cmd/
[root@d8e784ed1d22 bp-agent]# file myagent
myagent: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=90ac14fe0ac828b0defb3ae4e3c328a589948a8c, for GNU/Linux 3.7.0, with debug_info, not stripped
[root@d8e784ed1d22 bp-agent]# ldd myagent
not a dynamic executable
编译工具链目录分析 #
Host 架构工具链 #
ubuntu host aarch64 架构编译器,库文件搜索路径如下:
- /usr/libexec/gcc/aarch64-linux-gnu/13/
- 保存 gcc 内部调用的二进制,如 cc1,collect2 等
- /usr/lib/gcc/aarch64-linux-gnu/13/
- 保存 gcc 自身使用的库,引用
/usr/lib/aarch64-linux-gnu
下的动态库,如 libatomic.so/libcc1.so 等
- 保存 gcc 自身使用的库,引用
- /usr/aarch64-linux-gnu/bin/aarch64-linux-gnu/13/,/usr/aarch64-linux-gnu/bin/,/usr/aarch64-linux-gnu/lib/aarch64-linux-gnu/13
- NO, 目录不存在。
- /usr/aarch64-linux-gnu/lib
- NO, 目录不存在。
- /usr/lib/aarch64-linux-gnu/
- 系统标准库目录,放到 /usr/lib/
目录下,而非以前的 /usr/lib 目录。
- 系统标准库目录,放到 /usr/lib/
- /lib,/usr/lib
/lib, /usr/lib, /usr/libexec 都是 Host 架构库,其它架构的库位于 /usr/
ubuntu 不再提供 /lib64 和 /usr/lib64 目录, /bin, /sbin, /lib 都指向 /usr 下对应目录。
root@lima-dev2:~# ls -l /
total 68
...
lrwxrwxrwx 1 root root 7 Mar 7 2024 bin -> usr/bin
lrwxrwxrwx 1 root root 7 Mar 7 2024 lib -> usr/lib
lrwxrwxrwx 1 root root 8 Mar 7 2024 sbin -> usr/sbin
...
root@lima-dev2:~# ls -l /usr/
total 88
drwxr-xr-x 2 root root 36864 Oct 14 18:09 bin
drwxr-xr-x 2 root root 4096 Oct 10 2023 games
drwxr-xr-x 45 root root 4096 Oct 8 12:27 include
drwxr-xr-x 90 root root 4096 Oct 14 18:09 lib
drwxr-xr-x 12 root root 4096 Oct 14 18:09 libexec
drwxr-xr-x 11 root root 4096 Jun 20 12:28 local
drwxr-xr-x 2 root root 20480 Oct 9 13:37 sbin
drwxr-xr-x 135 root root 4096 Oct 11 15:57 share
drwxr-xr-x 7 root root 4096 Jul 14 06:21 src
drwxr-xr-x 8 root root 4096 Oct 14 18:09 x86_64-linux-gnu # 其它架构(交叉编译工具链)的根目录
# Host 架构的 libc 等标准库不再放到 `/usr/lib` 目录下,而是放到 Host 架构的 `/usr/lib/aarch64-linux-gnu` 目录下:
root@lima-dev2:~# ls -l /usr/lib/libc*
ls: cannot access '/usr/lib/libc*': No such file or directory
root@lima-dev2:~# ls -l /usr/lib/aarch64-linux-gnu/libc.so.6
-rwxr-xr-x 1 root root 1722984 May 1 02:11 /usr/lib/aarch64-linux-gnu/libc.so.6
ubuntu host aarch64 架构编译器,头文件搜索路径如下:
- /usr/include/aarch64-linux-gnu/ 和 /usr/lib/gcc/aarch64-linux-gnu/13/include : gcc 自身定义和使用的头文件目录
- /usr/include: 系统标准头文件目录
alizj@ubuntu:~$ ls -l /usr/lib/gcc/aarch64-linux-gnu/13/
total 24024
-rw-r--r-- 1 root root 3280 Sep 4 22:44 crtbegin.o
-rw-r--r-- 1 root root 3656 Sep 4 22:44 crtbeginS.o
-rw-r--r-- 1 root root 3832 Sep 4 22:44 crtbeginT.o
-rw-r--r-- 1 root root 1416 Sep 4 22:44 crtend.o
-rw-r--r-- 1 root root 1416 Sep 4 22:44 crtendS.o
-rw-r--r-- 1 root root 3928 Sep 4 22:44 crtfastmath.o
-rw-r--r-- 1 root root 1416 Sep 4 22:44 crtoffloadbegin.o
-rw-r--r-- 1 root root 1408 Sep 4 22:44 crtoffloadend.o
-rw-r--r-- 1 root root 1648 Sep 4 22:44 crtoffloadtable.o
drwxr-xr-x 1 root root 524 Jan 15 00:42 include
-rw-r--r-- 1 root root 3369448 Sep 4 22:44 libasan.a
-rw-r--r-- 1 root root 14848 Sep 4 22:44 libasan_preinit.o
lrwxrwxrwx 1 root root 39 Sep 4 22:44 libasan.so -> ../../../aarch64-linux-gnu/libasan.so.8
-rw-r--r-- 1 root root 208618 Sep 4 22:44 libatomic.a
lrwxrwxrwx 1 root root 41 Sep 4 22:44 libatomic.so -> ../../../aarch64-linux-gnu/libatomic.so.1
-rw-r--r-- 1 root root 107738 Sep 4 22:44 libbacktrace.a
lrwxrwxrwx 1 root root 38 Sep 4 22:44 libcc1.so -> ../../../aarch64-linux-gnu/libcc1.so.0
-rw-r--r-- 1 root root 3099922 Sep 4 22:44 libgcc.a
-rw-r--r-- 1 root root 53884 Sep 4 22:44 libgcc_eh.a
-rw-r--r-- 1 root root 132 Sep 4 22:44 libgcc_s.so
-rw-r--r-- 1 root root 72562 Sep 4 22:44 libgcov.a
-rw-r--r-- 1 root root 620414 Sep 4 22:44 libgomp.a
lrwxrwxrwx 1 root root 39 Sep 4 22:44 libgomp.so -> ../../../aarch64-linux-gnu/libgomp.so.1
-rw-r--r-- 1 root root 164 Sep 4 22:44 libgomp.spec
-rw-r--r-- 1 root root 1201118 Sep 4 22:44 libhwasan.a
-rw-r--r-- 1 root root 6440 Sep 4 22:44 libhwasan_preinit.o
lrwxrwxrwx 1 root root 41 Sep 4 22:44 libhwasan.so -> ../../../aarch64-linux-gnu/libhwasan.so.0
-rw-r--r-- 1 root root 221010 Sep 4 22:44 libitm.a
lrwxrwxrwx 1 root root 38 Sep 4 22:44 libitm.so -> ../../../aarch64-linux-gnu/libitm.so.1
-rw-r--r-- 1 root root 162 Sep 4 22:44 libitm.spec
-rw-r--r-- 1 root root 1175204 Sep 4 22:44 liblsan.a
-rw-r--r-- 1 root root 6264 Sep 4 22:44 liblsan_preinit.o
lrwxrwxrwx 1 root root 39 Sep 4 22:44 liblsan.so -> ../../../aarch64-linux-gnu/liblsan.so.0
lrwxrwxrwx 1 root root 61 Sep 4 22:44 liblto_plugin.so -> ../../../../libexec/gcc/aarch64-linux-gnu/13/liblto_plugin.so
-rw-r--r-- 1 root root 673462 Sep 4 22:44 libobjc.a
-rw-r--r-- 1 root root 701550 Sep 4 22:44 libobjc_gc.a
lrwxrwxrwx 1 root root 42 Sep 4 22:44 libobjc_gc.so -> ../../../aarch64-linux-gnu/libobjc_gc.so.4
lrwxrwxrwx 1 root root 39 Sep 4 22:44 libobjc.so -> ../../../aarch64-linux-gnu/libobjc.so.4
-rw-r--r-- 1 root root 362 Sep 4 22:44 libsanitizer.spec
-rw-r--r-- 1 root root 1534 Sep 4 22:44 libssp_nonshared.a
-rw-r--r-- 1 root root 6915858 Sep 4 22:44 libstdc++.a
-rw-r--r-- 1 root root 950348 Sep 4 22:44 libstdc++exp.a
-rw-r--r-- 1 root root 748174 Sep 4 22:44 libstdc++fs.a
lrwxrwxrwx 1 root root 14 Sep 4 22:44 libstdc++_libbacktrace.a -> libstdc++exp.a
lrwxrwxrwx 1 root root 41 Sep 4 22:44 libstdc++.so -> ../../../aarch64-linux-gnu/libstdc++.so.6
-rw-r--r-- 1 root root 422436 Sep 4 22:44 libsupc++.a
-rw-r--r-- 1 root root 2801138 Sep 4 22:44 libtsan.a
-rw-r--r-- 1 root root 4912 Sep 4 22:44 libtsan_preinit.o
lrwxrwxrwx 1 root root 39 Sep 4 22:44 libtsan.so -> ../../../aarch64-linux-gnu/libtsan.so.2
-rw-r--r-- 1 root root 1065066 Sep 4 22:44 libubsan.a
lrwxrwxrwx 1 root root 40 Sep 4 22:44 libubsan.so -> ../../../aarch64-linux-gnu/libubsan.so.1
# gcc 提供的头文件 /usr/include/aarch64-linux-gnu/
alizj@ubuntu:~$ ls -l /usr/include/aarch64-linux-gnu/
total 48
-rw-r--r-- 1 root root 4351 Aug 8 22:47 a.out.h
drwxr-xr-x 1 root root 644 Jan 14 23:55 asm
drwxr-xr-x 1 root root 4188 Jan 14 23:55 bits
drwxr-xr-x 1 root root 4 Jan 14 23:55 c++
-rw-r--r-- 1 root root 4251 Dec 2 04:52 expat_config.h
-rw-r--r-- 1 root root 14041 Apr 9 2024 ffi.h
-rw-r--r-- 1 root root 2748 Apr 9 2024 ffitarget.h
-rw-r--r-- 1 root root 3006 Aug 8 22:47 fpu_control.h
drwxr-xr-x 1 root root 120 Jan 14 23:55 gnu
-rw-r--r-- 1 root root 4430 Aug 8 22:47 ieee754.h
drwxr-xr-x 1 root root 56 Jan 14 23:55 openssl
drwxr-xr-x 1 root root 20 Jan 14 23:56 python3.12
drwxr-xr-x 1 root root 1190 Jan 14 23:55 sys
# 系统标准库 /usr/lib/aarch64-linux-gnu/
alizj@ubuntu:~$ ls -l /usr/lib/aarch64-linux-gnu/lib[cm].so
-rw-r--r-- 1 root root 291 Aug 8 22:47 /usr/lib/aarch64-linux-gnu/libc.so
-rw-r--r-- 1 root root 149 Aug 8 22:47 /usr/lib/aarch64-linux-gnu/libm.so
alizj@ubuntu:~$ ls -l /usr/lib/aarch64-linux-gnu/lib[cm].a
-rw-r--r-- 1 root root 5247070 Aug 8 22:47 /usr/lib/aarch64-linux-gnu/libc.a
-rw-r--r-- 1 root root 141 Aug 8 22:47 /usr/lib/aarch64-linux-gnu/libm.a
alizj@ubuntu:~$ ls -ld /usr/lib/aarch64-linux-gnu/ld*
-rwxr-xr-x 1 root root 203968 Aug 8 22:47 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
drwxr-xr-x 1 root root 8490 Jan 14 23:55 /usr/lib/aarch64-linux-gnu/ldscripts
Fedorat 40 Host 架构 x86_64-redhat-linux 的差异:
- 还提供 /lib64 目录,但是指向 /usr/lib64;
- 标准库 libc 位于 /usr/lib64 目录下;
- 其它架构的标准库位于 /usr/aarch64-redhat-linux/sys-root/fc40/usr/lib64/ 目录下
- 需要单独安装包 sysroot-aarch64-fc40-glibc-2.39-33.fc40.noarch
[root@d8e784ed1d22 ~]# ls -l /{bin,sbin,lib,lib64}
lrwxrwxrwx 1 root root 7 Jan 24 2024 /bin -> usr/bin
lrwxrwxrwx 1 root root 7 Jan 24 2024 /lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jan 24 2024 /lib64 -> usr/lib64
lrwxrwxrwx 1 root root 8 Jan 24 2024 /sbin -> usr/sbin
[root@d8e784ed1d22 ~]# ls -l /usr/lib64/libc.*
-rw-r--r-- 1 root root 6847798 Dec 23 00:00 /usr/lib64/libc.a
-rw-r--r-- 1 root root 253 Dec 23 00:00 /usr/lib64/libc.so
-rwxr-xr-x 1 root root 2449104 Dec 23 00:00 /usr/lib64/libc.so.6
[root@d8e784ed1d22 ~]# ls /usr/aarch64-linux-gnu/bin/
ar as ld ld.bfd nm objcopy objdump ranlib readelf strip
[root@d8e784ed1d22 ~]# ls /usr/aarch64-linux-gnu/sys-root/
[root@d8e784ed1d22 ~]# ls /usr/aarch64-redhat-linux/sys-root/fc40/usr/
include/ lib/ lib64/
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-redhat-linux/sys-root/fc40/usr/lib64/libc.*
-rw-r--r-- 1 root root 6411932 Dec 23 00:00 /usr/aarch64-redhat-linux/sys-root/fc40/usr/lib64/libc.a
-rw-r--r-- 1 root root 265 Dec 23 00:00 /usr/aarch64-redhat-linux/sys-root/fc40/usr/lib64/libc.so
-rw-r--r-- 1 root root 2364952 Dec 23 00:00 /usr/aarch64-redhat-linux/sys-root/fc40/usr/lib64/libc.so.6
交叉编译架构工具链 #
ubuntu x86_64 交叉编译器,库文件搜索路径:
- /usr/libexec/gcc-cross/x86_64-linux-gnu/13/
- 保存 gcc 内部调用的二进制
- /usr/lib/gcc-cross/x86_64-linux-gnu/13/
- 保存 gcc 提供的库,引用 /usr/x86_64-linux-gnu/lib 下的中的标准动态库,如 libatomic.so/libcc1.so 等
- /usr/x86_64-linux-gnu/13/bin/x86_64-linux-gnu/13/
- NO, 目录不存在
- /usr/x86_64-linux-gnu/bin
- 保存交叉编译架构的 binutils 二进制
- /usr/x86_64-linux-gnu/lib
- 保存交叉编译架构标准库文件
- /usr/lib/x86_64-linux-gnu/
- 保存链接器脚本和标准库的动态版本
- /lib
- /usr/lib
ubuntu x86_64 交叉编译器,头文件搜索路径:
- /usr/lib/gcc/x86_64-linux-gnu/13/include: gcc 自身定义和使用的头文件目录
- /usr/x86_64-linux-gnu/include:gcc 头文件 + 目标架构标准头文件(含内核)
交叉编译器使用 /usr/<target>
目录,如 /usr/x86_64-linux-gnu
,保存交叉编译工具链使用的二进制、头文件、标准库等:
# 交叉编译的第二 /usr 目录层次
alizj@ubuntu:~$ ls /usr/x86_64-linux-gnu/
bin include lib lib64
# 保存交叉编译版本的二进制工具
alizj@ubuntu:~$ ls -l /usr/x86_64-linux-gnu/bin/
total 48
lrwxrwxrwx 1 root root 29 Aug 7 18:15 ar -> ../../bin/x86_64-linux-gnu-ar
lrwxrwxrwx 1 root root 29 Aug 7 18:15 as -> ../../bin/x86_64-linux-gnu-as
lrwxrwxrwx 1 root root 31 Aug 7 18:15 gold -> ../../bin/x86_64-linux-gnu-gold
lrwxrwxrwx 1 root root 29 Aug 7 18:15 ld -> ../../bin/x86_64-linux-gnu-ld
lrwxrwxrwx 1 root root 33 Aug 7 18:15 ld.bfd -> ../../bin/x86_64-linux-gnu-ld.bfd
lrwxrwxrwx 1 root root 34 Aug 7 18:15 ld.gold -> ../../bin/x86_64-linux-gnu-ld.gold
lrwxrwxrwx 1 root root 29 Aug 7 18:15 nm -> ../../bin/x86_64-linux-gnu-nm
lrwxrwxrwx 1 root root 34 Aug 7 18:15 objcopy -> ../../bin/x86_64-linux-gnu-objcopy
lrwxrwxrwx 1 root root 34 Aug 7 18:15 objdump -> ../../bin/x86_64-linux-gnu-objdump
lrwxrwxrwx 1 root root 33 Aug 7 18:15 ranlib -> ../../bin/x86_64-linux-gnu-ranlib
lrwxrwxrwx 1 root root 34 Aug 7 18:15 readelf -> ../../bin/x86_64-linux-gnu-readelf
lrwxrwxrwx 1 root root 32 Aug 7 18:15 strip -> ../../bin/x86_64-linux-gnu-strip
# 保存交叉编译版本的标准库和内核头文件
alizj@ubuntu:~$ ls -l /usr/x86_64-linux-gnu/include/std*.h
-rw-r--r-- 1 root root 26902 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdbit.h
-rw-r--r-- 1 root root 2462 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdc-predef.h
-rw-r--r-- 1 root root 8155 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdint.h
-rw-r--r-- 1 root root 2800 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdio_ext.h
-rw-r--r-- 1 root root 34649 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdio.h
-rw-r--r-- 1 root root 41032 Apr 15 2024 /usr/x86_64-linux-gnu/include/stdlib.h
# 交叉编译版本的标准库(动态库+静态库)
alizj@ubuntu:~$ ls -l /usr/x86_64-linux-gnu/lib/lib[cm].so
-rw-r--r-- 1 root root 308 Apr 15 2024 /usr/x86_64-linux-gnu/lib/libc.so
-rw-r--r-- 1 root root 148 Apr 15 2024 /usr/x86_64-linux-gnu/lib/libm.so
alizj@ubuntu:~$ ls -l /usr/x86_64-linux-gnu/lib/lib[cm].a
-rw-r--r-- 1 root root 6112386 Apr 15 2024 /usr/x86_64-linux-gnu/lib/libc.a
-rw-r--r-- 1 root root 132 Apr 15 2024 /usr/x86_64-linux-gnu/lib/libm.a
# 交叉编译版本的标准库,保存动态链接版本的库,动态链接器和链接脚本
alizj@ubuntu:~$ ls -l /usr/lib/x86_64-linux-gnu/
total 6784
drwxr-xr-x 1 root root 18 Jan 15 20:57 bfd-plugins
drwxr-xr-x 1 root root 5434 Jan 11 22:22 gconv
-rwxr-xr-x 1 root root 236616 Aug 8 22:47 ld-linux-x86-64.so.2
drwxr-xr-x 1 root root 2648 Jan 15 20:57 ldscripts
-rw-r--r-- 1 root root 14408 Aug 8 22:47 libanl.so.1
-rw-r--r-- 1 root root 14624 Aug 8 22:47 libBrokenLocale.so.1
-rw-r--r-- 1 root root 60744 Aug 8 22:47 libc_malloc_debug.so.0
-rwxr-xr-x 1 root root 2125328 Aug 8 22:47 libc.so.6
-rw-r--r-- 1 root root 14408 Aug 8 22:47 libdl.so.2
-rw-r--r-- 1 root root 183024 Sep 9 21:21 libgcc_s.so.1
lrwxrwxrwx 1 root root 16 Apr 9 2024 libidn2.so.0 -> libidn2.so.0.4.0
-rw-r--r-- 1 root root 133192 Apr 9 2024 libidn2.so.0.4.0
-rw-r--r-- 1 root root 18712 Aug 8 22:47 libmemusage.so
-rw-r--r-- 1 root root 952616 Aug 8 22:47 libm.so.6
-rw-r--r-- 1 root root 1018144 Aug 8 22:47 libmvec.so.1
-rw-r--r-- 1 root root 100640 Aug 8 22:47 libnsl.so.1
-rw-r--r-- 1 root root 43736 Aug 8 22:47 libnss_compat.so.2
-rw-r--r-- 1 root root 14336 Aug 8 22:47 libnss_dns.so.2
-rw-r--r-- 1 root root 14336 Aug 8 22:47 libnss_files.so.2
-rw-r--r-- 1 root root 26912 Aug 8 22:47 libnss_hesiod.so.2
-rw-r--r-- 1 root root 14544 Aug 8 22:47 libpcprofile.so
-rw-r--r-- 1 root root 14408 Aug 8 22:47 libpthread.so.0
-rw-r--r-- 1 root root 68104 Aug 8 22:47 libresolv.so.2
-rw-r--r-- 1 root root 14624 Aug 8 22:47 librt.so.1
-rw-r--r-- 1 root root 47912 Aug 8 22:47 libthread_db.so.1
lrwxrwxrwx 1 root root 21 Apr 9 2024 libunistring.so.5 -> libunistring.so.5.0.0
-rw-r--r-- 1 root root 1755312 Apr 9 2024 libunistring.so.5.0.0
-rw-r--r-- 1 root root 14408 Aug 8 22:47 libutil.so.1
alizj@ubuntu:~$ ls -l /usr/x86_64-linux-gnu/lib64/ # 交叉编译版本的链接器
total 4
lrwxrwxrwx 1 root root 27 Apr 15 2024 ld-linux-x86-64.so.2 -> ../lib/ld-linux-x86-64.so.2
alizj@ubuntu:~$ ls /usr/libexec/gcc-cross/x86_64-linux-gnu/13/ # 交叉编译 GCC 自身二进制
cc1 collect2 liblto_plugin.so lto1 lto-wrapper
alizj@ubuntu:~$ ls -l /usr/lib/gcc-cross/x86_64-linux-gnu/13 # 交叉编译 GCC 自身使用的库和头文件
total 20884
-rw-r--r-- 1 root root 2448 Sep 15 19:33 crtbegin.o
-rw-r--r-- 1 root root 2752 Sep 15 19:33 crtbeginS.o
-rw-r--r-- 1 root root 2968 Sep 15 19:33 crtbeginT.o
-rw-r--r-- 1 root root 1168 Sep 15 19:33 crtend.o
-rw-r--r-- 1 root root 1168 Sep 15 19:33 crtendS.o
-rw-r--r-- 1 root root 4112 Sep 15 19:33 crtfastmath.o
-rw-r--r-- 1 root root 3768 Sep 15 19:33 crtprec32.o
-rw-r--r-- 1 root root 3776 Sep 15 19:33 crtprec64.o
-rw-r--r-- 1 root root 3768 Sep 15 19:33 crtprec80.o
drwxr-xr-x 1 root root 3530 Jan 15 20:57 include
-rw-r--r-- 1 root root 4984914 Sep 15 19:33 libasan.a
-rw-r--r-- 1 root root 3568 Sep 15 19:33 libasan_preinit.o
lrwxrwxrwx 1 root root 45 Sep 15 19:33 libasan.so -> ../../../../x86_64-linux-gnu/lib/libasan.so.8
-rw-r--r-- 1 root root 158816 Sep 15 19:33 libatomic.a
lrwxrwxrwx 1 root root 47 Sep 15 19:33 libatomic.so -> ../../../../x86_64-linux-gnu/lib/libatomic.so.1
-rw-r--r-- 1 root root 142090 Sep 15 19:33 libbacktrace.a
lrwxrwxrwx 1 root root 38 Sep 15 19:33 libcc1.so -> ../../../aarch64-linux-gnu/libcc1.so.0
-rw-r--r-- 1 root root 3093656 Sep 15 19:33 libgcc.a
-rw-r--r-- 1 root root 66708 Sep 15 19:33 libgcc_eh.a
-rw-r--r-- 1 root root 132 Sep 15 19:33 libgcc_s.so
-rw-r--r-- 1 root root 68002 Sep 15 19:33 libgcov.a
...
drwxr-xr-x 1 root root 212 Jan 15 20:57 plugin
总结:头文件搜索路径 #
总结: 先搜索 GCC 相关头文件目录,再搜索系统标准头文件目录。
对于 host 架构而言,系统标准库和头文件分别是 /usr/lib 和 /usr/include 目录:
- /usr/include/aarch64-linux-gnu/ 和 /usr/lib/gcc/aarch64-linux-gnu/13/include : gcc 自身定义和使用的头文件目录
- /usr/include: 系统标准头文件目录
对于交叉编译工具链,不存在 /usr/include/x86_64-linux-gnu/ 目录,gcc 相关和系统标准库头文件都位于:
- /usr/lib/gcc/x86_64-linux-gnu/13/include: gcc 自身定义和使用的头文件目录
- /usr/x86_64-linux-gnu/include:gcc 头文件 + 目标架构标准头文件(含内核)
对于 Fedora、CentOS 系列,安装交叉编译工具链后,还要安装 sysroot 包才能提供目标架构的头文件、库文件:
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-linux-gnu/
total 0
drwxr-xr-x 1 root root 92 Jan 22 07:59 bin
drwxr-xr-x 1 root root 0 May 13 2024 sys-root
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-linux-gnu/bin/
total 20056
-rwxr-xr-x 2 root root 1286616 May 13 2024 ar
-rwxr-xr-x 2 root root 2351968 May 13 2024 as
-rwxr-xr-x 4 root root 3426184 May 13 2024 ld
-rwxr-xr-x 4 root root 3426184 May 13 2024 ld.bfd
-rwxr-xr-x 2 root root 1362072 May 13 2024 nm
-rwxr-xr-x 2 root root 1514504 May 13 2024 objcopy
-rwxr-xr-x 2 root root 3455728 May 13 2024 objdump
-rwxr-xr-x 2 root root 1286616 May 13 2024 ranlib
-rwxr-xr-x 2 root root 890584 May 13 2024 readelf
-rwxr-xr-x 2 root root 1514504 May 13 2024 strip
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-linux-gnu/sys-root/ # 空目录
total 0
[root@d8e784ed1d22 ~]# rpm -qa |grep sysroot
sysroot-aarch64-fc40-glibc-2.39-33.fc40.noarch
# 安装 sysroot 包后,才会有交叉编译架构的头文件、标准库文件等类似于 /usr 的第二目录结构
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-redhat-linux/
total 0
drwxr-xr-x 1 root root 8 Jan 22 08:52 sys-root
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-redhat-linux/sys-root/
total 0
drwxr-xr-x 1 root root 6 Jan 22 08:52 fc40
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-redhat-linux/sys-root/fc40/
total 0
drwxr-xr-x 1 root root 30 Jan 22 08:52 usr
[root@d8e784ed1d22 ~]# ls -l /usr/aarch64-redhat-linux/sys-root/fc40/usr/
total 0
drwxr-xr-x 1 root root 2090 Jan 22 08:52 include
drwxr-xr-x 1 root root 42 Jan 22 08:52 lib
drwxr-xr-x 1 root root 1234 Jan 22 08:52 lib64
# 在编译时需要为链接器传入 --sysroot 参数来指定上面目录
aarch64-linux-gnu-gcc --sysroot=/usr/aarch64-redhat-linux/sys-root/fc40/
可以使用 cpp -v
命令或 echo 'main(){}' | gcc -E -v -
或 gcc -v -xc /dev/null -fsyntax-only
查看搜索路径:
alizj@ubuntu:/Users/alizj/docs/lang/c$ echo 'main(){}' | gcc -E -v -
...
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.
...
总结:库文件搜索路径 #
使用 gcc -print-search-dirs
打印库文件默认搜索路径(来源于默认链接脚本):
install: /usr/lib/gcc/aarch64-linux-gnu/13/
programs: =/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/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/
libraries: =/usr/lib/gcc/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/aarch64-linux-gnu/13/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/aarch64-linux-gnu/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/../lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../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/13/:/lib/aarch64-linux-gnu/:/lib/../lib/:/usr/lib/aarch64-linux-gnu/13/:/usr/lib/aarch64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/lib/:/usr/lib/gcc/aarch64-linux-gnu/13/../../../:/lib/:/usr/lib/
使用命令 echo 'main(){}' | gcc -E -v -
或者 gcc -v -xc /dev/null -fsyntax-only
查看编译时生效的头文件和库文件搜索路径:
alizj@ubuntu:/Users/alizj/docs/lang/c$ echo 'main(){}' | gcc -E -v -
...
/usr/libexec/gcc/aarch64-linux-gnu/13/cc1 -E -quiet -v -imultiarch aarch64-linux-gnu - -mlittle-endian -mabi=lp64 -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -dumpbase -
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.
# 0 "<stdin>"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "<stdin>"
main(){}
# GCC 内部调用二进制搜索路径
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/
交叉编译 makefile #
参考: 20240524-makefile-manual.md
交叉编译 pkg-config #
pkg-config 是一个管理编译和链接参数的工具,可以简化处理外部依赖库的工作。
pkg-config 是架构相关的,需要安装对应目录架构的 pkg-config 包,后续使用 target triplet prefix 来区分:
- pkgconf-pkg-config.x86_64
- pkgconf-pkg-config.aarch64
alizj@lima-dev2:~$ ls -l /usr/bin/pkg-config
lrwxrwxrwx 1 root root 7 Apr 24 2023 /usr/bin/pkg-config -> pkgconf
alizj@lima-dev2:~$ dpkg -S /usr/bin/pkgconf
pkgconf-bin: /usr/bin/pkgconf
alizj@lima-dev2:~$ dpkg -S /usr/bin/aarch64-linux-gnu-pkg-config
pkgconf:arm64: /usr/bin/aarch64-linux-gnu-pkg-config
除了用 -I 和 -L 手动指定路径外,还可以使用一些包提供的 pkg-config 机制和命令来自动查找要链接的库、头文件等编译参数:
- 它使用库开发者发布的 .pc 格式文件来自动生成 -I、-L 和 -l 参数。
- 库开发者使用
pkg-config --cflags --libs xxx
生成 gcc 的 -L 或 -l 参数(可以与 gcc、makefile 或 Autotools、CMake 等集成) - 主流构构建工具,如 CMake/autotools/meson/bazel, 都支持 pkg-config 来配置和管理动态链接库;
系统默认 .pc 文件路径:
alizj@ubuntu:~$ ls /usr/lib/pkgconfig/
alizj@ubuntu:~$ ls /usr/share/pkgconfig/
iso-codes.pc personality.d shared-mime-info.pc systemd.pc udev.pc xkeyboard-config.pc
alizj@ubuntu:~$ ls /usr/local/lib/pkgconfig
ls: cannot access '/usr/local/lib/pkgconfig': No such file or directory
alizj@ubuntu:~$ ls /usr/local/share/pkgconfig
ls: cannot access '/usr/local/share/pkgconfig': No such file or directory
示例:
CFLAGS="`pkg-config --cflags apophenia glib-2.0` -g -Wall -std=gnu11 -O3"
LDLIBS="`pkg-config --libs apophenia glib-2.0`"
# 等效为
CFLAGS="-I/home/b/root/include -g -Wall-std=gnu11 -O3"
LDLIBS="-L/home/b/root/lib -lweirdlib"
# 两者结合使用
gcc `pkg-config --cflags --libs gsl libxml-2.0` -o specific specific.c
# 等效为
gcc -I/usr/include/libxml2 -lgsl -lgslcblas -lm -lxml2 -o specific specific.c
示例: Makefile 中使用 pkg-config,假设依赖 glib 库:
# Compiler and flags
CC = gcc
CFLAGS = -Wall -Iinclude $(shell pkg-config --cflags glib-2.0) # 生成编译所需的参数,如 -Idir
# Directories
SRC_DIR = src
LIB_DIR = lib
EXT_LIB_DIR = ext_lib
# Source files
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
LIB_FILES = $(wildcard $(LIB_DIR)/*.c)
# Object files
OBJ_FILES = $(SRC_FILES:.c=.o) $(LIB_FILES:.c=.o)
# External libraries
EXT_LIBS = -L$(EXT_LIB_DIR) -lotherlib $(shell pkg-config --libs glib-2.0) # 生成链接所需参数,如 -Ldir -llib
# Output executable
OUTPUT = myprogram
# Default target
all: $(OUTPUT)
# Link object files
$(OUTPUT): $(OBJ_FILES)
$(CC) -o $@ $^ $(EXT_LIBS)
# Compile source files
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
# Clean up
clean:
rm -f $(SRC_DIR)/*.o $(LIB_DIR)/*.o $(OUTPUT)
.PHONY: all clean
交叉编译配置参数 autoconf #
对于 autoconf 项目,执行 ./configure 脚本时可以指定交叉编译参数:
- –build=build-type:构建机器的架构类型,缺省使用
config.guess
的结果; - –host=host-type:运行 autoconf 的机器架构类型,确实和 –build 一致;
- –target=target-type:编译生成的二进制的机器架构类型,缺省和 –host 一致;
示例:
# https://www.linuxfromscratch.org/lfs/view/development/chapter05/binutils-pass1.html
../configure --prefix=$LFS/tools \
--with-sysroot=$LFS \
--target=$LFS_TGT \
--disable-nls \
--enable-gprofng=no \
--disable-werror \
--enable-new-dtags \
--enable-default-hash-style=gnu
# --prefix 指定安装路径
./configure --build=i686-pc-linux-gnu --host=m68k-coff --prefix=/path/to/install
make
make install
参考 #
- https://www.gnu.org/software/autoconf/manual/autoconf-2.68/html_node/Specifying-Target-Triplets.html
- rustc –print target-list
- LLVM 定义的 triple:https://llvm.org/doxygen/classllvm_1_1Triple.html
- https://www.linuxfromscratch.org/lfs/view/development/partintro/toolchaintechnotes.html