CLion - cannot solve undefined reference to constructor in class - c++

I've already looked at this SO answer but I cannot seem to find the solution for my case.
I just started working in C++ and CLion. I did a basic test project that includes a header file and the main function then executes a method from the included class - all working just fine, CLion compiler is MinGW.
Now the real project I need to work on integrates a SDK from a vendor written in C++. They do have examples as well. Every time I run them, CLion breaks the build and complains about undefined references... the include file paths are all correct and CMakeList.txt looks like this:
project(test_2)
include_directories("../libraries/bin/headers/")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXE_LINKER_FLAGS "")
set(PROJECT_HEADERS
"../libraries/bin/headers/SDK.h"
"test.h"
)
set(PROJECT_SOURCES
main.cpp
)
add_executable(test_2 ${PROJECT_SOURCES} ${PROJECT_HEADERS})
the first undefined reference that is listed is the constructor of the SDK class, which is written simply as:
class SDK{
...
SDK();
...
}
Any suggestions what the problem is ?
Because of the current situation I cannot reach anybody on their end, so I thought I ask here...
Thanks !
Solution:
the solution was to compile the libs from the .cpp file an make a clean CMakeList file referencing those libs, this then resolved the undefined reference errors.

I'm not fluent in CMake - but you probably have to also link libraries/directories using something like target_link_libraries()/target_link_directories() if using external SDK. Seems to me that you simply tell the compiler "hey, here is my SDK header, do something" but compiler doesn't know where are the symbols for this SDK defined. Here is a little bit of an explanation what is the basic difference between the two, but I recommend checking CMake documentation directly.
c̛̣o̢̥m̯͕̖̠̙͡p͕̭͚͓̮̲ḭ͓͇͔̟̫l̪͈i͉̟̜̺͖͓͉n̮̻̼g͎̩̳̯ ̻̯̹̦̱̠̀w͕̬̜i̖̭̣th̹̠̕ C̙M̩a̲̮̹͉̻̥̥ķ͕̤̭̠͚e̩̙̼ ̫̮is̻̗͈͓͟ f̧̮͓̦u͏̯ͅń̹̣

I have no clue how the library that you're using is designed, but if there is no definition of the constructor in the header file, it is clearly not header-only. So you either have to link to that library, or add its implementation file (if you have one) to your project so linker gets what you promised. I suggest to look at target_link_libraries to see how to link in CMake (there are more ways to do it though).
Undefined reference error generally means that linker did not find something that was advertised in a header.

the solution was to compile the libs from the .cpp file an make a clean CMakeList file referencing those libs, this then resolved the undefined reference errors.

Related

How can I link a library that contains conditional types/variables definition based on global variables defined through CMake?

Introduction
I am trying to use Toulbar2 as a C++ library in my CMake project, however I am having much trouble linking it to my main executable.
I found many similar questions on this topic, both here and on other similar website, but none of them helped me with my specific issue. I tried literally everything and I did not menage to make it work, I was hoping that some of you may help me with that.
I am running Ubuntu 18.04, CMake version 3.23 and in my project I am using the standard C++11. I am a proficient programmer, but I am just an beginner/intermediate user of both C++ and CMake.
What I've already tried to do
I cannot list all my attempts, so I will only mention those I think are my best ones, to give you an idea of what I may be doing wrong.
1) In my first attempt, I tried to use the same approach I used for any non-standard library I imported, i.e. using find_package() in CMakeLists.txt to then link the found LIBRARIES and include the found INCLUDE_DIRS. However, I soon realised that Toulbar2 provides neither a Find<package>.cmake or <name>Config.cmake file. So, this approach could not work.
2) My second attempt is the one that in my opinion brought me the closest to the solution I hoped for. You can easily compile Toulbar2 as a dynamic library using the command: cmake -DLIBTB2=ON .. in an hypothetical build directory you previously created. After compiling with make you have your .so file in build/lib/Linux. After installation, you can make CMake find this library by itself using the command find_library. So, my CMakeLists.txt ended up looking like this:
[...]
find_library(TB2_LIBRARIES tb2)
if(TB2_LIBRARIES)
set(all_depends ${all_depends} ${TB2_LIBRARIES})
else(TB2_LIBRARIES)
add_compile_definitions("-DNO_TB2")
message("Compiling without Toulbar2, if you want to use it, please install it first")
endif(TB2_LIBRARIES)
[...]
target_link_libraries(main ${all_depends})
[...]
This code works to some extent, meaning that CMake correctly finds the library and runs the linking command, however if I try to #include <toulbar2lib.hpp> the header is not found. So I figured out I should have told CMake where to find that header, so I ended up adding a
include_directories(/path/to/header/file's/directory)
However, I still have another problem. The header is found, but a lot of names used in the header are not found at compilation time. The reason is that in Toulbar2 some variables/types are defined conditionally by using preprocessing directives like #ifdef or #ifndef, and in turn the global variables used in these conditions are defined through CMake at compilation time. If you are interested in an example, I can mention the Cost type that is used in the mentioned header file. I see that there's a piece missing in the puzzle here, but I cannot figure out which one. Since I pre-compiled the library those definitions should exist when I include the header file, because I am correctly linking the correspondent library that contains those definitions.
3) My third attempt is less elegant than the the other two I mentioned, but I was desperately trying to find a solution. So, I copied the whole toulbar2 cloned folder inside my project and I tried to add it as a subdirectory, meaning that my main CMakeLists.txt contains the line:
add_subdirectory(toulbar2)
It provides a CMakeLists.txt too, there should be no problem in doing it. Then I include the src directory of toulbar2, that contains the header file I need, and I should be okay. Right? Wrong. I got the same problem that I had before with (2), i.e. some variables/types conditionally defined were not actually defined when I tried to compile my project, even though the subproject toulbar2 was correctly (no errors) compiled.
I just wanted to mention that any answer is welcome, however if you could help me figure out an elegant solution (see 1 or 2) for this problem it would be way better, as this code is intended to be published soon or later. Thank you in advance for your help.
Solution 2) looks fine. You just need to add the following compilation flags -DNDEBUG -DBOOST -DLONGDOUBLE_PROB -DLONGLONG_COST when compiling your project with toulbar2lib.hpp. See github/toulbar2 README.md how to compile without cmake for those flags (except WCSPFORMATONLY that should not by used in this context).

