我正在使用 Clang++ 进行从
x86_64-pc-windows-msvc
到x86_64-pc-linux-gnu
的交叉编译。
演示程序只是一个 C++ Hello World 程序,使用
iostream
。
为了在我的 Windows 主机上提供 Linux 环境,我将环境(头文件、.a、.so、...)从 WSL2 复制到主机。
你可以看到我在Powershell中使用的命令和输出,我的lld链接器无法打开这个
libm.so.6
动态库。
C:/wsl2/
是我创建的用于存储从wsl2手动复制的Linux环境的文件夹。
PS C:\Users\xxx\Desktop\cmake_demo\simple> clang++ --target=x86_64-pc-linux-gnu --sysroot="C:/wsl2" -o main ./main.cpp -fuse-ld=lld -LC:/wsl2/usr/lib/x86_64-linux-gnu
ld.lld: error: cannot open /lib/x86_64-linux-gnu/libm.so.6: no such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
我遇到了
libc_nonshared.a
的“类似”问题,当时,我将相关 .a
文件从 wsl2 复制到主机 Linux 环境并且它有效。
不幸的是,这次这个方法不起作用,我尝试将
libm.so.6
复制到C:/wsl2
文件夹。您可以看到它们不是符号链接,因为它们的 Length
不是 0
。
PS C:\wsl2\usr\lib> ls C:\wsl2\usr\aarch64-linux-gnu\lib | findstr libm
-a---- 2/23/2022 12:26 PM 1445378 libm.a
-a---- 2/23/2022 12:26 PM 551064 libm.so
-a---- 4/16/2024 3:40 PM 940560 libm.so.6
Directory: C:\wsl2\usr\aarch64-linux-gnu\lib
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2024 3:40 PM 940560 libm.so.6
Directory: C:\wsl2\usr\lib
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2024 3:40 PM 940560 libm.so.6
Directory: C:\wsl2\usr\lib\x86_64-linux-gnu
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2024 3:40 PM 940560 libm.so.6
Directory: C:\wsl2\usr\lib64\x86_64-linux-gnu
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2024 3:40 PM 940560 libm.so.6
我猜这是因为Windows平台上缺少动态链接器。 (
.a
是静态库,但.so
似乎是动态库)在Clang++中添加-v
选项后,下面列出了更多详细信息的输出:
...
C:/wsl2/usr/include/x86_64-linux-gnu
C:/wsl2/usr/include
End of search list.
"C:\\Program Files\\LLVM\\bin\\ld.lld" --sysroot=C:/wsl2 --eh-frame-hdr -m elf_x86_64
-dynamic-linker /lib64/ld-linux-x86-64.so.2
-o main "C:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11/../../..\\crt1.o"
"C:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11/../../..\\crti.o"
"C:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11\\crtbegin.o"
-LC:/wsl2/usr/lib/x86_64-linux-gnu
-LC:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11
-LC:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib64
-LC:/wsl2/usr/lib/../lib64
-LC:/wsl2/usr/lib/x86_64-linux-gnu/../../lib64
-LC:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11/../../..
-LC:/wsl2/usr/lib "C:\\Users\\hzhang3\\AppData\\Local\\Temp\\main-61818f.o"
-lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc "C:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11\\crtend.o" "C:/wsl2/usr/lib/gcc/x86_64-linux-gnu/11/../../..\\crtn.o"
ld.lld: error: cannot open /lib/x86_64-linux-gnu/libm.so.6: no such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
...
我注意到
/lib64/ld-linux-x86-64.so.2
被分配给 ld.lld
作为动态链接器,这是一个 Unix 动态链接器。
ld.lld
尝试在我的Windows主机上查找但找不到/lib/x86_64-linux-gnu/libm.so.6
这个类似Unix的东西,这并不奇怪。
我有几个问题要在这里讨论:
用 clang++ 从 Windows 交叉编译到 Linux 真的很蠢吗?
在这种情况下应该使用哪个动态链接器?因为在 Windows 主机上使用 Linux 动态链接器似乎是不可能的。 (路径不正确且动态链接器不存在)
我如何破解
lld
并让它绕过这个奇怪的动态链接器,以便它可以在特定路径(放置 libm.so.6
的位置)上找到它需要的东西?
从Windows到Linux x64进行交叉编译时,推荐使用哪种Linux环境?我尝试了 Cygwin,但无法通过其安装应用程序安装某些库。看起来 Cygwin 是一个用于构建本机 Windows 应用程序的环境(也称为从 Linux 到 Windows)。
将
libm.so
替换为 libm.so.6
即可解决此问题。
虽然链接器说找不到
libm.so.6
,但它寻找的真正文件是libm.so
。
顺便说一句,使用 Ubuntu docker 镜像有助于简化库结构,并避免在安装 Linux 环境时弄乱无用的文件,例如驱动程序。
这就是我的做法,不使用重型 wsl2。