Linking errors on library built using cmake - c++

I guess I just made a simple mistake but I'm not getting which..
Anyways I'm working on a library, also I'm using cmake to build the Makefiles for the project: https://github.com/immapoint/NaNO3/blob/master/CMakeLists.txt
Everything works just fine when compiling the library; it builds the following Files:
bin/libNaNO3.dll
lib/libNaNO3.dll.a (I don't like that name as well)
To test the whole thing, I got another project set up, also using cmake. https://github.com/immapoint/NaNO3TestApp/blob/master/CMakeLists.txt
The main file to test the library looks like this:
https://github.com/immapoint/NaNO3TestApp/blob/master/src/main.cpp
But when it comes to compiling the main file, I'm getting following errors:
CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xbf): undefined reference to `nano::Event<int>::attach(std::function<void(int)> *)`
CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xd3): undefined reference to `nano::Event<int>::notify(int)`
[...]ld.exe: CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj): bad reloc address 0x8 in section `.rdata'
This error occures whether I'm building the project using make/cmake or compiling the source file directly using
g++ -Wall -pedantic -ansi -std=c++0x main.cpp [-L./lib -I./include] -lNaNO3
So the problem seems not to lie in cmake but in ld.
I'm working with CMake version 2.8 and MinGW containing GCC version 4.7.2.
Additional information:
Compiler output with -fPIC:

This has nothing to do with CMake or the linker. You need to include the definitions for the nano::Event member functions in the header, not in a separate source file, since templates are instantiated at compile time. By the time the linker gets there, it's too late.
For a fuller explanation, see Why should the implementation and the declaration of a template class be in the same header file? and http://www.parashift.com/c++-faq-lite/templates-defn-vs-decl.html

Related

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

How to correctly set GSL path on mac

I have 'correctly' installed gsl on mac 10.13.2.
In my c++ program, I am calling like usual, for example:
#include <gsl/gsl_math.h>
However while running the code, it can not find the gsl.
fatal error: 'gsl/gsl_math.h' file not found
I was wondering how to correctly link gsl PATH and libraries.
I have tried,
setting PATH and LD_LIBRARY_PATH in .bash_profile
setting PKG_CONFIG_PATH to .../Gsl2.3/lib/pkgconfig
$which gsl-config returns
/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/bin/gsl-config
$pkg-config --libs gsl returns
-L/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/lib -lgsl -lgslcblas -lm
The only solution I can find is to run everytime with gsl linked.
Like:
g++ $(gsl-config --cflags) mycode.cc $(gsl-config --libs) && ./a.out
But I was wondering if the GSL PATH can be set globally so that I can simply run
g++ mycode.cc && ./a.out
This is how c++ code is compiled and built:
COMPILATION
A compilation unit will take each cpp file and work its way through included headers to locate forward declaration of implementations of symbol signatures of used functionality in your code. In your case this involves gsl/gsl.h. If the file cannot be found in the search directories, which you can expand by specifying C_INCLUDE_PATH and or CPLUS_INCLUDE_PATH. If you omit #include <gsl/gsl_math.h>, your code will not compile as there are signatures, which cannot be found for GSL functions, which you use.
LINKING
Once you have compiled all cpp/cc files you need to link the binary, which can be executed. The linking process consists of a search through all symbols in your .o/.obj... files and a matching of the same to what it can find in your object files and the libraries, which you have specified using for example -lgsl. If all goes well, every lookup finds an according binary implementation for your machine's hardware model (i.e. 64bit/32bit ..., Arm, Intel, ... etc). If some are not found you will find linkage errors.
What you are asking is, is there a way that C++ does not work as above? No!
If you leave out #include <gsl/gsl.h> or if said file is not found in your search paths, compilation will not work or. If you omit -lgsl, linking will fail. If you find it annoying to write all the above stuff in the command line, write a Makefile to reduce the building process to ideally a simple command: make.
Don't forget, that if you are linking against the shared library version of GSL, you might need specifying LD_LIBARAY_PATH on Linux and DYLD_LIBRARY_PATH on Macs as well.
TLDR: you cannot ask a c++ compiler / linker to work differently as designed.

Using gcov to test a c++ program

I am using gcov for the first time to analyze my program (C++)
The program consists of three classes and I have built the project using Code::Blocks.
When I am invoking the program using the following command:
C:\Users\XXX\Documents\Test\TreeObjModel\src>gcc
-fprofile-arcs -ftest-coverage Tree.cpp
I receive the following error:
Tree.cpp:1:18: fatal error: Tree.h: No such file or directory
compilation terminated
While the cpp files are in the directory "C:\Users\XXX\Documents\Test\TreeObjModel\src\" , the header files are in directory "C:\Users\XXX\Documents\Test\TreeObjModel\include\"
Do we need to have both the code and header files in the same directory?
Thanks in advance.
You should use the -I flag to specify where your header files are.
Judging from your example, you should add -I../include
You have at least two options to instruct the compiler where to find the header files (includes).
-Ipath_to_includes as parameter for gcc compiler. E.g. -I../include
When including in your program, specify the directory. E.g. #include "../include/foo.h"
My strategy would be to just compile my project successfully and only then try to use some other stuff, like flags for code coverage. I say this because your error does not have anything to do with gcov, and trying to instrument your program to get code coverage before your program even compiles, makes things more complicated for you. One step at a time ;)

Problems with linking C++ code

I'm tying to learn how to make and use a static library and I've faced some problems. This is what I've done.
First I've written some code and placed in into String.h and String.cpp files.
Then I've compiled it into an object file:
mingw32-g++ -c -O2 -s -DNDEBUG String.cpp -o .\obj\String.o
Then I've archived(?) it:
ar cr .\lib\String.lib .\obj\String.o
And indexed(?) it:
ranlib .\lib\String.lib
After that I've successfully compiled and linked the tests with mingw:
mingw32-g++ -std=c++03 -Wall -O2 -s -DNDEBUG .\test\src\test.cpp .\lib\String.lib -o .\test\bin\test.exe
The test compiled, linked and ran perfectly.
After that I wanted to include this library into my MSVS12 project. I've:
Added a path to the String.h to the Project - C/C++ -General - Additional Include Directories
Included String.h to some project header
Added a path to the String.lib to the Project - Linker - General - Additional library directories
Added String.lib to the Project - Linker - Input - Additional dependencies
After all these steps when I try to build the project the linker gives me many LNK2011 and LNK2019 errors. It seems to me that it can not find the implementation of my functions...
Please, tell me what I'm doing wrong and how can I fix it. Thanks!
C++ doesn't have much of a standard regarding binary formats -- not even how names are recorded in a library. (C++ compilers like to "mangle" names, inserting things like argument- and return-type codes into them. But they don't agree on exactly how to do that.) Result being, libraries from one compiler are rarely portable to another compiler unless the functions in them are declared as extern "C".
You'll have to either declare your library functions as such, or compile the library with Visual Studio if that's where you want to use it. (You could also put the library's code in a header file if you wanted, but it sounds like you're trying to have an already-compiled, static library.)

Linking errors when trying to compile Fubi

This problem is not specific to Fubi, but a general linker issue. These past few days (read as 5) have been full of linking errors, but I've managed to narrow it down to just a handful.
I'm trying to compile Fubi (Full Body Interaction framework) under the Linux environment. It has only been tested on Windows 7, and the web is lacking resources for compiling on a *nix platform.
Now, like I mentioned above, I had a plethora of linking problems that dealt mostly with incorrect g++ flags. Fubi requires OpenNI and NITE ( as well as OpenCV, if you want ) in order to provide it's basic functionality. I've been able to successfully compile both samples from the OpenNI and NITE frameworks.
As far as I understand, Fubi is a framework, thus I would need to compile a shared library and not a binary file.
When I try to compile it as a binary file using the following command
g++ *.cpp -lglut -lGL -lGLU -lOpenNI -lXnVNite_1_5_2 -I/usr/include/nite -I/usr/include/ni -I/usr/include/GL -I./GestureRecognizer/ -o FubiBin
and I get the output located here. (It's kind of long and I did not want to ruin the format)
If I instead compile into object files (-c flag), no errors appear and it builds the object files successfully. Note, I'm using the following command:
g++ -c *.cpp -lglut -lGL -lGLU -lOpenNI -lXnVNite_1_5_2 -I/usr/include/nite -I/usr/include/ni -I/usr/include/GL -I./GestureRecognizer/
I then am able to use the ar command to generate a statically linked library. No error [probably] occurs (this is only a guess on my end) because it has not run through the linker yet, so those errors won't appear.
Thanks for being patient and reading all of that. Finally, question time:
1) Is the first error regarding the undefined reference to main normal when trying to compile to a binary file? I searched all of the files within that folder and not a single main function exists.
2) The rest of the undefined reference errors complain that they cannot find the functions mentioned. All of these functions are located in .cpp and .h files in the subdirectory GestureRecognizer/ which is a subdirectory of the path I'm compiling in. So wouldn't the parameter -I./GestureRecognizer/ take care of this issue?
I want to be sure that when I do create the shared library that I won't have any linking issues during run-time. Would all of these errors disappear when trying to compile to a binary file if they were initially linked properly?
You are telling the compiler to create an executable in the first invocation and an executable needs a main() function, which it can't find. So no, the error is not normal. In order to create a shared library, use GCC's "-shared" option for that. Trying some test code here, on my system it also wants "-fPIC" when compiling, but that might differ. Best idea is to dissect the compiler and linker command lines of a few other libraries that build correctly on your system.
In order to add the missing symbols from the subdirs, you have to compile those, too: g++ *.cpp ./GestureRecognizer/*.cpp .... The "-I..." only tells the compiler where to search when it finds an #include .... I wouldn't be surprised if this wasn't even necessary, many projects use #include "GestureRecognizer/Foo.h" to achieve that directly.
BTW:
Consider activating warnings when running the compiler ("-W...").
You can split between compiling ("-c") and linking. In both cases, use "g++" though. This should decrease your turnaround time when testing different linker settings.