Compilation issues with Cmake and Intel IPP under Ubuntu

The issue is that I have a source which includes ipps.h and this code I'm able to compile into a test.so file without issues.
The problem starts when I have a Qt example which requires this built test.so file, I get the following messages from the compiler:
/home/antti/test.so: undefined reference to 'ippsFilterMedianGetBufferSize'
/home/antti/test.so: undefined reference to 'ippsFilterMedian_32f'
In my CMakeLists.txt for compiling the test.so, I have the following lines in the end of the file:
add_library(libippcore SHARED IMPORTED)
set_property(TARGET libippcore PROPERTY IMPORTED_IMPLIB "/opt/intel/compilers_and_libraries_2018.3.222/linux/ipp/lib/ia32_lin/libippcode.so")
Is this a linker problem or what is causing the issue? And how to solve it properly? The strange thing is that the Qt example is built with its own CMakeLists.txt but I don't see any reference in it to the test.so file even though it clearly includes it somehow.
The 'ippsFilterMedian_32f' function is in 'libipps.so' library. That is signal processing library.
So, you need to add libipps (along with libippcore) to your cmake file.
Let's look what happens after you successfully built test.so.
Regards,
Sergey

Undefined reference when linking one dynamic library into the other using CMake and Cygwin

I've looked around, and it doesn't seem that the solution to my problem has been discussed anywhere. So, I write here.
I create a CMake project for generation of several Python libraries. I use Boost.Python to wrap my C++ code, CMake to build dynamic libraries. Everything is on Cygwin platform. The topmost level of the project is pretty standard- eventually it leads to the source directory via:
ADD_SUBDIRECTORY("src")
The /src directory contains two sub-folders - mmath and ann - each is intended for its own library. The CMake file at this level is:
MESSAGE("Going into subdirectory mmath...")
ADD_SUBDIRECTORY("mmath")
MESSAGE("Going into subdirectory ann...")
ADD_SUBDIRECTORY("ann")
So we build the mmath library first:
file(GLOB MMATH_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB MMATH_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${MMATH_HEADERS})
SET( ext_libs
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}/libpython2.6.dll
)
ADD_LIBRARY(mmath SHARED ${MMATH_SRC})
TARGET_LINK_LIBRARIES(mmath ${ext_libs})
and it works perfectly. The resulting dynamic library can then be imported in Python as a module (in cygwin the library is prepended with "cyg" prefix, instead of "lib"). Among other things, the library defines a class DATA, which is essentially a customized container (a collection of variables of standard types), so very simple.
Now, when CMake proceeds into the /src/ann directory, it tries to build the corresponding cygann.dll (cygwin convention) library, which depends on the mmath library we have built already. The CMake script is:
file(GLOB ANN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB ANN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${ANN_HEADERS})
SET( ext_libs1
mmath
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}/libpython2.6.dll
)
ADD_LIBRARY(ann SHARED ${ANN_SRC})
TARGET_LINK_LIBRARIES(ann ${ext_libs1})
In the src/ann directory we have a file defining the class Ann, which has the members of type std::vector. It is here where linking problem revels itself: the DATA class causes some problems on the linking stage - the "undefined reference" error. The errors indicate that neither constructor nor destructor for the DATA class are defined:
CMakeFiles/ann.dir/libann.cpp.o: In function `Destroy<libmmath::DATA>':
/usr/lib/gcc/i686-pc-cygwin/4.8.3/include/c++/bits/stl_construct.h:93: undefined reference to `libmmath::DATA::~DATA()'
CMakeFiles/ann.dir/libann.cpp.o: In function `Construct<libmmath::DATA, libmmath::DATA>':
/usr/lib/gcc/i686-pc-cygwin/4.8.3/include/c++/bits/stl_construct.h:83: undefined reference to `libmmath::DATA::DATA(libmmath::DATA const&)'
So I'm wondering what could be the problem. Is this related to CMake features, cygwin tricks or is it something regarding the code itself? Well, i feel that the problem is less likely related to the code itself, since it works in standard utilization (static exe or just a single dynamic library). It is more likely that it is something about CMake or cygwin that I'm missing. But what? Please, help. Thank you in advance.

