【发布时间】:2020-12-16 20:37:06
【问题描述】:
我一直在尝试让我的交叉编译工具链从我的 WSL Ubuntu 到 RasberryPi 工作。 由于我的 RaspberryPi 4B 的 GCC 版本是 8.3.0,我最近尝试使用来自 here 的 Buster 工具链。 我当前的文件夹结构如下所示:
Test
-> CMakeLists.txt
-> main.cpp
Toolchain
-> arm-linux-gnueabihf
-> bin
-> include
-> lib
-> libexec
-> share
raspi_root
-> lib
-> usr
Test 文件夹包含一个简单的测试项目,以使工具链正常工作。真正的目标项目要大一些。工具链是从存储库下载的交叉编译器工具链,最后 raspi_root 文件夹是来自 Raspberry Pi 的 lib 和 usr 文件夹的副本。
main.cpp 看起来很基本:
#include <iostream>
#include <bluetooth>
int main(int argc, char** argv)
{
std::cout << "Hello World" << std::endl;
}
请注意,它包含蓝牙标头,因为这是我遇到问题的库之一。
我的 CMakeLists.txt 看起来像这样:
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SYSTEM_NAME Linux)
set(COMPILER_PREF "/home/user/workspace/toolchain/bin/arm-linux-gnueabihf-")
SET(CMAKE_C_COMPILER "${COMPILER_PREF}gcc")
set(CMAKE_CXX_COMPILER "${COMPILER_PREF}g++")
set(SYSROOT "${SOURCE_DIR}/../raspi_root")
set(CMAKE_FIND_ROOT_PATH "${SYSROOT}")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
cmake_minimum_required(VERSION 3.0) # setting this is required
set(project_target Test)
project(${project_target}) # this sets the project name
set(SOURCES main.cpp)
find_library(BLUETOOTH bluetooth REQUIRED)
add_executable(${project_target} ${SOURCES})
set_property(TARGET ${project_target} PROPERTY CXX_STANDARD 17)
target_link_libraries(${project_target} PUBLIC
# ${SYSROOT}/usr/lib/arm-linux-gnueabihf/libbluetooth.so
${BLUETOOTH}
)
我试图让它尽可能简单,只让它使用工具链编译我的 hello world 程序并链接蓝牙库以使其在我的 Raspberry Pi 上工作。
现在出现以下问题:
Wenn 我做cmake . 它没有找到蓝牙库文件:
Please set them or make sure they are set and tested correctly in the CMake files:
BLUETOOTH
linked by target "Test" in directory /home/user/workspace/Test
他们就在${SYSROOT}/usr/lib/arm-linux-gnueabihf下面
只能找到像 ${SYSROOT}/usr/lib 或 ${SYSROOT}/lib 这样的传统目录中的库。当我从这些目录之一创建到 libbluetooth.so 的符号链接时,cmake 似乎找到了该库,尽管稍后在链接时出现了其他错误。
我还尝试通过将完整的库路径放在target_link_libraries 下替换find_library,但随后找到了库,但标题当然丢失了。我想这些必须单独包含在内。
但是,我的问题是,为什么 CMake 的 find_* 函数不能浏览更多的子目录?链接 boost-libraries 时也会发生这种情况。 find_package(boost) 找到标头但不链接库。
___ 编辑:___
感谢 Tsyvarev,我可以成功编译并执行我的 hello world 程序。现在,对于下一步,我想包含在我的其他项目中导致最多问题的 boost 线程库。
所以我将#include <boost/thread.hpp> 添加到我的main.cpp 和find_package(Boost COMPONENTS thread REQUIRED),${Boost_INCLUDE_DIRS} 到target_include_directories 和${Boost_LIBRARIES} 到我的CMakeLists.txt 中的target_link_libraries。现在它使用cmake . -DCMAKE_TOOLCHAIN_FILE=Toolchain 找到我的库并生成构建文件。但是使用make 我得到以下链接错误:
<path to toolchain linker>/ld: warning: librt.so.1, needed by ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so, not found (try using -rpath or -rpath-link)
<path to toolchain linker>/ld: warning: libpthread.so.0, needed by ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so, not found (try using -rpath or -rpath-link)
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_setspecific@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_condattr_setclock@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_key_create@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_join@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_detach@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_getspecific@GLIBC_2.4'
<path to toolchain linker>/ld: ../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so: undefined reference to `pthread_create@GLIBC_2.4'
<path to toolchain linker>/ld: /home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf/libboost_chrono.so: undefined reference to `clock_gettime@GLIBC_2.4'
我认为一旦正确找到库,未定义的引用就会被解析? CMakeCache.txt 说找到的线程库是libpthread.a 而不是libpthread.so。此外,在运行make VERBOSE=1 时,这是链接命令(为了便于阅读而中断):
/home/felix/workspace/toolchain/bin/arm-linux-gnueabihf-g++
-rdynamic CMakeFiles/Test.dir/main.cpp.o
-o Test
-Wl,-rpath,/home/felix/workspace/Test/../raspi_root/usr/lib/arm-linux-gnueabihf:/home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf
../raspi_root/usr/lib/arm-linux-gnueabihf/libboost_thread.so
/home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf/libboost_chrono.so
/home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf/libboost_system.so
/home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf/libboost_date_time.so
/home/felix/workspace/raspi_root/usr/lib/arm-linux-gnueabihf/libboost_atomic.so
../raspi_root/usr/lib/arm-linux-gnueabihf/libpthread.a
../raspi_root/usr/lib/arm-linux-gnueabihf/libbluetooth.so
我是否需要让 CMake 搜索共享库而不是静态库?我该怎么做?如果没有,我错过了什么?
感谢您的帮助。
【问题讨论】:
-
“但是,我的问题是,为什么 CMake 的 find_* 函数不能浏览更多的子目录?” - 因为它是designed so。
find_library和其他find_*函数的搜索机制不是递归的。有像/usr这样的已知系统安装前缀,像lib/这样的库前缀,所以CMake 只在那里查找。如果您希望 CMake 在${SYSROOT}/usr/lib/arm-linux-gnueabihf下搜索,则添加适当的目录进行搜索。例如。set(CMAKE_LIBRARY_PATH "/usr/lib/arm-linux-gnueabihf"). -
另请注意,在 CMake 工具链中的设置通常与
CMakeLists.txt文件分离。从SET(CMAKE_SYSTEM_NAME ...)到SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ...)的行通常位于工具链文件 中,由-DCMAKE_TOOLCHAIN_FILE=<path/to/file>选项指定到cmake。有关交叉编译的更多信息,请参阅documentation。 -
首先非常感谢您的快速响应!关于工具链的分离,我按照你的建议做了。据我了解,这只是为了有一个通用的 cmake 文件来本地构建项目,并且根据我选择的交叉编译环境,我可以选择相应的工具链文件。那是对的吗?或者通过变量指定工具链文件是否有其他值得注意的副作用,除了包括单独的变量(CMAKE_SYSTEM_NAME 到 CMAKE_FIND_ROOT_PATH_MODE)
-
除了将项目与构建环境分离之外,将特定于环境的变量放入单独的工具链文件中可以可靠地使用 try_compile 命令(和相关功能):当 CMake 为编译/链接配置新项目时检查,它也将
CMAKE_TOOLCHAIN_FILE变量传递给该项目,以便该项目使用与您的项目相同的工具链(及其设置)。
标签: c++ linux cmake cross-compiling