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

Cmake 交叉编译并链接到sysroot中的库-what';怎么了?,cmake,raspberry-pi,cross-compiling,gnu-toolchain,wiringpi,Cmake,Raspberry Pi,Cross Compiling,Gnu Toolchain,Wiringpi,我并不缺乏经验,但我很清楚,我在交叉编译和系统根方面缺乏一些基本的理解。我希望有人能提供我继续下去所需要的宝贵信息 我下载了一个预构建的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/

我并不缺乏经验,但我很清楚,我在交叉编译和系统根方面缺乏一些基本的理解。我希望有人能提供我继续下去所需要的宝贵信息

我下载了一个预构建的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
还包含另一组目录,看起来有点像一个单独的系统根目录,但我不知道它为什么在这里。我查看了其他工具链,包括我用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/
无论如何,我不确定这是否是一个问题,或者我是否必须将这两个系统根合并为一个

我已经在路径
/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)
我遇到的问题是,我有一个应用程序,它使用cmake行链接wiringpi,如下所示:

target_link_libraries(myapp wiringPi)
当我使用本机工具链在raspberry pi上构建它时,我不需要显式链接
libcrypt
。但在我的Docker/cross compiler环境中,我在链接时遇到以下错误:

/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
,它就不需要在顶层链接。如果不是这样的话,有没有人能帮我修复我的心智模型


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

自己回答这个问题

看来sysroot中存在
libc
目录是不寻常的,我检查了其他工具链,它总是与
lib
合并。因此,我放弃了那个特定的工具链,转而使用
crosstool ng
构建了自己的工具链。这完全避免了这个问题。我很高兴能理解我是如何让这一切运转起来的,但现在我必须继续前进


请注意,我只使用了
CMAKE\u SYSROOT
就取得了成功-在我的例子中,不需要指定
CMAKE\u FIND\u ROOT\u PATH
和朋友。

“我可能会错误地认为,既然
libwiringpi.so
已经链接到
libcrypt
,它就不需要在顶级链接。”-仔细阅读警告:它说
libcrypt.so.1
libwiringPi.so
所需要的,但它找不到
libcrypt.so.1
,因为它不在RPATH中。顺便说一句,如果
/cross-pi-gcc-9.1.0-1/arm-linux-gnueabihf/
是一个sysroot,那么将其分配给而不是
CMAKE\u FIND\u ROOT\u PATH
@Tsyvarev,这是否意味着链接器使用RPATH?我认为这是用来在运行时设置搜索路径,而不是在链接时?我最好温习一下这个地区。我也会试试你建议的改变-谢谢。编辑:另外,我不能100%确定是什么让系统根成为系统根-
/cross-pi-gcc-9.1.0-1/arm-linux-gnueabihf/
包含一些预构建的交叉编译库(如前所述),我一直在安装boost等,所以我猜它是一个sysroot?@Tsyvarev我用
CMAKE\u sysroot
替换了
CMAKE\u-FIND\u-ROOT\u-PATH
,虽然这对交叉编译Boost有效,但它在WiringPi上失败了,因为
ld
无法找到
crt1.o
。看起来该文件位于
libc
文件夹中(结构见上文),但
CMAKE_SYSROOT
只采用一条路径,因此我需要手动将
libc
子目录与主系统根目录合并以使其工作吗?而
CMAKE_FIND_ROOT_path
有效地重新根目录CMAKE搜索的每条路径(使用
find.*
调用),
CMAKE\u SYSROOT
对CMAKE和编译器/链接器执行相同的操作:也就是说,传递到链接器的每个路径(对象文件除外)都由SYSROOT预加。
/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