通过Bazel运行时,链接器无法在沙箱中运行,但在命令行中执行沙箱命令时,链接器有效

时间:2018-09-18 12:23:34

标签: gcc cross-compiling bazel toolchain

我正在尝试让我们的跨工具链(标准Yocto工具链)与Bazel一起使用。我遵循了https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain上的说明,但是每次尝试构建简单的测试程序时,链接器都会失败。它说

external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /lib64/libc.so.6
external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /usr/lib64/libc_nonshared.a
external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /lib64/ld64.so.1

sysroot设置正确。在沙盒外部运行链接器命令时(例如,使用--spawn_strategy=standalone或仅手动运行),该命令始终有效。奇怪的是,当我使用--debug_sandbox并从命令行运行发出的命令时,它也起作用。

我已经调试该问题两天了,包括strace调试Bazel守护程序并比较real-ld的输入,但是我没有发现任何可疑的地方。

执行环境之间一定有区别,但是我现在没有主意了。这是--debug_sandbox打印的失败命令:

(cd /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/execroot/__main__ && \
  exec env - \
    PATH=/home/sick/bin:/home/sick/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/sick/bin \
    PWD=/proc/self/cwd \
    TMPDIR=/tmp \
  /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/execroot/__main__/_bin/linux-sandbox -t 15 -w /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/sandbox/linux-sandbox/2/execroot/__main__ -w /tmp -w /dev/shm -D -- tools/compiler_e6500/e6500_gcc/powerpc64-fsl-linux-gcc -o bazel-out/e6500-fastbuild/bin/test '--sysroot=external/toolchain_e6500/sysroots/ppc64e6500-fsl-linux' -no-canonical-prefixes -pie -Wl,-z,relro,-z,now -Wl,-S -Wl,@bazel-out/e6500-fastbuild/bin/test-2.params)

您可以在https://github.com/jasal82/bazel-cross-eval

处查看工作区

如果需要,我可以提供工具链。


更新2018-09-25

在阅读了有关以下链接描述文件的答案后,我进行了更多调查。 this manual中的第4.4.2节说

  

如果配置了sysroot前缀,并且文件名以   /字符,正在处理的脚本位于   sysroot前缀,将在sysroot前缀中查找文件名。   否则,链接器将尝试在当前文件中打开文件。   目录。

显然,ld不认为该脚本位于sysroot前缀内,因此可以按原义使用(即相对于当前目录(可能是沙箱根目录)解析)。这将解释观察到的行为。但是,我仍然不明白为什么在手动运行命令(即不通过Bazel守护程序)时不发生这种情况。

这可能与CROSSTOOL文件中使用的相对sysroot路径有关吗?据我了解,由于沙箱操作,您无法指定sysroot的绝对路径。建议在Bazel中处理此问题的方法是什么?我希望避免修补工具链。

1 个答案:

答案 0 :(得分:1)

在您的sysroot中查看lib.so。可能看起来像这样:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 )

将其中的路径更改为相对于libc.so所在的目录。您必须对libm.solibpthread.so执行类似的操作。

在评估脚本是否在sysroot中之前,GNU链接程序先解析符号链接。当前的Bazel Linux沙箱实现可对所有操作的输入进行符号链接服务器场。因此,libc.so.6链接描述文件被检测到位于沙箱外部的sysroot中,而不位于沙箱内部。