0

I have been working on a C++ project which depends on RPLidar SDK. I have already installed the SDK as per the instructions in the README. (FYI: I couldn't install it in the /usr/local/ directory using sudo make install command). As per the SDK documentation:

When developing via RPLIDAR SDK, developers only need to include SDK’s external header files (under sdk\include) into their own source code and link the application with SDK’s static library (rplidar_driver.lib or rplidar_driver.a).

So, in my CMakeLists.txt, I have already added:

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

However, I couldn't find rplidar_driver.lib or rplidar_driver.h. Here, is the directory structure of the 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

Now, in my main.cpp, I have this line: #include <rplidar.h>. I can successfully run cmake .. command in the build directory of my project. However, upon running make command, it's giving me this error:

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

Here is my complete 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)

How can I fix this?

Milan
  • 1,743
  • 2
  • 13
  • 36
  • I don't think you're supposed to just grab files from the SDK. Why didn't `make install` work? – Botje Nov 24 '20 at 00:22
  • what linker are you using to build your final executable? you need to feed it the lib file and directory at that last step. – Abel Nov 24 '20 at 00:23
  • @Botje, I tried running `sudo make install` but it gave me this error: `make: *** No rule to make target 'install'. Stop` – Milan Nov 24 '20 at 00:26
  • The documentation is wrong, too. The sdk compiles to `librplidar_sk.a`, which is a static library – Botje Nov 24 '20 at 00:26
  • @Abel, sorry but as I'm still not quite experienced with `CMake`, I did't get your question. All I'm doing is just running `cmake ..` and then `make` command in the `build` directory of my project. I have Ubuntu 18.04 LTS, `cmake version 3.18.0`, and `g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0` – Milan Nov 24 '20 at 00:29
  • @Botje, yup, I also found that library at `/home/milan/rplidar_sdk/sdk/output/Linux/Release` location and also tried using that library like this: `LINK_DIRECTORIES(/home/milan/rplidar_sdk/sdk/output/Linux/Release/) target_link_libraries(${PROJECT_NAME} /home/milan/rplidar_sdk/sdk/output/Linux/Release/librplidar_sdk.a)` But still, getting the same error. Reference: https://stackoverflow.com/questions/8774593/cmake-link-to-external-library – Milan Nov 24 '20 at 00:32

2 Answers2

1

Since you already compiled the library, create an IMPORTED target that references the sdk/include and sdk/src directories as include path:

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/)

You may even need to add the sdk/arch/linux directory to the include path.

And now you can link that library to your main file by doing:

target_link_libraries(${PROJECT_NAME} rplidar)
Botje
  • 26,269
  • 3
  • 31
  • 41
  • Thanks a lot for such a quick response. However, now, I'm getting this error: `main.cpp:3:10: fatal error: rplidar.h: No such file or directory #include ^~~~~~~~~~~ compilation terminated.` I even tried adding `/home/milan/rplidar_sdk/sdk/obj/Linux/Release/sdk/src/arch/linux/` in `target_include_directories`. But, that doesn't work either. – Milan Nov 24 '20 at 00:47
  • I think I had not refreshed this page while trying before. Now, it's working. I was able to build after adding `target_link_libraries(${PROJECT_NAME} rplidar)`. Sorry about that and thank you so much for you help :) – Milan Nov 24 '20 at 00:51
  • If possible, could you please redirect me to some good resources for CMake. I have a basic understanding but this one was/is very difficult. I didn't quite understand what exactly is happing in your answer. I'm still not that much experienced with CMake. Thank you so much in advance! – Milan Nov 24 '20 at 00:55
  • I think there is still missing something. Because until now, I had only mentioned `` header file in my `main.cpp` & after making the above-mentioned changes, I was able to build the project. However, now I wrote `RPlidarDriver* lidar = RPlidarDriver::CreateDriver();` from the README & upon trying to build, I'm getting errors: `main.cpp:9:5: error: ‘RPlidarDriver’ was not declared in this scope RPlidarDriver* lidar = RPlidarDriver::CreateDriver(); ^~~~~~` & `error: ‘lidar’ was not declared in this scope` & `error: ‘RPlidarDriver’ is not a class, namespace, or enumeration` – Milan Nov 24 '20 at 01:29
  • 1
    Did you notice that that class is in the `rp::standalone::rplidar` namespace? Either `use namespace rp::standalone::rplidar;` and use that code as-is or alias the namespace to something short (`using rplidar = rp::standalone::rplidar;`) and reference it the function and all associated things by using the namespace (eg `rplidar::RPlidarDriver::CreateDriver`) – Botje Nov 24 '20 at 08:23
  • 1
    You can read about [IMPORTED libraries](https://cmake.org/cmake/help/latest/command/add_library.html#imported-libraries). the IMPORTED_LOCATION tells CMake where the prebuilt library is. By marking the include directories INTERFACE (or PUBLIC), they are propagated to target that links with it automatically. See [Modern CMake](https://cliutils.gitlab.io/modern-cmake/) and [It's time to do CMake right](https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/) for some explanation. – Botje Nov 24 '20 at 08:25
  • yup, you are right. I completely missed that `namespace`. I think their documentation needs many corrections! Thanks a lot for pointing this out :) – Milan Nov 24 '20 at 19:42
  • Thank you so much Botje for sharing the important resource. Sure, I would check them out to improve my understanding as well as for updating hardcoded paths. – Milan Nov 24 '20 at 19:44
  • 1
    @Milan You can always pay it forward by sending documentation patches or raising issues on the project! – Botje Nov 24 '20 at 19:52
  • Yup, that's a good idea. Thanks for the suggestion. I would create a pull request with an updated README. Based on their GitHub page, it looks like they are not very active but still, I would give it a shot. – Milan Nov 24 '20 at 20:03
1

If someone is directly looking for the updated CMakeLists.txt then here it is (special thanks to @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)

Note: First, you have to build rplidar_sdk

Milan
  • 1,743
  • 2
  • 13
  • 36