How to use / include libraries in Cmake / Kdevelop - c++

I don't understand what I need to do to use a library which is located in /usr/include.
For example: I want to use the json library which is located in /usr/include/json.
In my project 'main.cpp' I do #include <json/json.h>.
I don't get any errros but when I start to use the functions in the library I get undefined reference errors. I have this problem with multiple libraries, I have no idea what to do I searched on google but I only came across vague answers.
I'm pretty sure I need to do something in the CMakeLists.txt file but I have no idea what.

/usr/include is accessible for include by default. But when you include an external library, you must link it to your target. In case you are using cmake this can be done as follows: add to your CMakeLists.txt the following line:
target_link_libraries(your_target_name your_library_name)
For example, on my machine (Fedora 21) jsoncpp package is named jsoncpp, and it's include files are in /usr/include/jsoncpp/json. So I create test.cpp like this
#include <jsoncpp/json/json.h>
#include <iostream>
int main(int, char**)
{
Json::Value val(42);
Json::StyledStreamWriter sw;
sw.write(std::cout, val);
return 0;
}
and CMakeLists.txt
add_executable(test
test.cpp
)
target_link_libraries(test jsoncpp)
and all works well.

Related

C++ VSCode says it cannot open source file when it really can

I can run and compile with no problem, but VSCode Intellisense is saying that it cannot open source file boost/asio.hpp (even tho it obviously can) and is marking it as an error all the time, I want to know why its doing it and how to fix it
I have the following directory:
root/
include/
atr_include.hpp
user_interface.hpp
src/
user_interface.cpp
CMakeList.txt
main.cpp
CMakeList.txt
With CMakeList.txt:
#CMake minimum version
cmake_minimum_required(VERSION 3.0.0)
#C++ Standard version
set(CMAKE_CXX_STANDARD 20)
### Searches for the VCPKG
if(DEFINED ENV{VCPKG_ROOT})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
endif()
project(main LANGUAGES CXX VERSION 0.1.0 )
find_package(Boost COMPONENTS system json REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
include_directories(include)
link_directories(src)
add_subdirectory(src)
link_libraries(atr_lib)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})
endif()
if(MSVC OR MSYS OR MINGW)
target_link_libraries(${PROJECT_NAME} ws2_32)
endif()
src/CMakeList:
add_library(atr_lib STATIC user_interface.cpp)
include/atr_include.hpp:
#include <boost/asio.hpp>
#include <chrono>
#include <iostream>
#include <math.h>
#include <mutex>
#include <thread>
include/user_interface.hpp:
#include "atr_include.hpp"
class UserInterface
{
private:
public:
};
src/user_interface.cpp:
#include <user_interface.hpp>
main.cpp:
#include <user_interface.hpp>
int main() { return 0; }
I had the same problem and it was related to the incorrect configuration of the IntelliSense Configuration Provider item.
"configurations": [
{
...
"configurationProvider": "ms-vscode.cmake-tools"
...
}
The previous value corresponded to another Cmake extension that was no longer installed. After changing the value to ms-vscode.cmake-tools (I have the "CMake Tools" extension installed), IntelliSense started working correctly. Also boost headers includes correctly without errors from VS Code.
VSCode is not a C++ compiler. It is (mostly) a text editor, and some development tools. It merely runs some C++ compiler in order to actually compile and build C++ code.
Your actual C++ compiler is the final and ultimate authority on where it can find various header files.
For whatever reason, your VSCode configuration does not know where boost's header files are installed, so that's what it tells you. Your compiler knows, but that's your compiler, not VSCode.
So, no, VSCode really can't open or find these header files. Your question was:
I want to know why its doing it
Because it simply doesn't know. It's not your C++ compiler, and it doesn't automatically know where all header files are installed.
and how to fix it
That ...depends on your very, very specific computer, operating system (VSCode is available for multiple operating systems), whichever C++ compiler you are actually using with VSCode, and how exactly you are using VSCode (for a brief time, for example, I used VSCode to edit files that weren't even on the same computer, but accessed via ssh). Each one of these factors affects the how everything works, together.
If you know where boost's header files are installed, this may simply be a matter of digging through VSCode's configuration settings, there must be a setting somewhere that tells boost which directories contain header files to search for. If you don't know where boost's header files are installed, your first step will be to figure that part out, before anything else can be done.

How to add opendnp3 as a static C++ library

I am currently trying to set up the opendnp3 C++ library as a static library. I've built the solution following their build guide for Windows and have been able to generate several .lib files which I assume to be the static libraries.
In a completely separate folder, I have the following files under the following folder structure:
C:/Development/C++/opendnp3/lib/ # .lib files are contained in this directory
C:/Development/pybexample/
--> CMakeLists.txt
--> src/
--> test.cpp
I have the CMakeLists.txt configured as follows:
cmake_minimum_required(VERSION 2.8)
project(pybexample)
set(SOURCE_FILES src/test.cpp)
add_library(opendnp3 STATIC IMPORTED)
set_target_properties(opendnp3 PROPERTIES IMPORTED_LOCATION C:/Development/C++/opendnp3/lib/opendnp3.lib)
add_executable(pybexample ${SOURCE_FILES})
target_link_libraries(pybexample opendnp3)
Within test.cpp, I am simply calling:
#include <iostream>
#include "opendnp3/LogLevels.h"
using namespace std;
int main(void) {
cout << "Hello world!" << endl;
system("pause");
}
However, when I try to build test.cpp, I receive an error indicating: "Cannot open include file: 'opendnp3/LogLevels.h': No such file or directory". I feel like there must be something pretty basic that I've missed but I'm pretty new to using static libraries and with CMake so I can't seem to figure it out. Would anyone be able to help give some pointers as to why my include is failing?
Turns out this was caused by two problems.
The first problem was that I needed to add a line to my CMakeLists.txt that would add the header files for opendnp3 to my project. This was accomplished by adding include_directories(<path_to_headers>) before the add_executable(pybexample ${SOURCE_FILES}) line.
However, in doing this, it also became clear that there was a second problem: I hadn't built the library properly as it didn't generate any headers with the library. Turns out I had overlooked the instructions to run the INSTALL project. After setting CMAKE_INSTALL_PREFIX and running the INSTALL project, the library and headers were generated and ready for use.

How to Link a third Party Library (LibUSB) in CMake

I am attempting to use LibUSB in a project. However whenever I attempt to use basic libUSB functions I get the following error:
...src/main/main.cpp.o: In function `main':
...src/main/main.cpp:10: undefined reference to `libusb_init'
...src/main/main.cpp:11: undefined reference to `libusb_set_debug'
collect2: error: ld returned 1 exit status
The package LibUSB-devel is installed (I'm on fedora 22) and my IDE KDevelop finds and recognises the headers, to the point it offers LibUSB code completions once you have added the import statement. I don't have any custom include lines in either my IDE or CMake (my build system) so I would like to know what I need to to to make CMake find the LibUSB headers.
This is the contents of main.cpp, just in case I messed something up:
#include <iostream>
#include <libusb-1.0/libusb.h>
int main(int argc, char **argv) {
libusb_init(NULL);
libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
/*snip*/
std::cout << "Hello, world! PTPID=" << std::endl;
return 0;
}
The following are the CMakeLists.txt:
../
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_BUILD_TYPE Debug)
project(aProjectThatHasHadIt'sNameObcured)
add_subdirectory(src)
.../src/cmakelists.txt just adds subdirectories
.../src/main/
add_executable(main main.cpp)
In general, to link a third party library, you need to add the include directory where the compiler will look for the headers, and the libraries which are used by the linker.
To add include directories use target_include_directories, to add a library to be linked to a target use target_link_libraries.
For libUSB and a testLibUSB.cpp source file this would result in
add_executable(targetTestLibUSB testLibUSB.cpp)
target_include_directories(targetTestLibUSB ${LIBUSB_INCLUDE_DIR})
target_link_libraries(targetTestLibUSB ${LIBUSB_LIBRARY})
If you have several targets, you might want to use include_directories and link_libraries before defining any target. These commands apply to all targets of a project after they are set and save a lot of repetition
You can specify the paths for LIBUSB_INCLUDE_DIR and LIBUSB_LIBRARY by hand. But more flexible and portable is to use CMake built-in mechanisms to find headers and libraries.
Header can be searched by find_path and libraries by find_library.
in your case this could be
find_path(LIBUSB_INCLUDE_DIR
NAMES libusb.h
PATH_SUFFIXES "include" "libusb" "libusb-1.0")
find_library(LIBUSB_LIBRARY
NAMES usb
PATH_SUFFIXES "lib" "lib32" "lib64")
The PATH_SUFFIXES are optional. If you have installed the library in a default location, CMake will find it automatically. Otherwise specify CMAKE_PREFIX_PATH and CMake will look for the headers and libraries there, too. You can specify the variable either by adding it in the CMake GUI or adding -DCMAKE_PREFIX_PATH=/path/to/add to your CMake call.
A common pitfall is to not delete the CMakeCache.txt file in the build directory. CMake caches the values for LIBUSB_INCLUDE_DIR and LIBUSB_LIBRARY and if you makes adjustment to the prefix path or your search logic, it still does not reevaluate the variable values but sticks to the cached values.
From your projects CMakeLists.txt file it doesn't become apparent to me how you've tried to link libusb. The way I would do is the following:
target_link_libraries(project_name <other_dependencies> usb-1.0)
(Just to clarify I mean the CMakeLIsts.txt file in which you add your executable)
You're trying to import from <libusb-1.0/...> thus you need to link usb-1.0 (the lib is always omitted from linker commands!)
I'm on Fedora 23, also using KDevelop and I didn't have to specify a path. Especially because on my system all the environment variables used in the previous answer are NULL anyways.
And to confirm where and how a library is installed in the future you can just do:
locate libusb | grep .so
Hope this was somewhat helpful.

Converting a makefile to cmake using caching of .h files [duplicate]

Question is similar to this question
Handling header files dependencies with cmake
I have sample program dir having main.c main.h and CMakeLists.txt
main.h contents are
#ifndef MAIN_H
#define MAIN_H
int t=3;
int y=2;
#endif
main.c contents are
#include <main.h>
#include<stdio.h>
int main(){
printf("%d apple",t);
}
and CMakeLists.txt
PROJECT( test )
AUX_SOURCE_DIRECTORY(. test_SRCS)
include_directories(.)
ADD_EXECUTABLE (main ${test_SRCS})
but cmake is not rebuilding main.c on modification of header file.
I want it to auto-generate header file dependency.
Is it possible using cmake ?
if not is there any other tool which can do that ?
As mentioned in my comment, I have tried out your example and things were working fine: if main.h was modified then main.c would be recompiled.
My installation of CMake (version 2.8.0) told me to add
cmake_minimum_required(VERSION 2.8)
to the CMakeLists.txt file, but that is all of the adjustments I needed.
Answering this for others that google search...
I ran into this problem with one of my projects. As it turns out I added the header to the cpp file after running cmake. Re-running cmake fixed the problem. If you run into this, try that and see if it fixes the issue.
From the cmake 2.8.0 documentation of AUX_SOURCE_DIRECTORY:
It is tempting to use this command to avoid writing the list of source
files for a library or executable target. While this seems to work,
there is no way for CMake to generate a build system that knows when a
new source file has been added. Normally the generated build system
knows when it needs to rerun CMake because the CMakeLists.txt file is
modified to add a new source. When the source is just added to the
directory without modifying this file, one would have to manually
rerun CMake to generate a build system incorporating the new file.
Why do you want to avoid creating a list of files? Such lists generally do not change frequently.

Which libraries should be linked to this VTK example?

I want to compile this example in vtk, which includes the following include files:
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
// headers needed for this example
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkActor2D.h>
#include <vtkTextProperty.h>
#include <vtkTextMapper.h>
// needed to easily convert int to std::string
#include <sstream>
Originally it should be compiled with a CMakeLists.txt-file which looks like:
cmake_minimum_required(VERSION 2.8)
PROJECT(ReadDICOMSeries)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(ReadDICOMSeries MACOSX_BUNDLE ReadDICOMSeries)
if(VTK_LIBRARIES)
target_link_libraries(ReadDICOMSeries ${VTK_LIBRARIES})
else()
target_link_libraries(ReadDICOMSeries vtkHybrid vtkWidgets)
endif()
The problem is: When I simply copy this code and compile it, I get a lot of reference errors (for example: Undefined reference to 'vtkDICOMImageReader::SetDirectoryName(char const*)'). This leads me to the assumption that I should link some libraries to it. Unfortunately the CMakeLists-file does not tell me which libraries. How do I find that out?
Cmake is really strongly suggested for compiling VTK and related projects, especially as a beginner. I only use CMake, but I got an idea of what happens under the hood by checking the properties of the projects already built. In the example you provided, the CMake file only use "target_link_libraries(ReadDICOMSeries ${VTK_LIBRARIES}" , as far as I understood that it is providing to the linker ALL the libraries built with vtk.
To see what CMake will load with that instruction, check the file "VTKConfig.cmake" in the vtk build directory.
If you do it manually, you will also have to include a lot of directories
I managed to figure this out without using CMake directly or having to dig into each individual lib.
find a header file or C/CPP file that defines the object that's giving you linker pain.
Do a find-in-files of the *.cmake files that came with VTK, searching for that filename. So in your case, look for vtkDICOMImageReader.
I found vtkDICOMImageReader in vtkIOKit.cmake, so a decent guess might be libvtkio.
In my case, I was hunting for vtkDataSetAttributes, and this method successfully determined it was in vtkFiltering.lib.
If you've already got Cmake set up then doing it correctly might be easier, but I didn't want "set up vtk" to turn into "set up cmake so I can set up vtk" and then into "set up some other thing so I can set up cmake so I can set up vtk".