0

I am attempting to integrate a C++ library I downloaded into a new project using CMake.

I downloaded the library ("downloaded_library"), created the build folder, and inside of it ran cmake .. and make. These both ran successfully, and than I navigated to the build folder and ran ./example to run the example file that came with the library. This also was successful, and so I hoped to add it to another project.

I added this working project into the 'libraries' folder of the following directory structure:

project
  -libraries
      -downloaded_library
          -build
          -include
              -downloaded_lib
                  -downloaded_lib.h
          -src
          -examples
              -example.cpp
          -CMakeLists.txt
  -src
      -main.cpp
  -build
  -CMakeLists.txt

I hope to run the same code that ran in example.cpp in main.cpp, but I have been unable to get the import working. I navigate to the build folder and cmake .. runs successfully, but 'make' fails with an import error (fatal error on the include line, can't find the header file). This makes sense, as I didn't expect the same include line to work (I copy and pasted example.cpp to main.cpp), but I'm not sure what to make that.

fatal error: downloaded_lib/downloaded_lib.h: No such file or directory
    1 | #include "downloaded_lib/downloaded_lib.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

In this situation, what should my CMakeLists.txt contain, and what should my #include contain to be able to use the contents of this library in main.cpp in the same way I can in example.cpp?

EDIT--- I changed the package names above for simplicity sake, but the repository of 'downloaded_library' is the following: https://github.com/siposcsaba89/socketcan-cpp.

My top level CMakeLists.txt looks like this:

# Minimum version of CMake required to build this project
cmake_minimum_required(VERSION 3.0)

# Name of the project
project(projectname)

# Add all the source files needed to build the executable
add_executable(${PROJECT_NAME} src/main.cpp)

add_subdirectory(libraries/downloaded_library)

# Link the executable and the library together
target_link_libraries(${PROJECT_NAME} downloaded_library)

Edit 2-- (Here I will use the original package name, socketcan-cpp).

Top level CMakeLists.txt:

# Minimum version of CMake required to build this project
cmake_minimum_required(VERSION 3.0)

# Name of the project
project(socketcan_demo)

# Add all the source files needed to build the executable
add_executable(${PROJECT_NAME} src/main.cpp)

add_subdirectory("libraries/socketcan-cpp")

target_include_directories(${PROJECT_NAME} PUBLIC "libraries/socketcan-cpp/include")

When running make I get this error:

fatal error: socketcan_cpp/socketcan_cpp_export.h: No such file or directory
    4 | #include <socketcan_cpp/socketcan_cpp_export.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

So the top level CMakeLists is able to find the header file located in include, but that header file contains the line: #include <socketcan_cpp/socketcan_cpp_export.h> which references a file in a gen directory inside the build directory created by the library's CMakeLists.txt (https://github.com/siposcsaba89/socketcan-cpp/blob/master/CMakeLists.txt). And my top level package is unable to find it.

figbar
  • 714
  • 12
  • 35
  • 1
    target_link_libraries? – Omid CompSCI Jan 23 '22 at 00:33
  • right now I have `target_link_libraries(${PROJECT_NAME} downloaded_library)` in my root CMakeLists.txt but it didn't seem to have helped. – figbar Jan 23 '22 at 01:07
  • You need to post a real MRE, ie. _everything_ necessary to reproduce your issue. Generally, when you have a problem and have not been able to solve it yourself, it is because (in part) you are unable to localize the problem correctly. If your project is open source, post a link to a git repo or something. – Alex Reinking Jan 23 '22 at 01:25
  • Ok, I updated the question to include the repository I downloaded, and the top level CMakeLists.txt. That is everything contained in this project. – figbar Jan 23 '22 at 01:33
  • So if the downloaded lib is indeed socketcan_cpp, I assume you're doing `target_link_libraries(${PROJECT_NAME}` socketcan_cpp)` and not `target_link_libraries(${PROJECT_NAME} downloaded_library)`. This should already provide you with the required include directories, see https://github.com/siposcsaba89/socketcan-cpp/blob/5e328b7afe70b359a06f340ac7240ae36a544f5c/CMakeLists.txt#L50 Btw: The linked cmake command combined with `#include ` indicates that the library's git must be cloned into a dir `socketcan_cpp`, not to some dir of a different name. – fabian Jan 23 '22 at 08:10

1 Answers1

0

In order to include the header files from the downloaded library, you can add the following to the CMakeLists.txt file:

find_library(downloaded_lib
             NAMES downloaded_lib
             HINTS "path to downloaded lib file")

if(NOT downloaded_lib)
  message(FATAL_ERROR "downloaded_lib not found!")
endif()

target_include_directories(${PROJECT_EXECUTABLE} PUBLIC "path to download_lib.h")
target_link_libraries(${PROJECT_EXECUTABLE} ${downloaded_lib})

This includes the directory where the header file is located in addition to the library file.

  • There is no lib file in the downloaded project... I got `CMake Error ... downloaded_lib not found!` when running `cmake ..` – figbar Jan 23 '22 at 01:55
  • If it's a header-only library it should be sufficient to only use the `target_include_directories()` function. In case there is no `downloaded_lib.so` or `downloaded_lib.a` file available. – SarahJuliet1510 Jan 23 '22 at 01:59
  • I used `include_directories(libraries/downloaded_lib/include)`, but 'downloaded_lib.h' couldn't find the cmake export header file. Would using `target_include_directories` change that? – figbar Jan 23 '22 at 02:03
  • It should. See also the discussion here: [link](https://stackoverflow.com/questions/16982144/cmake-and-generateexportheader). If it's really only a header file, you can also consider adding it to your other source files in the `CMakeLists.txt` file as an alternative. – SarahJuliet1510 Jan 23 '22 at 02:08
  • Ok, thanks for your help, sorry, I am new to this. What would I put as the 'target' then? e.g. `target_include_directories(??? libraries/downloaded_lib/include)` – figbar Jan 23 '22 at 02:10
  • No problem. The target would be your project target or executable `${PROJECT_NAME}`. – SarahJuliet1510 Jan 23 '22 at 02:12
  • Hm, that seems to have the same issue with finding the export header file located in `downloaded_lib/build/gen/downloaded_lib`. – figbar Jan 23 '22 at 02:16
  • Basically it seems like my project is able to find the header file using your solution, but that header file references a header file ending with _export.h which is created in the build directory when cmake is run. Is there a way I can watch the build directory for header references or is that bad practice? – figbar Jan 23 '22 at 02:37
  • The only other issue I can think of is, did you specify the absolute path to your files in the `CMakeLists.txt`? – SarahJuliet1510 Jan 23 '22 at 02:37
  • I think so, I attached the CMakeLists and the one in the library, if you could look at those. – figbar Jan 23 '22 at 02:46
  • It looks like you specified the relative path. You can type `pwd` to get the absolute path. If you build the library with cmake, then you should also have a library file in the `build/lib` folder of your library. Likewise there should also be a `build/include` folder you can include. – SarahJuliet1510 Jan 23 '22 at 03:03