如何在我的 C++ 项目中链接本地安装的 SDK 的静态库?

Posted

技术标签:

【中文标题】如何在我的 C++ 项目中链接本地安装的 SDK 的静态库?【英文标题】:How can I link locally installed SDK's static library in my C++ project? 【发布时间】:2020-11-23 23:58:10 【问题描述】:

我一直在开发一个依赖于RPLidar SDK 的 C++ 项目。我已经按照 README 中的说明安装了 SDK。 (仅供参考:我无法使用sudo make install 命令将其安装在/usr/local/ 目录中)。根据 SDK 文档:

通过 RPLIDAR SDK 开发时,开发者只需要包含 SDK 的 外部头文件(在 sdk\include 下)到他们自己的源代码中并链接 带有 SDK 静态库(rplidar_driver.lib 或 rplidar_driver.a)的应用程序。

所以,在我的CMakeLists.txt 中,我已经添加了:

include_directories(/home/milan/rplidar_sdk/sdk/sdk/include/)

但是,我找不到 rplidar_driver.librplidar_driver.h。这里是SDK的目录结构:

.
├── docs
│   ├── ReleaseNote.v1.10.0.md
│   |       ...
│   └── ReleaseNote.v1.9.1.md
├── LICENSE
├── README.md
├── sdk
│   ├── app
│   │   ├── frame_grabber
│   │   │   ├── AboutDlg.cpp
│   │   │   ├── AboutDlg.h
│   │   │   ├── drvlogic
│   │   │   │   ├── common.h
│   │   │   │   ├── lidarmgr.cpp
│   │   │   │   └── lidarmgr.h
│   │   │   ├── framegrabber.cpp
│   │   │   ├── framegrabber.h
│   │   │   ├── framegrabber.rc
│   │   │   ├── FreqSetDlg.cpp
│   │   │   ├── FreqSetDlg.h
│   │   │   ├── MainFrm.cpp
│   │   │   ├── MainFrm.h
│   │   │   ├── ref
│   │   │   │   └── wtl
│   │   │   │       ├── atlapp.h
│   │   │   │       ├── atlcrack.h
│   │   │   │       ├── atlctrls.h
│   │   │   │       ├── atlctrlw.h
│   │   │   │       ├── atlctrlx.h
│   │   │   │       ├── atlddx.h
│   │   │   │       ├── atldlgs.h
│   │   │   │       ├── atldwm.h
│   │   │   │       ├── atlfind.h
│   │   │   │       ├── atlframe.h
│   │   │   │       ├── atlgdi.h
│   │   │   │       ├── atlmisc.h
│   │   │   │       ├── atlprint.h
│   │   │   │       ├── atlresce.h
│   │   │   │       ├── atlres.h
│   │   │   │       ├── atlribbon.h
│   │   │   │       ├── atlscrl.h
│   │   │   │       ├── atlsplit.h
│   │   │   │       ├── atltheme.h
│   │   │   │       ├── atluser.h
│   │   │   │       ├── atlwince.h
│   │   │   │       └── atlwinx.h
│   │   │   ├── res
│   │   │   │   ├── rplidar.ico
│   │   │   │   └── Toolbar.bmp
│   │   │   ├── resource.h
│   │   │   ├── scanView.cpp
│   │   │   ├── scanView.h
│   │   │   ├── SerialSelDlg.cpp
│   │   │   ├── SerialSelDlg.h
│   │   │   ├── stdafx.cpp
│   │   │   ├── stdafx.h
│   │   │   ├── TcpChannelSelDlg.cpp
│   │   │   └── TcpChannelSelDlg.h
│   │   ├── Makefile
│   │   ├── simple_grabber
│   │   │   ├── main.cpp
│   │   │   └── Makefile
│   │   └── ultra_simple
│   │       ├── main.cpp
│   │       └── Makefile
│   ├── cross_compile.sh
│   ├── mak_common.inc
│   ├── mak_def.inc
│   ├── Makefile
│   ├── obj
│   │   └── Linux
│   │       └── Release
│   │           ├── sdk
│   │           │   └── src
│   │           │       ├── arch
│   │           │       │   └── linux
│   │           │       │       ├── net_serial.o
│   │           │       │       ├── net_socket.o
│   │           │       │       └── timer.o
│   │           │       ├── hal
│   │           │       │   └── thread.o
│   │           │       └── rplidar_driver.o
│   │           ├── simple_grabber
│   │           │   └── main.o
│   │           └── ultra_simple
│   │               └── main.o
│   ├── output
│   │   └── Linux
│   │       └── Release
│   │           ├── librplidar_sdk.a
│   │           ├── simple_grabber
│   │           └── ultra_simple
│   ├── sdk
│   │   ├── include
│   │   │   ├── rplidar_cmd.h
│   │   │   ├── rplidar_driver.h
│   │   │   ├── rplidar.h
│   │   │   ├── rplidar_protocol.h
│   │   │   └── rptypes.h
│   │   ├── Makefile
│   │   └── src
│   │       ├── arch
│   │       │   ├── linux
│   │       │   │   ├── arch_linux.h
│   │       │   │   ├── net_serial.cpp
│   │       │   │   ├── net_serial.h
│   │       │   │   ├── net_socket.cpp
│   │       │   │   ├── thread.hpp
│   │       │   │   ├── timer.cpp
│   │       │   │   └── timer.h
│   │       │   ├── macOS
│   │       │   │   ├── arch_macOS.h
│   │       │   │   ├── net_serial.cpp
│   │       │   │   ├── net_serial.h
│   │       │   │   ├── net_socket.cpp
│   │       │   │   ├── thread.hpp
│   │       │   │   ├── timer.cpp
│   │       │   │   └── timer.h
│   │       │   └── win32
│   │       │       ├── arch_win32.h
│   │       │       ├── net_serial.cpp
│   │       │       ├── net_serial.h
│   │       │       ├── net_socket.cpp
│   │       │       ├── timer.cpp
│   │       │       ├── timer.h
│   │       │       └── winthread.hpp
│   │       ├── hal
│   │       │   ├── abs_rxtx.h
│   │       │   ├── assert.h
│   │       │   ├── byteops.h
│   │       │   ├── event.h
│   │       │   ├── locker.h
│   │       │   ├── socket.h
│   │       │   ├── thread.cpp
│   │       │   ├── thread.h
│   │       │   ├── types.h
│   │       │   └── util.h
│   │       ├── rplidar_driver.cpp
│   │       ├── rplidar_driver_impl.h
│   │       ├── rplidar_driver_serial.h
│   │       ├── rplidar_driver_TCP.h
│   │       └── sdkcommon.h
│   └── workspaces
│       ├── vc10
│       │   ├── frame_grabber
│       │   │   ├── frame_grabber.vcxproj
│       │   │   └── frame_grabber.vcxproj.filters
│       │   ├── rplidar_driver
│       │   │   ├── rplidar_driver.vcxproj
│       │   │   └── rplidar_driver.vcxproj.filters
│       │   ├── sdk_and_demo.sln
│       │   ├── simple_grabber
│       │   │   ├── simple_grabber.vcxproj
│       │   │   └── simple_grabber.vcxproj.filters
│       │   └── ultra_simple
│       │       ├── ultra_simple.vcxproj
│       │       └── ultra_simple.vcxproj.filters
│       └── vc14
│           ├── frame_grabber
│           │   ├── frame_grabber.vcxproj
│           │   └── frame_grabber.vcxproj.filters
│           ├── rplidar_driver
│           │   ├── rplidar_driver.vcxproj
│           │   └── rplidar_driver.vcxproj.filters
│           ├── sdk_and_demo.sln
│           ├── simple_grabber
│           │   ├── simple_grabber.vcxproj
│           │   └── simple_grabber.vcxproj.filters
│           └── ultra_simple
│               ├── ultra_simple.vcxproj
│               └── ultra_simple.vcxproj.filters
└── tools
    └── cp2102_driver
        └── CP210x_Windows_Drivers.zip

