【发布时间】:2017-04-19 09:07:00
【问题描述】:
我有一些关于我的嵌入式系统编译问题的相关问题。我的问题不仅是关于如何做某事,而是更多关于为什么,因为我有解决问题的方法(但也许有更好的解决方案?),但不知道为什么有些事情在某些条件下有效,而在某些情况下无效其他。我已经花了一些时间,但直到昨天我还是有点盲目地做事,反复试验,不知道自己在做什么。是时候停下来了!请帮忙。
场景
我想在 Zedboard 上为 Xilinx 的 Zynq ARM 处理器开发一个应用程序。该应用程序将涉及多线程、一些音频操作和 httpserver。所以我需要 pthread、alsa、sndfile 和 microhttpd 库。我用 yocto 创建了 rootfs。在原始 conf.local 文件中,我添加/修改了这些行:
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
MACHINE ?= "zedboard-zynq7"
PACKAGE_CLASSES ?= "package_deb"
EXTRA_IMAGE_FEATURES = "debug-tweaks eclipse-debug"
IMAGE_INSTALL_append = "libgcc alsa-utils mpg123 libstdc++ sthttpd libmicrohttpd libsndfile1"
LICENSE_FLAGS_WHITELIST = "commercial_mpg123"
我还必须在 bblayers.conf 中添加一些额外的层(当然还下载了它们):
meta-xilinx
meta-multimedia (from meta-openembedded)
meta-oe (from meta-openembedded)
meta-webserver (from meta-openembedded)
最后,我用 bitbake 生成了 core-image-minimal。
这与 Linux 内核以及其他单独编译的东西一起启动并正常工作。
问题
1。使用此 rootfs 的简单应用
它是 Zynq 的应用程序,所以我使用 XSDK,它是 Xilinx 的 SDK,基于 Eclipse。我创建了新的应用程序项目。在对话窗口中,我选择 Linux 作为平台,C++ 作为语言,并提供了解压后的 rootfs 的路径(正是系统通过 NFS 启动的那个)。我的rootfs路径是/home/stas/ZedboardPetalinuxFS(不是Petalinux,我刚用过,这个文件夹名还是一样)。这为在 rootfs 中的库和头文件搜索设置了正确的路径。
我从非常简单的事情开始:
#include <pthread.h>
int main()
{
int i;
i = 1;
return 0;
}
我还为链接器添加了 pthread 库(在 Eclipse 设置中)。此时链接命令:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread
此时它已编译。但是当我添加 sndfile 库时它会停止
#include <sndfile.h>
这是合理的,因为这个 rootfs 没有所有的头文件。我需要添加另一个路径来搜索标题。所以我在 yocto tmp 文件夹中添加了路径,其中包含构建 rootfs 所需的所有标题。我添加后,它再次编译成功。但是问题开始了,当我添加 sndfile 库进行链接时。这是链接命令和错误:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread -lsndfile
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lsndfile
我查看了 usr/lib 以检查 libsndfile.so 是否存在,但我发现只有 libsndfile.so.1 和 ibsndfile.so.1.27。但 pthread 也是如此,链接器不会为此抱怨。我决定手动创建 libsndfile.so(我将它链接到 libsndfile.so.1)。 Linker 不再抱怨它,而是开始抱怨它的依赖关系。因此,我还为所有依赖项及其依赖项创建了 .so 文件,并添加了它们以进行链接。然后就成功了。最后,链接命令如下所示:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lpthread -lvorbisenc -lvorbis -logg -lFLAC -lsndfile
所以第一个问题出现了——为什么我不需要 .so 文件用于 pthread,但需要它用于所有其他库?或更笼统地说——我什么时候需要 .so 文件,什么时候 .so.X 文件就足够了?
2。简单的应用程序 - 另一种方法
第一次尝试后,我想我应该再做一个图像,这次更适合开发。幸运的是,在 Yocto 中这很容易——我只需要修改一行:
EXTRA_IMAGE_FEATURES = "debug-tweaks eclipse-debug dev-pkgs"
dev-pkgs 选项为所有已安装的软件包添加 -dev 软件包。
所以现在我有了包含所有需要的标头的 rootfs,以及指向它们应该指向的位置的 .so 文件。
在编译之前,我删除了不必要的 Include 路径,只保留了 rootfs 中的一个,并删除了除 pthread 和 sndfile 之外的所有库。但后来我得到了新的错误:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" -o "test.elf" ./src/main.o -lsndfile -lpthread
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/libpthread.so.0
makefile:48: polecenia dla obiektu 'test.elf' nie powiodły się (commands for ‘test.elf’ did not succeed)
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find /usr/lib/libpthread_nonshared.a
我发现它在我的根文件夹中查找库。在 Google 中快速搜索(以及 SO:))告诉我应该设置 --sysroot 变量。所以我将它添加到 Eclipse 选项中(在链接器选项中的杂项卡中),如下所示:
--sysroot=/home/stas/ZedboardPetalinuxFS
所以现在链接器命令看起来像这样:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" --sysroot=/home/stas/ZedboardPetalinuxFS -o "test.elf" ./src/main.o -lsndfile -lpthread
一切都成功了!我还编写了使用 pthreads 和 sndfile 的简单示例,它也有效。但为什么?这引出了第二个问题: 为什么在这种情况下我需要 --sysroot 选项?我一般什么时候需要使用这个选项?为什么这次我不必将所有依赖项都添加到链接命令中?
3。另一个想法
此时,我有一个想法,如果我添加 --sysroot 选项,让 rootfs 填充旧的非开发图像,我想检查会发生什么。但这给了我新的错误:
arm-linux-gnueabihf-g++ -L"/home/stas/ZedboardPetalinuxFS/usr/lib" -L"/home/stas/ZedboardPetalinuxFS/lib" --sysroot=/home/stas/ZedboardPetalinuxFS -o "test.elf" ./src/main.o -lpthread -lvorbisenc -lvorbis -logg -lFLAC -lsndfile
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find crt1.o: No such file or directory
makefile:48: polecenia dla obiektu 'test.elf' nie powiodły się
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find crti.o: No such file or directory
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lpthread
/opt/Xilinx/SDK/2016.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabihf/5.2.1/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lm
那么第三个问题——这个错误是什么意思?
提前非常感谢!
【问题讨论】:
标签: c++ linux linker yocto zynq