【问题标题】:How to Link a third Party Library (LibUSB) in CMake如何在 CMake 中链接第三方库 (LibUSB)
【发布时间】:2016-01-25 15:14:57
【问题描述】:

我正在尝试在项目中使用 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)

【问题讨论】:

  • 未定义的引用是链接器错误,所以它们是关于查找库,而不是标题。也许您可以展示您的项目如何使用 CMake 链接到 LibUSB?
  • 您是否从 libusb 链接二进制文件?
  • 看起来你误会了一些 libusb 的链接器标志
  • 包含路径(存储标头的位置)和库之间存在差异。您需要显式配置您的构建系统以链接到您正在使用的库。我在你的 CMake 代码中没有看到 target_link_libraries() 调用,所以你显然没有链接到 LibUSB。
  • @NathanOliiver 我改进了标题

标签: c++ cmake linker-errors


【解决方案1】:

一般来说,要链接第三方库,您需要添加编译器查找头文件的包含目录,以及链接器使用的库。
添加包含目录使用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_directorieslink_libraries。这些命令设置好后适用于项目的所有目标,省去了很多重复

您可以手动指定LIBUSB_INCLUDE_DIRLIBUSB_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 中添加变量或在 CMake 调用中添加 -DCMAKE_PREFIX_PATH=/path/to/add 来指定变量。

一个常见的陷阱是不删除构建目录中的 CMakeCache.txt 文件。 CMake 缓存 LIBUSB_INCLUDE_DIRLIBUSB_LIBRARY 的值,如果您调整前缀路径或搜索逻辑,它仍然不会重新评估变量值,而是坚持缓存的值。

【讨论】:

  • 很好的解释。小提示:目前include_directoriestarget_include_directories 更常见,尤其是对于CMake 初学者。最后一段实际上描述了开发人员调试过程——不应该以某种方式从“如何编写CMake脚本”内容中划定界限吗?
  • 这一切都很好,而且是一个非常有用的答案,但就我而言,当我和 find_path 似乎都不知道 DNF 将库放在哪里时,它并没有帮助。我认为那是一个单独的问题
  • @LordNibbler repoquery --list &lt;packagename&gt; 可能会有所帮助
  • @Tsyvarev 感谢您的提示,我也添加了include_directories。你是对的,缓存有点不相关,但这是一个常见的陷阱。这就是我提到它的原因。
  • @usr1234567 修复了它
【解决方案2】:

从您的项目CMakeLists.txt 文件中,我看不出您是如何尝试链接 libusb 的。我会做的方式如下:

target_link_libraries(project_name <other_dependencies> usb-1.0)

(澄清一下,我的意思是添加可执行文件的 CMakeLIsts.txt 文件)

您正在尝试从 &lt;libusb-1.0/...&gt; 导入,因此您需要链接 usb-1.0(该库总是从链接器命令中省略!)

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

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

希望这有点帮助。

【讨论】:

  • 对于我的项目rookery,我添加了target_link_libraries(rookery usb-1.0),但这给了我CMake Error at CMakeLists.txt:6 (target_link_libraries): Cannot specify link libraries for target "rookery" which is not built by this project.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2017-06-22
  • 2011-03-13
相关资源
最近更新 更多