How do I configure the way a project is built in CLion? - c++

The problem is as follows.
I have installed libarmadillo on my Ubuntu distributive via apt utility having liblapack and libblas previously installed. And I'm trying to use it in my CLion project. What my intentions result in is that I'm receiving some build errors. One of them was solved by adding #define ARMA_DONT_USE_WRAPPER.
I have found the way to build my project in this topic -
Armadillo + BLAS + LAPACK: Linking error?. Though, I can build it only with terminal. I assume that the issue with CLion is CMake configuration.
What is the way for me to alter CMake script so that I refine its built behavior and make it compile my project?
In simple words, how do I make it compile my program with g++ main.cpp -o lab2 -O1 -llapack -lblas.
Code sample:
#define ARMA_DONT_USE_WRAPPER
#define ARMA_USE_BLAS
#define ARMA_USE_LAPACK
#include <armadillo>
#include <iostream>
using namespace arma;
using namespace std;
int main() {
mat A(4, 5);
A.load("matrix.txt");
mat B = resize(A, 4, 4);
cout << norm(A, 2);
cout << B;
return 0;
}
The errors I'm issued:
CMakeFiles/lab2.dir/main.cpp.o: In function `double
arma::blas::asum<double>(unsigned long long, double const*)':
/usr/include/armadillo_bits/wrapper_blas.hpp:241: undefined reference
to `dasum_'
CMakeFiles/lab2.dir/main.cpp.o: In function `double
arma::blas::nrm2<double>(unsigned long long, double const*)':
/usr/include/armadillo_bits/wrapper_blas.hpp:273: undefined reference
to `dnrm2_'
collect2: error: ld returned 1 exit status
CMakeFiles/lab2.dir/build.make:94: recipe for target 'lab2' failed
make[3]: *** [lab2] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/lab2.dir/all'
failed
make[2]: *** [CMakeFiles/lab2.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/lab2.dir/rule'
failed
make[1]: *** [CMakeFiles/lab2.dir/rule] Error 2
Makefile:118: recipe for target 'lab2' failed
make: *** [lab2] Error 2
CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(lab2)
set(CMAKE_CXX_STANDARD 11)
add_executable(lab2 main.cpp)

You first need CMake functions to find the libraries liblapack and libblas.
For both there are already functions in the standard cmake distribution so
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
find_package(Armadillo REQUIRED)
See FindBLAS.cmake and FindLAPACK.cmake in your cmake modules directory for documentation what variables they define.
then add them to your targets, e.g.:
target_link_libraries(lab2 ${LAPACK_LIBRARIES} ${BLAS_LIBARIES} ${ARMADILLO_LIBRARIES})

As #Richard Hodges said in a comment, in the Settings you can set the variables fed to CMake as well as define environment variables.
Something also I like to do is to include a custom CMake script to easily tweak a configuration; for example add in your CMakeLists.txt:
include(local.cmake OPTIONAL)
That way, you can put any CMake configuration you want in local.cmake in your source directory, and it will be parsed. Nothing happens if the file does not exist.

Related

CMake Beginner's Question: project with 3rd party library gets not compiled

So I am struggeling with cmake for some time now. I want to use the xmlrpc-c library from here. So I started a new project with main.cpp and CMakeLists.txt and copied the xmlrpc-c as a subdirectory into my project (since xmlrpc-c is unfortunately not a cmake library):
My code is exactly a example from here and looks like this:
#include <iostream>
#include <string>
#include "xmlrpc-c/include/xmlrpc-c/base.hpp"
#include "xmlrpc-c/include/xmlrpc-c/registry.hpp"
#include "xmlrpc-c/include/xmlrpc-c/server_abyss.hpp"
using namespace std;
class hello : public xmlrpc_c::method
{
public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
string msg(params.getString(0));
params.verifyEnd(1);
cout << msg << endl;
*retval = xmlrpc_c::value_string("XMLRPC server says hello!");
}
};
int main(int argc, char** argv)
{
xmlrpc_c::registry registry;
registry.addMethod("hello", new hello);
xmlrpc_c::serverAbyss server(xmlrpc_c::serverAbyss::constrOpt().registryP(&registry).portNumber(8080));
server.run();
return 1;
}
CMakeLists.txt looks like this
cmake_minimum_required(VERSION 3.16)
project(xmlrpc_c_server C CXX)
add_executable(xmlrpc_c_server main.cpp)
target_link_libraries(xmlrpc_c_server -lxmlrpc++ -lxmlrpc_server++ -lxmlrpc_server_abyss++ -lxmlrpc_util++)
The problem I have is that my build-process fails with a linker-error: as far as I understand is the header file registry.hpp not included correctly. If I comment out the code line registry.addMethod("hello", new hello);, I can compile the program without any errors.
====================[ Build | xmlrpc_c_server | Debug ]=========================
/usr/bin/cmake --build /mnt/c/Users/valentin.ackva/CLionProjects/xmlrp-c-server/cmake-build-debug --target xmlrpc_c_server -- -j 9
Scanning dependencies of target xmlrpc_c_server
[ 50%] Building CXX object CMakeFiles/xmlrpc_c_server.dir/main.cpp.o
[100%] Linking CXX executable xmlrpc_c_server
/usr/bin/ld: CMakeFiles/xmlrpc_c_server.dir/main.cpp.o: in function `main':
/mnt/c/Users/struppel/CLionProjects/xmlrp-c-server/main.cpp:31: undefined reference to `xmlrpc_c::registry::addMethod(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, xmlrpc_c::method*)'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/xmlrpc_c_server.dir/build.make:84: xmlrpc_c_server] Error 1
make[2]: *** [CMakeFiles/Makefile2:76: CMakeFiles/xmlrpc_c_server.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/xmlrpc_c_server.dir/rule] Error 2
make: *** [Makefile:118: xmlrpc_c_server] Error 2
What is missing?
Since the library you want to use doesn't have a cmake project you need to handle this on your own. I would suggest using add_subdirectory and creating a sub-project, where you build the library (either as shared or static depending on your needs).
In addition you need to point cmake to the location of the headers. Try manually adding what's missing to the add_executable or use include_directories and adjust your #includes accordingly.
You can also use some unofficial cmake version of it like this one. If you are using git you can add the repo as a submodule and integrate the code from that repo into your main project.
Since you are new to CMake maybe it's worth looking at a tutorial instead?
https://cliutils.gitlab.io/modern-cmake/
I think it would help your confusion a lot.