现在,在我的main.cpp 中,我有这行:#include <rplidar.h>。我可以在我的项目的build 目录下成功运行cmake .. 命令。但是,在运行 make 命令时,它给了我这个错误:

In file included from /home/milan/<project>/src/main.cpp:3:0:
/home/milan/rplidar_sdk/sdk/sdk/include/rplidar.h:38:10: fatal error: hal/types.h: No such file or directory
 #include "hal/types.h"
          ^~~~~~~~~~~~~
compilation terminated.
CMakeFiles/<project>.dir/build.make:81: recipe for target 'CMakeFiles/<project>.dir/src/main.cpp.o' failed
make[2]: *** [CMakeFiles/<project>.dir/src/main.cpp.o] Error 1
CMakeFiles/Makefile2:94: recipe for target 'CMakeFiles/<project>.dir/all' failed
make[1]: *** [CMakeFiles/<project>.dir/all] Error 2
Makefile:102: recipe for target 'all' failed
make: *** [all] Error 2

这是我完整的CMakeLists.txt

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)

project(<project>)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

include_directories(include)
include_directories(/home/milan/rplidar_sdk/sdk/sdk/include/)

add_executable($PROJECT_NAME src/main.cpp)

我该如何解决这个问题?

【问题讨论】:

我认为您不应该只从 SDK 中获取文件。为什么make install 不起作用? 您使用什么链接器来构建您的最终可执行文件?您需要在最后一步为其提供 lib 文件和目录。 @Botje,我尝试运行sudo make install,但它给了我这个错误:make: *** No rule to make target 'install'. Stop 文档也是错误的。 sdk编译成librplidar_sk.a,是一个静态库 @Abel,对不起,但由于我对CMake 的经验还不够丰富,所以我没有得到你的问题。我所做的只是在我的项目的build 目录中运行cmake .. 然后make 命令。我有 Ubuntu 18.04 LTS、cmake version 3.18.0g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 【参考方案1】:

