我一直在尝试让我的交叉编译工具链从我的 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 文件夹是来自 lib
的拷贝。和 usr
Raspberry Pi 中的文件夹。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 上工作。现在出现以下问题:
温我愿意
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 的符号链接(symbolic link)时,cmake 似乎找到了该库,尽管稍后在链接时出现了其他错误。我也尝试替换
find_library
通过将完整的库路径放在 target_link_libraries
下但是后来找到了库,但是标题当然丢失了。我想这些必须单独包括在内。但是,我的问题是,为什么 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'
我认为一旦正确找到库, undefined reference 就会得到解决? 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 搜索共享库而不是静态库?我该怎么做?如果没有,我错过了什么?感谢您的帮助。
最佳答案
好的,感谢 Tsyvarev 对我所缺少的内容的快速提示。事实证明,答案比我想象的更明显。
正如 Tsyvarev 在评论中提到的那样,CMake 不会在指定的根目录中递归搜索库。相反,它搜索标准路径,例如/usr/lib、/lib 等。可以通过将它们附加到 CMAKE_LIBRARY_PATH
来添加更多搜索路径。如 documentation 中所述.所以为了解决我的错误,我做了以下事情:
我将所需的库路径附加到搜索路径。
...
set(SOURCES main.cpp)
set(CMAKE_LIBRARY_PATH
${CMAKE_LIBRARY_PATH}
"/lib/arm-linux-gnueabihf"
"/usr/lib/arm-linux-gnueabihf"
)
add_executable(${project_target} ${SOURCES})
...
然后我看到我忘记添加任何包含目录:target_include_directories(${project_target} PUBLIC
${SYSROOT}/usr/include/bluetooth
${SYSROOT}/usr/include/arm-linux-gnueabihf
)
我能够编译main.cpp
.至于编辑 :
为了正确链接 boost 线程库,我还必须链接它的依赖项。所以我放了:
find_package(Boost COMPONENTS thread REQUIRED)
...
target_include_directories(${project_target} PUBLIC
${SYSROOT}/usr/include/bluetooth
${SYSROOT}/usr/include/arm-linux-gnueabihf
${Boost_INCLUDE_DIRS}
)
target_link_libraries(${project_target} PUBLIC
rt
Threads::Threads
${Boost_LIBRARIES}
${BLUETOOTH}
)
关于c++ - CMake find_* 不搜索子目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63624827/