Trouble including third-party code in my C++ application

I'm trying to include some networking code into my C++ application. I downloaded CSimpleSocket and I copied all the .h and .cpp files into the directory where my main file is. Then I tried including one of the headers, but the linker just barfs up a bunch of errors, like:
[Linker error] undefined reference to CPassiveSocket::CPassiveSocket(CSimpleSocket::CSocketType)'
[Linker error] undefined reference to `CSimpleSocket::Initialize()'
[Linker error] undefined reference to `CPassiveSocket::Listen(unsigned char const*, short, int)'
[Linker error] undefined reference to `CPassiveSocket::Accept()'
and others. Everything is in one directory, so I don't think that's the problem. The code I'm using to include is #include "PassiveSocket.h". I'm using Dev-C++, if that makes any difference. I don't understand what I'm doing wrong, so if somebody could help me, that would be great.
Forgive me if this is a really dumb question, but I'm trying to learn C++, and it's not easy. Thanks for your help.
The reason you're getting this error is because your compiler can't find the binary that corresponds to the CSimpleSocket headers. It's as if you wrote
void someFunction(int someArg);
And then never provided the implementation for someFunction.
To use a third party library you need two things:
Header files (.h, .hpp, etc...)
Library files (.a, .lib, etc...)
Once you've got your header files and library files you need to put them in a place your compiler can find them. This place will vary depending on your OS, environment variables and compiler configuration.
Now that they're somewhere the compiler can find them you need to tell the compiler to use them. Header files are used with the #include command and library files are linked by providing arguments to the compiler.
Behind the scenes Dev-C++ uses the MinGW GNU GCC compiler, it invokes a command similar to g++ file1.cpp file2.cpp ... filen.cpp -o filename that tells the program g++ to compile a C++ executable named "filename" using files 1 to n. There are other flags that can be added to g++ such as telling it where to search and what to link.
The name of the CSimpleSocket library when compiled is "clsocket" so we need to find a way to configure Dev-C++ to add -lclsocket to the g++ command. I don't use Dev-C++ so I can't help you here but you're probably looking for "Linking Options" or something similar in your compile configuration. You also need to make sure the .lib and .h files are on the search path which should also be configurable in Dev-C++.
CSimpleSocket also provides an installer that should automatically create the .lib file and place the .lib and .h in places where they can be found, you should consider using that installer.
I think the complexity of this answer highlights the abysmal state of the C++ library integration ecosystem. Unfortunately there is no concept of a "module" in C++ at the time of writing.

Getting undefined reference error at adding simple class to library

I am working with a rather sizeable library which uses CMake for compilation/linking. I need to add some functionality, thus I need to add some classes to the library. The problem is that when I add even a simple helloWorld class to the library, and try to call it from some main function, I get undefined reference problem at link time. When I looked into the built code ("CMakeFiles" within the library folder), my class hasn't been compiled by CMake (and thus, for instance, there is no HelloWorld.o file in there).
Can somebody point out where I am going wrong? Do I need to explicitely tell CMake to compile this class? (if yes, how?). I am novice in CMake, so don't know how to tackle this problem.
I call the function like this.
``
GSROrdinary sord;
The error message, I get, is something like this.
undefined reference to beep::GSROrdinary::GSROrdinary()
undefined reference to beep::GSROrdinary::~GSROrdinary()
Yes, you need to tell CMake to compile your class. I suggest that you check out some CMake tutorials that can be found online. Here is a nice one: http://www.cs.swarthmore.edu/~adanner/tips/cmake.php - pay particular attention to the CMakeLists.txt file and syntax. You will have to modify your lib's CMakeLists.txt in order to add a new class.
You have to explicitly add your new file to the CMake file so that they get compiled and linked.
This commented sample could give you a start (basically you have to look for a add_library (LIBNAME files) directive in one of your CMakeLists.txt files and add your new file there, but you should also possibly read the documentation.