C++ include library in Cmake project - c++

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.

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.

Related

Creating c++ project using cmake and automatically adding source and header files

I'm new to cmake and im trying to create a project for simulating a few libraries im writing to run on arduino. This means the directory structure of the libraries cant be changed but i can add a cmakelists file but would rather not. I need some help writing the CMakeLists file.
The simulator directory structure is:
include/
lib/
src/
CMakeLists.txt
Each library im writing must have this file structure:
TestLib/
include/VeryGoodLib.hpp
include/VeryGoodLib/sometool.hpp
src/*.cpp //All the source files
Each library is placed into the main projects lib/ directory and im hoping to make get cmake to "glob" all the libraries inside lib/ and automatically add them to the main project while also making them show up when I write #include. In this cade i would see the VeryGoodLib/ folder and VeryGoodLib.hpp header.
My current CMakeLists file is:
cmake_minimum_required(VERSION 3.0.0)
project(EasyVTOL-Sim VERSION 0.1.0)
file(GLOB_RECURSE SRC_FILES src/*.cpp)
add_executable(EasyVTOL-Sim ${SRC_FILES})
target_include_directories(EasyVTOL-Sim PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Any simple way of globing the files and including them this way?

cpprestsdk using vcpkg, cmake - can't find include files

I am porting a Windows project to CentOS Linux that uses cpprestsdk. I use vcpkg on Windows and I thought I would use vcpkg (and cmake) to bring in and build the packages and 'expose' the libs and header files to my project. The sequence fails in trying to get package header file 'known' to my source. This is what I did.
$ vcpkg install boost cpprestsdk
$ vcpkg integrate install
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake"
$ cd <source>
$ vi CMakeLists.txt
cmake_minimum_required(VERSION 2.8.9)
project(Domain)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -I../ ")
file(GLOB SOURCES "*.cpp")
#Generate the shared library from the sources
add_library(Domain SHARED ${SOURCES})
install(TARGETS Domain DESTINATION ../lib)
$ cmake -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Unix Makefiles" .
$ make
[ 7%] Building CXX object CMakeFiles/Domain.dir/BaseDataFactory.cpp.o
In file included from /src/Domain/stdafx.h:4:0,
from /src/Domain/BaseDataFactory.cpp:1:
../Common/Common.h:75:26: fatal error: cpprest/json.h: No such file or directory
#include <cpprest/json.h>
By adding the vcpkg toolchain file parameter to cmake, I thought it was supposed to take care of exposing all of the package paths (lib/header) and write them to the output Makefile?
I tried adding
find_package(cpprestsdk REQUIRED)
Then I got bunch of new errors:
CMake Error at CMakeLists.txt:7 (find_package):
Could not find a package configuration file provided by "cpprestsdk" with
any of the following names:
cpprestsdkConfig.cmake
cpprestsdk-config.cmake
cpprestConfig.cmake
cpprest-config.cmake
cpprestsdk-config.cmake does exist under the vcpkg root directory and I can definitely see the offending header file for the package under the vcpkg root directory, but why does the cmake-generated Makefile not have everything it needs to build? Does each and every package under vcpkg have to be manually included in some way in the CMakeLists.txt file?
I found the problem. Cpprestsdk does not register/expose any cmake find_package() config module. If it did that, this wouldn't be an issue - the generated toolchain file would set everything cmake needs in order to generate the paths to include in the MakeFile.
I added the following line to the CMakeList.txt file and cmake was then able to find the config file:
set(cpprestsdk_DIR "/vcpkg/installed/x64-linux/share/cpprestsdk")
Which is really, really bad, IMHO, to have to hard code a path to find cpprestsdk. I still have the header file path problem, so there's actually much more going wrong/missing. I'll update this post once I get word from the vcpkg/cmake teams.
https://github.com/Microsoft/cpprestsdk/blob/ea4eff7cd1d6110833df869f7591f266816f8328/Release/src/CMakeLists.txt#L282-L285
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CPPREST_EXPORT_DIR}
)
and
https://github.com/Microsoft/cpprestsdk/blob/9d8f544001cb74544de6dc8c565592f7e2626d6e/Release/CMakeLists.txt#L22
set(CPPREST_EXPORT_DIR cpprestsdk CACHE STRING "Directory to install CMake config files.")
One thing puzzle me (not a vcpkg expert yet)
https://github.com/Microsoft/vcpkg/blob/master/ports/cpprestsdk/portfile.cmake#L45
vcpkg_fixup_cmake_targets(CONFIG_PATH lib/share/cpprestsdk)
while it should be lib/cpprestsdk IMHO (ed: not checked SHA1 version)
#cardinalPilot did you try to locate the config file on your system ?
can you also try to print the CMAKE_PREFIX_PATH etc to see if vcpkg do correctly its stuff...

Statically linking GLEW from source with cmake

I am somewhat new to cmake and completely new to glew, glfw, and the like. I'm following a youtube channel to learn more about game engines and programming.
My problem is linking the static glew library in my project using cmake.
First, I start with the glew source code from http://mcs.une.edu.au/doc/glew-devel/index.html.
I compile it by:
cd build; cmake ./cmake; make glew_s
This adds a lib directory into the build directory with libGLEW.a
A shortened version of my CMakeLists.txt looks like:
cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
project (TestProject CXX)
set(CMAKE_CXX_FLAGS "-std=c++11")
###########################
# GLEW
###########################
add_subdirectory(${CMAKE_SOURCE_DIR}/Dependencies/GLEW)
target_link_libraries(${PROJECT_NAME} glew)
and in Dependencies/GLEW I have another CMakeLists.txt:
# Add glew source and header files
file(GLOB_RECURSE glew-lib ${CMAKE_CURRENT_SOURCE_DIR}/lib/*)
file(GLOB_RECURSE glew-headers ${CMAKE_CURRENT_SOURCE_DIR}/include/GL/*)
add_library(glew ${glew-lib} ${glew-headers})
target_include_directories(glew PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/GL")
I put a copy of the libGLEW.a file into the lib directory and the include directory is copied from the glew source code include directory. It holds the GL directory, which contains the header files glew.h, wglew.h, eglew.h, and glxew.h.
When I run cmake I get the error:
CMake Error: Cannot determine link language for target "glew".
CMake Error: CMake can not determine linker language for target: glew
The glew source code also has a src directory with glew.c in it, but if I put it in the libs directory and include it in the Dependencies/GLEW/CMakeLists.txt like:
# Add glew source and header files
file(GLOB_RECURSE glew-lib ${CMAKE_CURRENT_SOURCE_DIR}/lib/*.c)
file(GLOB_RECURSE glew-headers ${CMAKE_CURRENT_SOURCE_DIR}/include/GL/*)
add_library(glew ${glew-lib} ${glew-headers})
target_include_directories(glew PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
I get the error:
CMake Error: Error required internal CMake variable not set, cmake may
be not be built correctly.
Missing variable is: CMAKE_C_COMPILE_OBJECT
CMake Error: Error required internal CMake variable not set, cmake may
be not be built correctly.
Missing variable is: CMAKE_C_CREATE_STATIC_LIBRARY
Lastly, I have tried just including the glew.c and headers in the root CMakeLists.txt like:
#########################
# GLEW
#########################
include_directories("${CMAKE_SOURCE_DIR}/Dependencies/GLEW/lib/")
include_directories("${CMAKE_SOURCE_DIR}/Dependencies/GLEW/include/GL/")
Here cmake will finish, but it won't be able to compile, saying classes do not name a type and/or are not declared in this scope.
Any help would be appreciated. I was under the impression that the libGLEW.a was the static library, and all I would have to do is link and compile it along with the headers, but that did not work.
First of all, I forgot to use
make install
after using make the first time, so I was using the incorrect libGLEW.a file.
After including the proper libGLEW.a file, my directory structure had
./Dependencies/GLEW/include/GL/*.h //header files
./Dependencies/GLEW/lib/libGLEW.a //source file
Finally, the TopLevel CMakeLists.txt is changed to include:
add_library(glew STATIC IMPORTED GLOBAL)
set_target_properties(glew PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Dependencies/GLEW/lib/libGLEW.a )
set_target_properties(glew PROPERTIES INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Dependencies/GLEW/include )
If I want to include the library from a lower CMakeLists.txt such as /Dependencies/GLEW/CMakeLists.txt Then I would have to first export the library from there and then import it at the topLevel CMakeLists.txt file.
Now, in order to use glew headers in my project I can just use #include .

Cmake configuration for multiple sub-libraries in a "packages" directory

Here is a sample project I am trying to build with a "Packages" directory which includes all the libraries to be used in the main code.
I am trying to keep my root cmake file as clean as possible and avoid relative path such as
include_directory(packages/lib1)
but I am struggling. Is there a way of including sub-directories of a directory for the purposes of header inclusion.
First a few minor remarks:
always name the CMake configuration files CMakeLists.txt (because of)
bookmark the documentation on CMake: https://cmake.org/documentation/
Sometimes it's not that easy to read, but very specific once you adopt your head to the "CMake world" ;-)
make yourself comfortable with the scope of CMake variables
include_directories(DIR1 [DIR2 [...]])
Tells CMake where the compiler should look for header files, i.e. -IDIR1 -IDIR2 ....
add_library(NAME [STATIC|SHARED] SOURCES)
This command creates the required compiler commands to create a static or shared library out of a given list of source files. No need to add in the header files. The make target will be called NAME and the library target is known to CMake as NAME.
add_subdirectory(DIR)
Tells CMake to look into DIR and parse the included CMakeLists.txt with all its content.
target_link_libraries(TARGET LIB1 [LIB2 [...]])
Tells CMake to instruct the linker to link LIB1, LIB2, etc. to the TARGET, i.e. -LLIB1 -LLIB2 .... TARGET is a CMake/make target previously defined/created with a call to add_{library,executable,custom_target}.
CMakeLists.txt:
include_directories(libraries)
# a header file in `libraries/lib1/foo.hpp` can be included
# in the whole CMake project by `#include "lib1/foo.hpp"`.
add_subdirectory(libraries)
add_subdirectory(tests)
libraries/CMakeLists.txt:
add_subdirectory(lib1)
add_subdirectory(lib2)
libraries/lib1/CMakeLists.txt:
add_library(lib1 STATIC ${LIB1_SOURCES})
libraries/lib2/CMakeLists.txt:
add_library(lib2 STATIC ${LIB2_SOURCES})
tests/CMakeLists.txt:
add_executable(tests ${TEST_SOURCES})
target_link_libraries(tests lib1 lib2)

Can't Include LibXML2 Files in a CMake C++ Project (using QtCreator IDE)

I'm working on a Cmake based C++ project in QtCreator. I am trying to use mlpack in my project, but as soon as I include the line #include <mlpack/core.hpp> to my only source file, I get an error pertaining to some libxml files that are included by mlpack/core.hpp:
In file included from /usr/local/include/mlpack/core/util/save_restore_utility.hpp:26:0,
from /usr/local/include/mlpack/core.hpp:171,
from /home/revinci/code/workspaces/qt_ws/Semantic_Perception/src/features_slic.cpp:18:
/usr/include/libxml2/libxml/parser.h:15:31: fatal error: libxml/xmlversion.h: No such file or directory
#include <libxml/xmlversion.h>
Now, I went into /usr/include/libxml2/libxml/ and found parser.h with the line #include <libxml/xmlversion.h> in it.
So, I saw that xmlversion.h and parser.h are in the same folder and tried a hack: I changed the #include <libxml/xmlversion.h> in parser.h to #include "xmlversion.h" only to get the following error:
In file included from /usr/include/libxml2/libxml/parser.h:15:0,
from /usr/local/include/mlpack/core/util/save_restore_utility.hpp:26,
from /usr/local/include/mlpack/core.hpp:171,
from /home/revinci/code/workspaces/qt_ws/Semantic_Perception/src/features_slic.cpp:18:
/usr/include/libxml2/libxml/xmlversion.h:13:31: fatal error: libxml/xmlexports.h: No such file or directory
#include <libxml/xmlexports.h>
Which is basically telling me that it can't find xmlexports.h (included by xmlversion.h). More importantly, xmlexports.h is in the same directory as xmlversion.h and parser.h!
I tried the solution mentioned here and installed libxml2-dev (again) and libxslt1-dev, but my problem wasn't solved.
I think this may have something to do with specifying my include paths correctly. I've tried to add /usr/include/libxml2 to the various path environment variables (PATH, INCLUDE_PATH and CPATH) that are present in my build environment in QtCreator, but to no avail. My CMakeLists.txt looks like this:
project(Semantic_Perception)
cmake_minimum_required(VERSION 2.8)
#Vigra Headers
include_directories(
include
)
file(GLOB_RECURSE VigraImpex include/impex/)
add_library(VigraImpex ${VigraImpex})
#LibXml2 Headers
find_package(LibXml2 REQUIRED)
#Armadillo Headedrs
find_package(Armadillo REQUIRED)
include_directories(${ARMADILLO_INCLUDE_DIRS})
#Boost Headers
find_package(Boost 1.54.0 REQUIRED)
add_executable(features_slic src/features_slic.cpp)
target_link_libraries(features_slic
VigraImpex
${ARMADILLO_LIBRARIES}
)
BTW: LibXml2, Armadillo and Boost are all dependencies of the library I am trying to use - mlpack. The command find_pakcage(mlpack) won't work because there is no Findmlpack.cmake file on my system anywhere, and I couldn't find one on the internet either.