如何在 CMake 中链接第三方库(LibUSB)

问题描述 投票:0回答:3

我正在尝试在项目中使用 LibUSB。然而,每当我尝试使用基本的 libUSB 函数时,我都会收到以下错误:

...src/main/main.cpp.o: In function `main':
...src/main/main.cpp:10: undefined reference to `libusb_init'
...src/main/main.cpp:11: undefined reference to `libusb_set_debug'
collect2: error: ld returned 1 exit status

LibUSB-devel 包已安装(我使用的是 fedora 22),我的 IDE KDevelop 会查找并识别标头,一旦您添加了 import 语句,它就会提供 LibUSB 代码补全。我的 IDE 或 CMake(我的构建系统)中没有任何自定义包含行,因此我想知道需要做什么才能让 CMake 找到 LibUSB 标头。

这是

main.cpp
的内容,以防万一我搞砸了:

#include <iostream>
#include <libusb-1.0/libusb.h>

int main(int argc, char **argv) {
      libusb_init(NULL);
      libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);

      /*snip*/

      std::cout << "Hello, world! PTPID="  << std::endl;
      return 0;
}

以下是

CMakeLists.txt

../

cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_BUILD_TYPE Debug)

project(aProjectThatHasHadIt'sNameObcured)
add_subdirectory(src)

.../src/cmakelists.txt 只是添加子目录

.../src/main/

add_executable(main main.cpp)
c++ cmake linker-errors
3个回答
8
投票

一般来说,要链接第三方库,您需要添加编译器将在其中查找头文件的包含目录以及链接器使用的库。
要添加包含目录,请使用

target_include_directories
,要添加要链接到目标的库,请使用
target_link_libraries

对于 libUSB 和
testLibUSB.cpp
源文件,这将导致

add_executable(targetTestLibUSB testLibUSB.cpp)
target_include_directories(targetTestLibUSB ${LIBUSB_INCLUDE_DIR})
target_link_libraries(targetTestLibUSB ${LIBUSB_LIBRARY})

如果您有多个目标,您可能需要在定义任何目标之前使用

include_directories
link_libraries
。这些命令在设置后适用于项目的所有目标,并节省大量重复

您可以手动指定

LIBUSB_INCLUDE_DIR
LIBUSB_LIBRARY
的路径。但更灵活和可移植的是使用 CMake 内置机制来查找标头和库。
标题可以通过
find_path
搜索,库可以通过
find_library
搜索。
在你的情况下这可能是

find_path(LIBUSB_INCLUDE_DIR
  NAMES libusb.h
  PATH_SUFFIXES "include" "libusb" "libusb-1.0")
find_library(LIBUSB_LIBRARY
  NAMES usb
  PATH_SUFFIXES "lib" "lib32" "lib64")

PATH_SUFFIXES
是可选的。如果您已将库安装在默认位置,CMake 会自动找到它。否则指定
CMAKE_PREFIX_PATH
,CMake 也会在那里查找标头和库。您可以通过将变量添加到 CMake GUI 中或将
-DCMAKE_PREFIX_PATH=/path/to/add
添加到 CMake 调用来指定变量。

一个常见的陷阱是不删除构建目录中的 CMakeCache.txt 文件。 CMake 缓存

LIBUSB_INCLUDE_DIR
LIBUSB_LIBRARY
的值,如果您对前缀路径或搜索逻辑进行调整,它仍然不会重新评估变量值,而是坚持缓存的值。


5
投票

从您的项目

CMakeLists.txt
文件中,我并不清楚您如何尝试链接 libusb。我会做的方式如下:

target_link_libraries(project_name <other_dependencies> usb-1.0)

(为了澄清,我的意思是在其中添加可执行文件的 CMakeLIsts.txt 文件)

您正在尝试从

<libusb-1.0/...>
导入,因此您需要链接 usb-1.0(该库在链接器命令中always被省略!)

我使用的是 Fedora 23,也使用 KDevelop,并且不需要指定路径。特别是因为在我的系统上,之前答案中使用的所有环境变量无论如何都是 NULL。

要确认将来库的安装位置和方式,您可以执行以下操作:


locate libusb | grep .so

希望这对您有所帮助。


0
投票

自最近(2023 年 5 月)以来,出现了完全不同的替代方案: https://github.com/libusb/libusb-cmake

需要注意的一些事项:

  • 截至目前,CMake 导出/包不可用(即 CMake 的
    find_package
    将无法使用);
  • 这不受主线 libusb 维护者的正式支持,而是由 Libusb Org 托管。在 Github 上并得到社区的支持;
  • 这对于那些需要将 libusb 作为其项目的一部分作为
    subdirectory
    ;
  • 的人来说是最有用的
© www.soinside.com 2019 - 2024. All rights reserved.