Undefined reference using external library with CMake and Conan

I am trying to develop a program that communicates with a PCSC USB reader using Conan and CMake with the LibLogicalAccess library. I followed the instructions of building and installing the library which seemed to have gone fine. I created a small simple console project with a "main.cpp" file. Following the C++ guide on the wiki of the library I tried to call a function from the library which resulted in a "Undefined reference to function. I know there are a lot of topics covering this but I have read as many as I could but could not seem to find the right solution.
I don't have much experience with Ubuntu/CMake/Conan/C++ so it might as well be a very simple fix.
OS: Kubuntu 18.04
Lang: C++
Related software: LibLogicalAccess
2.2.1,
CMake 3.17.1,
Conan 1.25.0
main.cpp
#include <iostream>
#include <logicalaccess/dynlibrary/librarymanager.hpp>
#include <logicalaccess/readerproviders/readerconfiguration.hpp>
#include <logicalaccess/cards/chip.hpp>
int main()
{
std::cout << "Program started\n";
// Reader configuration object to store reader provider and reader unit selection.
std::shared_ptr<logicalaccess::ReaderConfiguration> readerConfig(new logicalaccess::ReaderConfiguration());
// Set PCSC ReaderProvider by calling the Library Manager which will load the function from the corresponding plug-in
readerConfig->setReaderProvider(logicalaccess::LibraryManager::getInstance()->getReaderProvider("PCSC"));
std::cout << "after..\n";
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(project)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
set(CMAKE_CXX_FLAGS "-I /usr/include/PCSC")
add_executable(project main.cpp)
target_link_libraries(project PUBLIC CONAN_PKG::LogicalAccess)
When I try to build the program using cmake --build . this is the output:
[100%] Linking CXX executable bin/project
CMakeFiles/project.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x140): undefined reference to `logicalaccess::LibraryManager::getReaderProvider(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
CMakeFiles/project.dir/build.make:191: recipe for target 'bin/project' failed
make[2]: *** [bin/project] Error 1
CMakeFiles/Makefile2:95: recipe for target 'CMakeFiles/project.dir/all' failed
make[1]: *** [CMakeFiles/project.dir/all] Error 2
Makefile:103: recipe for target 'all' failed
make: *** [all] Error 2
The weird part is that the first line of code: std::shared_ptr<logicalaccess::ReaderConfiguration> readerConfig(...) works fine and the second line of code gives an undefined reference.
I have tried other functions in the same file which give the same result. The file compiles and runs fine when I remove the last "setReaderProvider" line of code. Also tried a lot of different little adjustments regarding the conanfile.txt and CMakeLists.txt.
Your error says:
main.cpp:(.text+0x140): undefined reference to `logicalaccess::LibraryManager::getReaderProvider(std::__cxx11::basic_string, std::allocator > const&)'
It occurs because your CMake is using libstdc++11 to link, however, Conan is configured to use libstdc++ due backward compatibility.
You need to update your default libcxx:
conan profile update settings.compiler.libcxx=libstdc++11 default
Please, read this section in Conan docs How to Manage GCC ABI to get more information.
Also, it's explained on step 5 of Getting Started.
Now when building again, you will need that your local packages won't be available, because it's a new package, using different settings, so you will need to install, or build from sources. The link to libstdc++11 is automatically managed by Conan, it passes the definitions to CMake.
Regards!

