在macOS上用Clang交叉编译C项目为PE32+可执行文件遇报错
解决交叉编译PE32+时找不到-lgcc/-lgcc_eh的问题
问题根因
你指定了x86_64-unknown-windows-gnu目标,Clang默认会尝试链接GCC的运行时库,但你的环境里缺少对应Windows目标的GCC库——要么是手动下载的mingw工具链路径配置错误,要么是LLD没找到mingw自带的gcc库文件。
具体解决方案
1. 安装完整的mingw-w64工具链(推荐)
放弃手动下载mingw,直接用Homebrew安装,它会自动配置好路径:
brew install mingw-w64
安装完成后,mingw的库路径默认是/usr/local/opt/mingw-w64/x86_64-w64-mingw32/lib,把编译命令里手动指定的mingw路径替换成这个即可。
2. 手动指定gcc库搜索路径
如果不想重新安装,直接在编译命令里添加gcc库的具体路径(替换成你mingw中gcc的实际版本路径,比如13.2.0):
/usr/local/opt/llvm/bin/clang \ --target=x86_64-unknown-windows-gnu \ -Wl,-e,_KernMain \ -o kernel.exe # PE可执行文件后缀用.exe,不要用.o src/Kernel/Kernel.c \ src/Kernel/Memory/KernMem.c \ src/Kernel/Graphics/KernGraphics.c \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/ \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/X64 \ -I/Users/kernel/Documents/edk2-master/edk2/KernelOSPkg/src/Common \ -I/usr/local/opt/mingw-w64/x86_64-w64-mingw32/include \ -L/usr/local/opt/mingw-w64/x86_64-w64-mingw32/lib \ -L/Users/kernel/Documents/edk2-master/edk2/MdePkg/Library/ \ -L/usr/local/lib \ -L/usr/local/opt/mingw-w64/lib/gcc/x86_64-w64-mingw32/13.2.0 \ -fuse-ld="/usr/local/opt/llvm/bin/ld.lld"
3. 跳过gcc库(代码无依赖时)
如果你的内核代码没用到GCC的异常处理和特定运行时,可以直接让Clang跳过这些库,手动指定标准库:
/usr/local/opt/llvm/bin/clang \ --target=x86_64-unknown-windows-gnu \ -Wl,-e,_KernMain \ -o kernel.exe \ src/Kernel/Kernel.c \ src/Kernel/Memory/KernMem.c \ src/Kernel/Graphics/KernGraphics.c \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/ \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/X64 \ -I/Users/kernel/Documents/edk2-master/edk2/KernelOSPkg/src/Common \ -I/usr/local/opt/mingw-w64/x86_64-w64-mingw32/include \ -L/usr/local/opt/mingw-w64/x86_64-w64-mingw32/lib \ -L/Users/kernel/Documents/edk2-master/edk2/MdePkg/Library/ \ -L/usr/local/lib \ -fuse-ld="/usr/local/opt/llvm/bin/ld.lld" \ -nostdlib -lc -lm
4. 改用UEFI专属目标(编译UEFI内核时)
从你引入edk2头文件来看,应该是开发UEFI内核,直接用x86_64-unknown-windows-uefi目标更合适,Clang对UEFI的支持更完善,无需依赖gcc库:
/usr/local/opt/llvm/bin/clang \ --target=x86_64-unknown-windows-uefi \ -Wl,-e,KernMain # UEFI入口点不需要下划线前缀 -o kernel.efi \ src/Kernel/Kernel.c \ src/Kernel/Memory/KernMem.c \ src/Kernel/Graphics/KernGraphics.c \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/ \ -I/Users/kernel/Documents/edk2-master/edk2/MdePkg/Include/X64 \ -I/Users/kernel/Documents/edk2-master/edk2/KernelOSPkg/src/Common \ -fuse-ld="/usr/local/opt/llvm/bin/ld.lld"
额外提醒
- 输出文件后缀:普通Windows PE用
.exe,UEFI镜像用.efi,不要用.o(.o是中间目标文件,不是可执行文件)。 - 入口点差异:
windows-gnu目标需要给入口点加下划线前缀,windows-uefi目标不需要。
内容的提问来源于stack exchange,提问作者kernel_dev
相关产品推荐
相关产品推荐

