交叉编译并链接到sysroot中的库-怎么了?

时间:2019-09-24 05:52:01

标签: cmake raspberry-pi cross-compiling gnu-toolchain wiringpi

我并不缺乏经验,但是对我来说很清楚,我在交叉编译和sysroots领域缺乏一些基本的了解。我希望有人可以向我提供我需要继续的信息。

我下载了一个预先构建的armhf gcc交叉编译器/工具链,它带有一个名为arm-linux-gnueabihf的目录,其中包含以下目录:

bin/
include/
lib/  - contains libstdc++.a, libgcc_s.so, but does NOT contain `libcrypt.so` or `libcrypt.so.1`, etc.
libc/

奇怪的是,libc包含另一组目录,看起来有点像一个单独的sysroot,但是我不确定为什么它在这里。我查看了其他工具链,包括我使用crosstool-ng构建自己的工具链,但没有看到类似的东西:

libc/
     etc/
     lib/  - contains files like libcrypt.so.1 / libcrypt-2.24.so
     sbin/
     usr/
         bin/
         include/
         lib/  - contains files like libc.a, libc.so, libcrypt.a, libcrypt.so, 
         libexec/
         sbin/
         share/
     var/

无论如何,我不确定这是否是一个问题,或者我是否必须将这两个sysroot合并为一个

我已将其安装在路径/cross-pi-gcc-9.1.0-1的Docker容器中。我正在使用cmake进行交叉编译,而我的toolchain.cmake文件引用了此工具链:

SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER /cross-pi-gcc-9.1.0-1/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER /cross-pi-gcc-9.1.0-1/bin/arm-linux-gnueabihf-g++)
SET(CMAKE_FIND_ROOT_PATH /cross-pi-gcc-9.1.0-1/arm-linux-gnueabihf/)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

这似乎足以使用交叉编译器(包括Boost)构建大多数代码。

作为此容器的一部分,我希望在sysroot中安装WiringPi,以便可以针对它进行构建和链接。

为此,我创建了一个自定义CMakeLists.txt文件,该文件成功构建并安装了WiringPi:

cmake_minimum_required(VERSION 3.0)
project(WiringPi)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
add_library(wiringPi SHARED ads1115.c <snip a bunch of .c files>)
target_include_directories(wiringPi PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(wiringPi PUBLIC ${CMAKE_THREAD_LIBS_INIT} crypt m rt)
install(TARGETS wiringPi DESTINATION lib)
install(FILES ads1115.h <snip a bunch of .h files>
        DESTINATION include)

这表示结果libwiringpi.so应该与libcryptlibpthreadlibmlibrt链接。而且,如果我在ldd上运行目标的libwiringpi.so工具,则确实确实将这些库显示为依赖项:

$ ldd libwiringPi.so 
    linux-vdso.so.1 (0x7eee6000)
    /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0x76f0a000)
    libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76ee0000)
    libcrypt.so.1 => /lib/arm-linux-gnueabihf/libcrypt.so.1 (0x76ea0000)
    libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76e1e000)
    librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76e07000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76cb9000)
    /lib/ld-linux-armhf.so.3 (0x76f43000)

我遇到的问题是我有一个应用程序,该应用程序使用cmake线链接到wirepi:

target_link_libraries(myapp wiringPi)

当我使用本机工具链在树莓派上构建它时,不需要显式链接到libcrypt。但是在我的Docker /跨编译器环境中,我在链接时收到此错误:

/cross-pi-gcc-9.1.0-1/bin/arm-linux-gnueabihf-g++     CMakeFiles/app.dir/main.cpp.o   -o myapp -lpthread -lwiringPi -lrt 
/cross-pi-gcc-9.1.0-1/bin/../lib/gcc/arm-linux-gnueabihf/9.1.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libcrypt.so.1, needed by /cross-pi-gcc-9.1.0-1/bin/../lib/gcc/arm-linux-gnueabihf/9.1.0/../../../../arm-linux-gnueabihf/lib/libwiringPi.so, not found (try using -rpath or -rpath-link)
/cross-pi-gcc-9.1.0-1/bin/../lib/gcc/arm-linux-gnueabihf/9.1.0/../../../../arm-linux-gnueabihf/lib/libwiringPi.so: undefined reference to `crypt@GLIBC_2.4'
collect2: error: ld returned 1 exit status

请注意,-lrt-lpthread似乎已自动包含在链接库列表中。但是-lcrypt不存在。

如果我复制/粘贴与该错误相对应的make VERBOSE=1输出,并在命令末尾手动添加-lcrypt,则它成功链接并且应用程序编译完成。

我意识到这是一个冗长的描述,但是我最终想要做的是发现我的知识上的漏洞,这使我无法理解为什么我需要在这种环境中将libcrypt显式链接到此应用程序中

我可能会错误地认为,由于libwiringpi.so已与libcrypt链接,因此不需要在顶层链接。如果那不是它的工作原理,请问有人能帮助我修复我的心理模型吗?

注意:我可以只添加target_link_libraries(myapp wiringPi crypt),但是我认为没有必要(在本机构建时不需要),我想了解更多有关该过程的信息,而不仅仅是找到解决方法。 / p>

1 个答案:

答案 0 :(得分:0)

自己解决这个问题...

看来sysroot中存在DSLContext目录是不寻常的,我检查了其他工具链,并且该目录始终与libc合并。因此,我最终放弃了该特定的工具链,而是使用lib构建了自己的工具链。这完全避免了该问题。很高兴了解我是如何做到这一点的,但是现在我必须继续前进。

请注意,仅使用crosstool-ng就可以成功-在我的情况下,无需指定CMAKE_SYSROOT和朋友。