Undefined reference in libfreenect c++ wrapper

I want to print the number of connected devices with libfreenect in c++. As described in https://openkinect.org/wiki/C%2B%2B_Wrapper
i include the libfreenect.hpp header file in my TestKinectConnection.cpp.
My TestKinectConnection.cpp:
#include <iostream>
#include "libfreenect.hpp"
using namespace std;
int main(void) {
Freenect::Freenect nect;
freenect_context *f_ctx;
cout << nect.deviceCount() << endl;
return(0);
}
When i build with cmake --build build -- -j3 the terminal shows
CMakeFiles/projektinf.dir/src/main/TestKinectConnection.cpp.o: In function `Freenect::Freenect::Freenect()':
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectC2Ev[_ZN8Freenect8FreenectC5Ev]+0x40): undefined reference to `freenect_init'
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectC2Ev[_ZN8Freenect8FreenectC5Ev]+0x90): undefined reference to `freenect_select_subdevices'
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectC2Ev[_ZN8Freenect8FreenectC5Ev]+0xb0): undefined reference to `pthread_create'
CMakeFiles/projektinf.dir/src/main/TestKinectConnection.cpp.o: In function `Freenect::Freenect::~Freenect()':
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectD2Ev[_ZN8Freenect8FreenectD5Ev]+0xa5): undefined reference to `pthread_join'
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectD2Ev[_ZN8Freenect8FreenectD5Ev]+0xb4): undefined reference to `freenect_shutdown'
CMakeFiles/projektinf.dir/src/main/TestKinectConnection.cpp.o: In function `Freenect::Freenect::deviceCount()':
TestKinectConnection.cpp:(.text._ZN8Freenect8Freenect11deviceCountEv[_ZN8Freenect8Freenect11deviceCountEv]+0x17): undefined reference to `freenect_num_devices'
CMakeFiles/projektinf.dir/src/main/TestKinectConnection.cpp.o: In function `Freenect::Freenect::operator()()':
TestKinectConnection.cpp:(.text._ZN8Freenect8FreenectclEv[_ZN8Freenect8FreenectclEv]+0x4f): undefined reference to `freenect_process_events_timeout'
collect2: error: ld returned 1 exit status
CMakeFiles/projektinf.dir/build.make:95: recipe for target '../bin/projektinf' failed
make[2]: *** [../bin/projektinf] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/projektinf.dir/all' failed
make[1]: *** [CMakeFiles/projektinf.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
My CMakeLists.txt:
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.10)
# Project's name
project(projektinf)
# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
set(PROJECT_SOURCE_DIR ${CMAKE_SOURCE_DIR})
set(EXTERNAL_INSTALL_LOCATION ${CMAKE_SOURCE_DIR}/lib)
# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}/src/include")
add_executable(projektinf ${PROJECT_SOURCE_DIR}/src/main/TestKinectConnection.cpp)
add_library(libfreenect ${PROJECT_SOURCE_DIR}/src/include/libfreenect.hpp)
target_link_libraries(projektinf PUBLIC libfreenect)
set_target_properties(libfreenect PROPERTIES LINKER_LANGUAGE CXX)
https://github.com/OpenKinect/libfreenect/blob/master/wrappers/cpp/libfreenect.hpp
https://github.com/OpenKinect/libfreenect/blob/master/include/libfreenect.h
In short summary, libfreenect.hpp tries to include libfreenect.h und completely fails.
From your question it is unclear whether you installed libfreenect globally or simply bundled the library with your code.
If you installed it globally, you forgot to tell CMake that the libfreenect target needs to link with libfreenect.so using the -lfreenect linker flag.
Adding the following should fix that:
set_property(TARGET libfreenect PROPERTY INTERFACE_LINK_LIBRARIES -lfreenect)
The proper approach is to make libfreenect an IMPORTED target, as documented in "It's time to do CMake right".
If you bundled the .cpp with your code, you need to add the .cpp file to the add_library statement that defines the libfreenect target.

How to correctly import freenect2 using cmake?

I have to use a kinect2 (ubuntu 16.04 LTS). So I installed several things :
OpenNi (https://github.com/OpenNI/OpenNI)
OpenNi2 (https://github.com/occipital/openni2
libfreenect, (because I used the first kinect before) (https://github.com/OpenKinect/libfreenect)
libfreenect2 (https://github.com/OpenKinect/libfreenect2)
PrimeSese (with the corresponding part of https://www.icyphy.org/accessors/wiki/Main/InstallingThePrimeSenseKinectSensorOnUbuntu)
OpenCV (https://github.com/opencv/opencv)
When I was using the first kinect I was able to import the libfreenect tools without an problem, but now way with libfreenect !
You can find my CMake here. There isn't any problem with the others libs in the CMake.
What I changed to install libfreenect2:
I clone the repository in my folder ~/sofware. (I put all my libs here)
Instead of
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2
I did
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/software/libfreenect2/freenect2
With my Cmake when I compile I got this:
CMakeFiles/Kinect2CaptureYM.dir/app/Kinect2CaptureYM.cpp.o: In function `Kinect2CaptureYM::Kinect2CaptureYM()':
Kinect2CaptureYM.cpp:(.text._ZN16Kinect2CaptureYMC1Ev[_ZN16Kinect2CaptureYMC1Ev]+0x108): undefined reference to `libfreenect2::Freenect2::Freenect2(void*)'
Kinect2CaptureYM.cpp:(.text._ZN16Kinect2CaptureYMC1Ev[_ZN16Kinect2CaptureYMC1Ev]+0x427): undefined reference to `libfreenect2::Freenect2::~Freenect2()'
CMakeFiles/Kinect2CaptureYM.dir/app/Kinect2CaptureYM.cpp.o: In function `Kinect2CaptureYM::~Kinect2CaptureYM()':
Kinect2CaptureYM.cpp:(.text._ZN16Kinect2CaptureYMD1Ev[_ZN16Kinect2CaptureYMD1Ev]+0xb8): undefined reference to `libfreenect2::Freenect2::~Freenect2()'
collect2: error: ld returned 1 exit status
CMakeFiles/Kinect2CaptureYM.dir/build.make:156: recipe for target 'Kinect2CaptureYM' failed
make[2]: *** [Kinect2CaptureYM] Error 1
CMakeFiles/Makefile2:190: recipe for target 'CMakeFiles/Kinect2CaptureYM.dir/all' failed
make[1]: *** [CMakeFiles/Kinect2CaptureYM.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
So my make isn't able to link the the freenec2 lib. But I don't understand why as I put this in my makefile:
FIND_PACKAGE(freenect2 REQUIRED)
LIST(APPEND INCLUDE_DIRS ${FREENECT2_INCLUDE_DIRS})
LIST(APPEND LIBRARIES ${FREENECT2_LIBRARIES})
Does someone know how to link it correctly ? I'm really stuck beacause of that :/
If you need anything else just ask, thx!
PS : The most important things in my code are (enough to make the make crash):
the include : #include <libfreenect2/libfreenect2.hpp>
the declaration : libfreenect2::Freenect2 freenect2;

Unable to compile example from OpenCL C++ Bindings Documentation (cl2.hpp)

I am trying to learn OpenCL2 with C++.
I'm using kubuntu 16.04.1 LTS and beignet from repository.
My laptop is a lenovo with a intel i5-5200U without nvidia or similar.
The command clinfo recognize the platform.
The first bug i found in the example is the variable output2 that isn't declared i have tried to comment it, but still get many link error...
The example is this http://github.khronos.org/OpenCL-CLHPP/index.html#example
This is a minimal example that reproduce a part of link error:
main.cpp:
// Defines the target OpenCL runtime version to build the header against.
// Defaults to 200, representing OpenCL 2.0.
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <CL/cl2.hpp>
int main()
{
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11
project(exampleopencl2)
add_executable(exampleopencl2 main.cpp)
install(TARGETS exampleopencl2 RUNTIME DESTINATION bin)
I use KDevelop and i get this output when i try to compile this code:
/home/deglans/ExampleOpenCL2/build> make -j2 mytests
Scanning dependencies of target mytests
[ 50%] Building CXX object CMakeFiles/mytests.dir/main2.cpp.o
[100%] Linking CXX executable mytests
CMakeFiles/mytests.dir/main2.cpp.o: In function `cl::detail::ReferenceHandler<_cl_device_id*>::release(_cl_device_id*)':
/usr/include/CL/cl2.hpp:1438: undefined reference to `clReleaseDevice'
CMakeFiles/mytests.dir/main2.cpp.o: In function `cl::detail::ReferenceHandler<_cl_context*>::release(_cl_context*)':
/usr/include/CL/cl2.hpp:1473: undefined reference to `clReleaseContext'
CMakeFiles/mytests.dir/main2.cpp.o: In function `cl::detail::ReferenceHandler<_cl_command_queue*>::release(_cl_command_queue*)':
/usr/include/CL/cl2.hpp:1482: undefined reference to `clReleaseCommandQueue'
collect2: error: ld returned 1 exit status
CMakeFiles/mytests.dir/build.make:94: recipe for target 'mytests' failed
make[3]: *** [mytests] Error 1
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/mytests.dir/all' failed
make[2]: *** [CMakeFiles/mytests.dir/all] Error 2
CMakeFiles/Makefile2:116: recipe for target 'CMakeFiles/mytests.dir/rule' failed
make[1]: *** [CMakeFiles/mytests.dir/rule] Error 2
Makefile:175: recipe for target 'mytests' failed
make: *** [mytests] Error 2
*** Errore: Codice di uscita 2 ***
I have solved the problem by adding target_link_libraries(exampleopencl2 OpenCL) in the CMakeLists.txt file.