c++ - CMake find_* 不搜索子目录

标签 c++ linux cmake cross-compiling

我一直在尝试让我的交叉编译工具链从我的 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/

相关文章:

cmake - 如何正确使用 target_include_directories 和包含列表

c++ - Arduino eInk Image2LCD - c 数组的大小

linux - 如何管道虚拟文件?

c++ - 如何为 Linux 开发设置头文件和库

c - Linux 管道 : Bad file descriptor in functions read and write

c - 如何使用 cmake 和 find_package 在 macOS 上链接到 FreeGlut 而不是 Glut?

c++ - 是否有用于对 vector 元素进行成对比较的标准算法?

c++ - 在类对象段错误中使用 boost::interprocess ,为什么?

C++ 无法识别我在 object.cpp 中的更改

c++ - CMake:不支持的 GNU 版本 -- 不支持高于 8 的 gcc 版本