Undefined reference using external library with CMake and Conan - c++

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!

Related

C++ Tensorflow lite, undefined reference on some functions

I'm trying to build and run a project using tensorflow lite on my debian 11 intel x86_64 architecture. So far I've followed the official documentation and the official github example.
Here are the steps I've followed:
On ~/Desktop/ I ran git clone https://github.com/tensorflow/tensorflow.git tensorflow_src
mkdir tflite_build & cd ~/Desktop/tflite_build
cmake ../tensorflow_src/tensorflow/lite
cmake --build . I've removed the -J flag regardless of what the docs says because it causes my pc to freeze.
mkdir ~/Desktop/tf_test & cd ~/Desktop/tf_test
Create a CMakeLists.txt and a main.cpp file inside tf_testdirectory.
Put the main code from the minimal example on the github repo provided above then this code in CMake:
cmake_minimum_required(VERSION 3.16)
project(minimal C CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTFLITE_DISABLE_TELEMETRY=1")
set(TENSORFLOW_SOURCE_DIR "" CACHE PATH
"Directory that contains the TensorFlow project" )
if(NOT TENSORFLOW_SOURCE_DIR)
get_filename_component(TENSORFLOW_SOURCE_DIR
"/home/user/Desktop/tensorflow_src" ABSOLUTE)
endif()
add_subdirectory(
"${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
"${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL)
add_executable(minimal minimal.cc)
target_link_libraries(minimal tensorflow-lite)
Created the folder tf_Test/build and ran cmake .. inside it.
After cmake is completed I run make inside the build directory and I'm getting the following error:
...
[100%] Linking CXX executable minimal
/usr/bin/ld: tensorflow-lite/libtensorflow-lite.a(interpreter.cc.o): in function `tflite::impl::Interpreter::ReportTelemetrySettings(char const*)':
interpreter.cc:(.text+0x292f): undefined reference to `tflite::telemetry::TelemetryReportSettings(TfLiteContext*, char const*, TfLiteTelemetryInterpreterSettings const*)'
/usr/bin/ld: tensorflow-lite/libtensorflow-lite.a(subgraph.cc.o): in function `tflite::Subgraph::Invoke()':
subgraph.cc:(.text+0x41c0): undefined reference to `tflite::telemetry::TelemetryReportEvent(TfLiteContext*, char const*, TfLiteStatus)'
/usr/bin/ld: tensorflow-lite/libtensorflow-lite.a(subgraph.cc.o): in function `tflite::Subgraph::ModifyGraphWithDelegate(TfLiteDelegate*)':
subgraph.cc:(.text+0x6ad0): undefined reference to `tflite::telemetry::TelemetryReportEvent(TfLiteContext*, char const*, TfLiteStatus)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/minimal.dir/build.make:184: minimal] Error 1
make[1]: *** [CMakeFiles/Makefile2:1408: CMakeFiles/minimal.dir/all] Error 2
make: *** [Makefile:149: all] Error 2
Notice that it's not saying this for all the functions. For example this works std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile(filename); without errors.
These tree are causing trouble: tflite::ops::builtin::BuiltinOpResolver resolver; std::unique_ptr<tflite::Interpreter> interpreter; tflite::InterpreterBuilder(*model, resolver)(&interpreter);
Note: I've trimmed some code compare to the github example for the sake of testing it, so only the above 4 lines are present on my main.
Why am I getting this error? I've tried compiling with bazel aswell but I'm getting the same error. What am I missing?
Probably it is missing from the CMakeLists file
Update CMakeLists.txt and add
tensorflow/lite/profiling/telemetry/telemetry.cc and
tensorflow/lite/profiling/telemetry/telemetry.h
to TFLITE_PROFILER_SRCS
It is also worth creating issue on Tensorflow repo for the team

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

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.

Make/Cmake subdirectory linking to external library fails

I'm currently having trouble in the following setup:
My main project has a subdirector that is a library. This library depends on a system library "triangle" (installed from source). The main project does use a file from the subdirectory.
Cmake of the main project (and the library) work fine.
Building the library works just fine.
(Either in it's own directory or after cmake in the main directory with
make subdir_lib compiles without problems)
This is where the problems starts.
Building the main project with make project fails. It happens during linking:
subdir/libsubdir_lib.a(Test.cpp.o): In function `Test::run()':
/home/mimre/workspace/tmp/cmake-problem/subdir/files/Test.cpp:34: undefined reference to `triangle_context_create'
/home/mimre/workspace/tmp/cmake-problem/subdir/files/Test.cpp:35: undefined reference to `triangle_context_options'
/home/mimre/workspace/tmp/cmake-problem/subdir/files/Test.cpp:42: undefined reference to `triangle_mesh_create'
/home/mimre/workspace/tmp/cmake-problem/subdir/files/Test.cpp:50: undefined reference to `triangle_context_destroy'
collect2: error: ld returned 1 exit status
CMakeFiles/cmake_problem.dir/build.make:95: recipe for target 'cmake_problem' failed
make[3]: *** [cmake_problem] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/cmake_problem.dir/all' failed
make[2]: *** [CMakeFiles/cmake_problem.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/cmake_problem.dir/rule' failed
make[1]: *** [CMakeFiles/cmake_problem.dir/rule] Error 2
Makefile:118: recipe for target 'cmake_problem' failed
make: *** [cmake_problem] Error 2
To avoid having a wall of code in here, I uploaded a minimal example onto github: https://github.com/mimre25/cmake_problem
Also, this is the library I'm using, installed with cmake & sudo make install: https://github.com/wo80/Triangle
I've tried the solutions from various similar threads but to no avail.
Thanks in advance for any help!
I would have written this as a comment but I don't have enough reputation for that. Is this a situation where you need to use this Triangle (https://github.com/wo80/Triangle), rather than the original Triangle (https://www.cs.cmu.edu/~quake/triangle.html)? If you can use the latter, I know from experience that its is very easy to link to. I just put it in a subdirectory in my code with this CMakeLists.txt.
## This only works for linux. Use an if statement to handle all architectures.
SET(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -O -DLINUX -DTRILIBRARY -w -DANSI_DECLARATORS"
)
SET(FILES_SOURCE
triangle.h triangle.c
)
ADD_LIBRARY( my_local_name_for_triangle_library STATIC ${FILES_SOURCE} )
And then I can link to the triangle library I have created like this:
include_directories(my_local_triangle_dir)
target_link_libraries(my_local_name_for_triangle_library)
However, some of the #define macros are missing in triangle.h, so you need to copy them from triangle.c to triangle.h.
It seems that you tried to link a library that doesn't exist (where CMake can find it).
You either need to create a find_library, or when you link to triangle, give a full path with name.
Alternatively, you can leave the source in a sub directory which you can call then link to the name.

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;

Compiling Qt5 hello world .cpp file under Windows using MinGW-w64 gives "undefined reference" error

When I run make to compile the Makefile produced by cmake, to compile an hello world example of a Qt5 application, the compilation fails with the following error:
Why is the compilation failing?
(details of what exactly I'm trying to do follow)
I'm under Windows 10, using the Qt5.5 binaries downloaded from Qt official website, mingw-w64 gcc and g++ shipped with WinBuilds, and cmake v3.6 downloaded from the official website and installed with the Windows win64-x64 Installer.
I'm trying to compile the following hello world test file, provided in Qt5's official wiki:
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication app (argc, argv);
return app.exec();
}
The Makefile is built successfully using the command cmake -G "MinGW Makefiles" .. from a folder called build inside the directory containing the .cpp file. The following CMakeLists.txt file (taken from Qt5's cmake wiki page, with the addition of the specification of the CMAKE_PREFIX_PATH variable, which is required as for example discussed in this SO post) was used:
cmake_minimum_required(VERSION 2.8.11)
SET(CMAKE_C_COMPILER C:/WinBuilds/bin/x86_64-w64-mingw32-gcc-4.8.3.exe)
SET(CMAKE_CXX_COMPILER C:/WinBuilds/bin/x86_64-w64-mingw32-g++-4.8.3.exe)
project(testproject)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
#set(CMAKE_PREFIX_PATH "C:/WinBuilds/lib64/cmake")
set(CMAKE_PREFIX_PATH "C:/Qt/5.5/mingw492_32/lib/cmake")
find_package(Qt5Widgets)
add_executable(testfile WIN32 test.cpp)
target_link_libraries(testfile Qt5::Widgets)
(I did not use the cmake shipped with Qt5 as that did not work).
Now, the problem arises when I run make (or more precisely, mingw32-make, again shipped with WinBuilds) on the Makefile produced by cmake.
When I do this, the compilation fails with the following error (same one showed in the screenshot above):
CMakeFiles\testfile.dir/objects.a(test.cpp.obj):test.cpp:(.text+0x35): undefined reference to `__imp__ZN16QCoreApplicationC1ERiPPci'
CMakeFiles\testfile.dir/objects.a(test.cpp.obj):test.cpp:(.text+0x3e): undefined reference to `__imp__ZN16QCoreApplication4execEv'
CMakeFiles\testfile.dir/objects.a(test.cpp.obj):test.cpp:(.text+0x50): undefined reference to `__imp__ZN16QCoreApplicationD1Ev'
CMakeFiles\testfile.dir/objects.a(test.cpp.obj):test.cpp:(.text+0x67): undefined reference to `__imp__ZN16QCoreApplicationD1Ev'
c:/winbuilds/bin/../lib64/gcc/x86_64-w64-mingw32/4.8.3/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\testfile.dir/objects.a(test.cpp.obj): bad reloc address 0xc in section `.xdata'
c:/winbuilds/bin/../lib64/gcc/x86_64-w64-mingw32/4.8.3/../../../../x86_64-w64-mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
CMakeFiles\testfile.dir\build.make:127: recipe for target 'testfile.exe' failed
mingw32-make[2]: *** [testfile.exe] Error 1
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/testfile.dir/all' failed
mingw32-make[1]: *** [CMakeFiles/testfile.dir/all] Error 2
Makefile:82: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
Why is the compilation failing?
A similar undefined reference error was reported in this other SO question, but the reason there seemed to be different than the present case.
The problem is you are using 32 bit mingw compiled Qt binaries when you are trying to build a 64 bit Qt application. You need to use 64 bit Qt binaries compiled with mingw for this to work.