如何在我的 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.lib
或 rplidar_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.0
和 g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
【参考方案1】:
由于您已经编译了库,因此创建一个引用 sdk/include
和 sdk/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 <rplidar.h> ^~~~~~~~~~~ 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 的静态库?的主要内容,如果未能解决你的问题,请参考以下文章