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.
Related
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.
I have working C++/Windows program compiled with Visual Studio 2008. The program consists of just two .cpp files. I am now attempting to compile and link it using MinGW. So far I have successfully compiled both source files without error, but now when I link them with the command...
g++ -o program.exe file1.o file2.o
... I get many instances of "undefined reference to.." assorted graphics related functions like:
GetStockObject, SelectObject, MoveTo, LineTo, SetPixel, TextOut, BitBlt, CreatePen etc.
I am not getting undefined references for any other types of windows call. Clearly I have missed something in my linker command line, but cant work out what.
Since this spans two (similar) prior answers, I'll add it as a separate answer, rather than as duplicate comments on those preceding answers.
Better, rather than jumping in and adding "-lgdi32", you should first add the "-mwindows" option; this tells GCC that you are building a Windows application, (its default is a "console" application type), and so causes it to automatically bind a number of additional graphics device interface specific libraries, (one of which is gdi32.dll). Only if adding this option still fails to resolve all symbols need you worry about what other non-default libraries may be needed.
All these functions are located in Gdi32.dll. You need to link Gdi32.lib to make them work. You can try:
g++ -o program.exe file1.o file2.o -L MinGW\lib -lgdi32
By the way, Microsoft documents each function extensively and names the appropriate library. For example: GetStockObject.
You can solve it like this:
For each undefined reference, look up that function at Microsoft Developer Network documentation. In your case, google for
GetStockObject msdn
The MSDN page describing the function contains at the bottom a section "Requirements". Here it lists required DLLs that you need to link to.
In case of GetStockObject, that's Gdi32.dll
Extend your command line to include -lGdi32
Retry the linking and repeat for any remaining undefined references.
I'm adding two classes and libraries to a system, parent.so and child.so deriving from it.
The problem is when the program is loading child.so it cannot find parent's virtual function's definition from parent.so.
What happens,
nm -D child.so will gives something like (I just changed the names)
U _ZN12PARENT15virtualFunctionEv
The program will crash running
_handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); //filename is child.so
it'll give an error with LD_DEBUG = libs
symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv (fatal)
The thing I cannot explain is, I tried LD_DEBUG = symbols using GDB, when running dlopen, the log shows it tried to look up basically in all libaries in the system except parent.so, where the symbol is defined. But from libs log parent.so is already loaded and code is run, and it is at the same path of all other libraries.
......
27510: symbol=_ZN12PARENT15virtualFunctionEv; lookup in file=/lib/tls/libm.so.6
27510: symbol=_ZN12PARENT15virtualFunctionEv; lookup in file=/lib/tls/libc.so.6
27510: symbol=_ZN12PARENT15virtualFunctionEv; lookup in file=/lib/ld-linux.so.2
27510: child.so: error: symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv(fatal)
How the program or system is managing which library to look for a symbol's definition?
I'm new to Linux, can anybody point me some directions to work on?
Thanks.
EDIT
The command used to generate parent.so file is
c++ -shared -o parent.so parent.o
Similar for child.so. Is any information missing for linking here? Looks like child is only including parent's header file.
EDIT2
After another test, calling
_handle = dlopen("parent.so", RTLD_NOW|RTLD_GLOBAL);
before the crashing line will solve the problem, which I think means originally parent.so was not loaded. But I'm still not very clear about the cause.
You need to tell the linker that your library libchild.so uses functionality in libparent.so. You do this when you are creating the child library:
g++ -shared -o libchild.so child_file1.o child_file2.o -Lparent_directory -lparent
Note that order is important. Specify the -lparent after all of your object files. You might also need to pass additional options to the linker via the -Wl option to g++.
That still might not be good enough. You might need to add the library that contains libparent.so to the LD_LIBRARY_PATH environment variable.
A couple of gotchas: If you aren't naming those libraries with a lib prefix you will confuse the linker big time. If you aren't compiling your source files with either -fPIC or -fpic you will not have relocatable objects.
Addendum
There's a big potential problem with libraries that depend on other libraries. Suppose you use version 1.5 of the parent package when your compile your child library source files. You manage to get past all of the library dependencies problems. You've specified that your libchild.so depends on libparent.so. Your stuff just works. That is until version 2.0 of the parent package comes out. Now your stuff breaks everywhere it's used, and you haven't changed one line of code.
The way to overcome this problem is to specify at the time you build your child library that the resultant shared library depends specifically on version 1.5 of libparent.so`.
To do this you will need to pass options from g++/gcc to the linker via the -Wl option. Use -Wl,<linker_option>,<linker_option>,... If those linker options need spaces you'll need to backslash-escape them in the command to g++. A couple of key options are -rpath and -soname. For example, -rpath=/path/to/lib,-soname=libparent.so.1.5.
Note very well: You need to use the -soname=libparent.so.1.5 option when you are building libparent.so. This is what lets the system denote that your libchild.so (version 1.0) depends on libparent.so (version 1.5). And you don't build libparent.so. You build libparent.so.1.5. What about libparent.so? That needs to exist to, but it should be a symbolic link to some numbered numbered version (preferably the most recent version) of libparent.so.
Now suppose non-backward compatible parent version 2.0 is compiled and built into a shiny new libparent.so.2.0 and libparent.so is symbolically linked to this shiny new version. An application that uses your clunky old libchild.so (version 1.0) will happily use the clunky old version of libparent.so instead of the shiny new one that breaks everything.
It looks like you're not telling the linker that child.so needs parent.so, use something like the following:
g++ -shared -o libparent.so parent.o
g++ -shared -o libchild.so -lparent child.o
When you build your main program, you have to tell the compiler that it links with those libraries; that way, when it starts, linux will load them for it.
Change their names to libparent.so and libchild.so.
Then compile with something like this:
g++ <your files and flags> -L<folder where the .so's are> -lparent -lchild
EDIT:
Maybe it would be a smaller change to try loading parent.so before child.so. Did you try that already?
I'm attempting to design a shared library of shared libraries using g++ with hopes of simplifying my compile scripts and easing my update process in the future, but I'm still novice at best with GNU tools and writing libraries, at that. Can anyone provide advice on whether the following idea is possible with g++?
For convenience, consider the following file system layout:
main.cpp
libraryX/
libraryX/libX.so
libraryX/libraryY/
libraryX/libraryY/libY.so
libraryX/libraryZ/
libraryX/libraryZ/libZ.so
My goal is to be able to link indirectly using cascading relative paths. For instance, main.cpp links to libraryX/libX.so, which links to libraryY/libY.so and libraryZ/libZ.so. Is it possible to only link main.cpp to libX.so and use functions defined in libY.so and libZ.so?
If so, could you provide an example of the flags one would need to do so? I've been trying variations of the following command using various sources from Google to no avail:
g++ -shared -fPIC -Wl-rpath=libraryX -LlibraryX -lX.so main.o -o executable
Any guidance or references are greatly appreciated.
Don't do this (even if you can figure out how).
When you link against -lX, the static linker must know all other shared libraries that are "part of this link". Since -lY is not on the link line, the static linker will either give you an error, or it must somehow figure out where libY.so is coming from. For the latter, it has to replicate the RPATH search that the runtime loader will perform. This replication is error prone (the static linker may not use the exact same algorithm) and best avoided.
Finally, your command line is totally wrong: -shared means you ask the linker for a shared library, but you are clearly trying to link an executable. You generally should not use -fPIC when linking an executable. Also, -Wl-rpath=... should be -Wl,-rpath=... (the comma is important).
I'm trying to use some of the functions that are in the /lib/libproc-3.2.6.so library in my Ubuntu distribution.
I have downloaded and installed the header files and they are defined in my source files.
Currently, this is all I'm trying to do, just for starters...
proc_t **read_proc = readproctab(0);
But I get the following compiler error:
/tmp/cclqMImG.o: In function `Sysmon::initialise_sysmon()':
sysmon.cpp:(.text+0x494): undefined reference to `readproctab'
collect2: ld returned 1 exit status
I'm aware I'm probably doing some wrong with the command I'm using to compile it, but due to lack of experience I'm not sure what I'm doing wrong. This is the g++ command I'm using to compile my cpp file:
g++ -o sysmon.o sysmon.cpp `pkg-config --libs --cflags gtk+-2.0`
Can someone please give me some pointers as to where I'm going wrong.
You are not linking your executable against libproc (that is a linker error message).
Try adding -lproc to the linker command.
You are not actually linking against the library that you wish to use, you are merely including its header files, therefor, the compiler will complain about undefined references.
You can read up on linking against shared libraries here.
A small suggestion, start using the build tool SCons, it can take care of linking to libraries for you, just add the ones you wish to use in the SConstruct file required by SCons and then you don't have to mess about with compiler specifics. You also gain lots of other good stuff that SCons provide. It's highly recommended.
Ubuntu 17.04
You probably want to use -lprocps instead of -lproc.