由于您已经编译了库,因此创建一个引用 sdk/includesdk/src 目录作为包含路径的 IMPORTED 目标:

add_library(rplidar STATIC IMPORTED)
set_property(TARGET rplidar
  PROPERTY IMPORTED_LOCATION /home/milan/rplidar_sdk/output/Linux/Release/librplidar_sdk.a)
target_include_directories(rplidar INTERFACE
  /home/milan/rplidar_sdk/sdk/sdk/include/
  /home/milan/rplidar_sdk/sdk/sdk/src/)

您甚至可能需要将sdk/arch/linux 目录添加到包含路径。

现在您可以通过以下方式将该库链接到您的主文件:

target_link_libraries($PROJECT_NAME rplidar)

【讨论】:

非常感谢您的快速回复。但是,现在,我收到了这个错误:main.cpp:3:10: fatal error: rplidar.h: No such file or directory #include &lt;rplidar.h&gt; ^~~~~~~~~~~ compilation terminated. 我什至尝试在target_include_directories 中添加/home/milan/rplidar_sdk/sdk/obj/Linux/Release/sdk/src/arch/linux/。但是,这也不起作用。 我想我之前尝试的时候没有刷新过这个页面。现在,它正在工作。添加target_link_libraries($PROJECT_NAME rplidar) 后我能够构建。对此感到抱歉,非常感谢您的帮助:) 您是否注意到该类位于rp::standalone::rplidar 命名空间中? use namespace rp::standalone::rplidar; 并按原样使用该代码或将命名空间别名为短名称(using rplidar = rp::standalone::rplidar;)并使用命名空间(例如rplidar::RPlidarDriver::CreateDriver)引用它的函数和所有相关事物 你可以阅读IMPORTED libraries。 IMPORTED_LOCATION 告诉 CMake 预建库在哪里。通过标记包含目录 INTERFACE(或 PUBLIC),它们会自动传播到与其链接的目标。请参阅Modern CMake 和It's time to do CMake right 以获得一些解释。 @Milan 您可以随时通过发送文档补丁或提出项目问题来支付费用!【参考方案2】:

如果有人直接寻找更新后的CMakeLists.txt,那么就是这里(特别感谢@Botje):

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)

project(<project_name>)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
SET(CMAKE_CXX_FLAGS -pthread)

include_directories(include)
add_executable($PROJECT_NAME src/main.cpp src/another_src_file.cpp)

## RPLidar
# Update the following path variable as per the RPLidar SDK installation in your system!
set(RPLIDAR_SDK_PATH "/home/milan/rplidar_sdk/")

add_library(rplidar STATIC IMPORTED)

set_property(TARGET rplidar
  PROPERTY IMPORTED_LOCATION $RPLIDAR_SDK_PATH/sdk/output/Linux/Release/librplidar_sdk.a)

target_include_directories(rplidar INTERFACE
  $RPLIDAR_SDK_PATH/sdk/sdk/include/
  $RPLIDAR_SDK_PATH/sdk/sdk/src/)

target_link_libraries($PROJECT_NAME rplidar)

注意:首先,您必须构建rplidar_sdk

【讨论】:

以上是关于如何在我的 C++ 项目中链接本地安装的 SDK 的静态库?的主要内容,如果未能解决你的问题,请参考以下文章

如何在我现有的项目中使用 AgoraLive 完整 SDK

当您的外部 SDK 只有 .dll、.lib、.h 文件时如何链接和构建项目

将共享对象链接到其他共享对象 C++ 项目

如何将 .dll 库与 C++ VS 项目链接?

如何在 iPhone SDK 中使用自定义字体? [复制]

Travis-CI 在我的项目中使用 xcodebuild 构建/链接问题