Can't link a dynamic lib including iostream [duplicate] - c++

This question already has answers here:
Using only g++ works, but not "g++ -c" and ld
(4 answers)
Closed 6 years ago.
ld is acting weirdly and I want to understand what's going on. In a mycode.cpp, I have the following:
#include <algorithm>
#include "mycode.hpp"
// awesome stuff here
I compile it with g++ -fPIC -c mycode.cpp and link it with ld -Bshareable -o libmylib.so mycode.o. Works like a charm.
Then I want to call cout in mycode.cpp. Actually, even before adding this cout, if I just add #include <iostream> in the code above, while linking I get the error
mycode.o: In function `__static_initialization_and_destruction_0(int, int)':
mycode.cpp:(.text+0x50): undefined reference to `__dso_handle'
ld: mycode.o: relocation R_X86_64_PC32 against undefined hidden symbol `__dso_handle' can not be used when making a shared object
ld: final link failed: Bad value
If I link it with g++ -shared, it works, but that's not the point. I do not understand what's wrong here, and I am looking for insights.
EDIT: I understand one must call g++ instead of ld directly. My problem is, I want to understand what's under the hood: why including iostream break things while algorithm is already here (so ld knows stdc++)

link it with ld -Bshareable -o libmylib.so mycode.o. Works like a charm.
It only works by accident.
User-level code should never be linked directly with ld, and should always use the appropriate compiler driver (g++ here) to perform the link. Anything else, and you'll fail with weird link-time or runtime errors (just as you did here).

Related

Symbol present in .so, compiled .o references it but link fails

I have a strange problem linking c++ with Leptonica. Normal function invocation works fine, but I need functions from the library which were originally not exposed in the .so library. So I have searched for the two interesting functions in the source, removed the static keyword, so they look similar to exposed ones. I have remade the full library after a make clean. The .so file looks OK:
nm liblept.so.5.0.0
...
000000000009d010 T dewarpGetMeanVerticals
000000000009d160 T dewarpGetTextlineCenters
000000000009d8f0 T dewarpIsLineCoverageValid
Compiling to .o file and observing it:
g++ -c -std=c++11 -I../leptonica/src/src/ preproc.cpp -L../leptonica/src/.libs/ -llept -o preproc
nm preproc
...
U dewarpGetMeanVerticals
U dewarpIsLineCoverageValid
While the same compiling without -c flag results in
/tmp/ccCPqS1R.o: In function `_dewarpGetTextlineCenters(Pix*, int)':
preproc.cpp:(.text+0x3d5): undefined reference to `dewarpGetMeanVerticals'
/tmp/ccCPqS1R.o: In function `_dewarpBuildPageModel(L_Dewarp*, char const*)':
preproc.cpp:(.text+0x81d): undefined reference to `dewarpIsLineCoverageValid'
collect2: error: ld returned 1 exit status
What do I do wrong?
Thank you in advance: Balázs
I think you may need the extern "C" keywords around those functions if you want to expose them in the so. Since the names don't appear to be mangled by the C++ compiler in the .so this is probably not the case.
I notice that you're showing us what's in liblept.so.5.0.0 and linking against liblept.so. Is it possible that you need to update a symbolic link so that you're linking against the correct .so file?

Google RE2 library cannot compile with 'make testinstall' in ubuntu

Gurus!
I am using Ubuntu 13.10 64-bit to compile latest Google RE2 library, but 'make testinstall' failed to compile, here is the log:
kevin#ubuntu:~/re2$ make testinstall
cp testinstall.cc obj
(cd obj && g++ -I/usr/local/include -L/usr/local/lib testinstall.cc -lre2 -pthread -o testinstall)
/tmp/ccSsaSXS.o: In function main':
testinstall.cc:(.text+0xce): undefined reference tore2::FilteredRE2::FirstMatch(re2::StringPiece const&, std::vector > const&) const'
/usr/local/lib/libre2.so: undefined reference to pthread_rwlock_rdlock'
/usr/local/lib/libre2.so: undefined reference topthread_rwlock_wrlock'
/usr/local/lib/libre2.so: undefined reference to pthread_rwlock_destroy'
/usr/local/lib/libre2.so: undefined reference topthread_rwlock_init'
/usr/local/lib/libre2.so: undefined reference to `pthread_rwlock_unlock'
collect2: error: ld returned 1 exit status
make: * [testinstall] Error 1
I tried to replace -pthread with -lpthread, still failed, then I dumped libre2.so and found that pthread_xxx is in it.
Here is the issue tracking in RE2 forum: https://code.google.com/p/re2/issues/detail?id=100
Anyone here have ever complied RE2 successfully ? Thank you!
See this comment:
Adding -pthread to LDFLAGS seems to fix make test (all tests are
passing), but not make testinstall.
That will get you to the next error
Depending on what you build it for 'make testinstall' might not be necessary.
I just needed to get python re2 port working, and this can be installed after running make install.
I encounter this problem before. Modify the makefile and use -lpthread instead of -pthread.
So I tried looking for the lines in testinstall.cc that were causing the symbol errors and I found out that the only line was on line 18:
18 - f.firstMatch(:abbccc:, ids);
I commented this line out (so that the FullMatch function below is still called) and just ran g++ testinstall.cc -lre2 -pthread -o testinstall (basically what the Makefile does) and I was able to get a binary successfully. Although this might not really solve the problem, its good to know that we can still use the RE2::Fullmatch and partial match functions
If I were to guess, maybe there is a dependency somewhere inside the filtered_re2 module?
I had the same problem. But if you compile with -static everything goes well.
nm -C shows that the "missing" symbol exists in both .a and .so files.

Undefined reference to member function found in static library

I know what you're thinking - this has been answered a million times. I wish I could put something in the Title that would make it clear that I already know that the order of libraries is important.
I'm using g++ on Centos 6 64. I have a simple test program:
#include <ptlib.h>
int main()
{
PTimer indirectTimer1_;
indirectTimer1_.SetNotifier(0);
return 0;
}
and I compile and link it with this command:
g++ -I./ptlib/include/ mm.cpp ptlib/lib_linux_x86_64/libpt_s.a -lpthread -lrt
and I get this as an answer back:
/tmp/cc53itXb.o: In function `main':
mm.cpp:(.text+0x52): undefined reference to `PTimer::SetNotifier(PNotifierTemplate<int> const&)'
collect2: ld returned 1 exit status
But I know that PTimer::SetNotifier is in the .a file:
nm -AC ptlib/lib_linux_x86_64/libpt_s.a | grep SetNotifier
ptlib/lib_linux_x86_64/libpt_s.a:osutil.o:0000000000003dd8 T PTimer::SetNotifier(PNotifierTemplate<long> const&)
To make matters more confusing, when I compile the library on Centos 5, 32bit, and run the same test, it links just fine.
I've tried using '-Lptlib/lib_linux_x86_64 -lpt_s' and I've tried using the -Wl,--start-group / -Wl,--end-group args to no avail. If I add 'ptlib/src/ptlib/unix/osutil.cxx' to the g++ line, it compiles and links just fine. Unfortunately, this is but a sample of the unreferenced functions in our main program. Not all of the, just a few seemingly random methods like this one are undefined (which also links just fine on Centos 5, 32 bit).
As you can see, I've tried a lot of things but still haven't figured it out. I need something else to try! Or someone to point out something terribly easy that I am doing wrong.
undefined reference to `PTimer::SetNotifier(PNotifierTemplate<int> const&)'
PTimer::SetNotifier(PNotifierTemplate<long> const&)
Notice the difference in int vs. long?

Compiling Fortran netCDF programs on Ubuntu

Ok, newb question here.
I'm trying to compile simple_xy_wr.f90 -- a netCDF example program -- using gfortran on Ubuntu, and I must be doing something pretty silly; I don't have much experince compiling Fortran.
First, I've got the libnetcdf-dev package installed, which includes files like
/usr/lib/libnetcdf.a
/usr/lib/libnetcdff.a
/usr/include/netcdf.mod
So, I've tried to compile the code with (various command like)
f95 -o xy -I/usr/include/ -L/usr/lib/ -lnetcdff -lnetcdf simple_xy_wr.f90
and I get the following output
/tmp/ccE6g7sr.o: In function `check.1847':
simple_xy_wr.f90:(.text+0x72): undefined reference to `__netcdf_MOD_nf90_strerror'
/tmp/ccE6g7sr.o: In function `MAIN__':
simple_xy_wr.f90:(.text+0x284): undefined reference to `__netcdf_MOD_nf90_create'
simple_xy_wr.f90:(.text+0x2b6): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x2e8): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x432): undefined reference to `__netcdf_MOD_nf90_def_var_manydims'
simple_xy_wr.f90:(.text+0x468): undefined reference to `__netcdf_MOD_nf90_enddef'
simple_xy_wr.f90:(.text+0x4aa): undefined reference to `__netcdf_MOD_nf90_put_var_2d_fourbyteint'
simple_xy_wr.f90:(.text+0x4cb): undefined reference to `__netcdf_MOD_nf90_close'
collect2: error: ld returned 1 exit status
I think that I'm including the right libraries. E.g. it seems that __netcdf_MOD_nf90_strerror should be there:
$ nm /usr/lib/libnetcdff.a | grep __netcdf_MOD_nf90_strerror
000000000004a100 T __netcdf_MOD_nf90_strerror
What am I doing wrong?
(FWIW, a few relevant references I've looked at are below.
undefined reference using netcdf library
Compiling problems with gfortran and NETCDF
Compiling and Running Fortran Programs - a basic guide
)
Ordering of object files and archives on the linker command line is very important on Unix systems since the default linker behaviour is to search for symbol definitions only in archives that follow the object file or archive, where an unresolved reference was found, referred to single pass linking.
This means that if your code references __netcdf_MOD_nf90_strerror, then the archive that contains the definition of this symbol (libnetcdff.a) must appear after the list of object files from your program. libnetcdff.a itself references symbols from the C library libnetcdf.a, hence it must be linked after libnetcdff.a. So the correct link order is:
/tmp/ccE6g7sr.o libnetcdff.a libnetcdf.a
where /tmp/ccE6g7sr.o is the temporary object file that the assembler produces from the compiled source file. The correct command line to compile your code is then:
f95 -o xy -I/usr/include/ simple_xy_wr.f90 -lnetcdff -lnetcdf
In this case the linker is not called directly, rather the compiler does it. GCC compilers pass all link-related things in the same order to an intermediate utility called collect2 which then calls the actual linker ld.
Note that if shared object versions of the netCDF library archives are also present (i.e. there are libnetcdff.so and libnetcdf.so), then the linker would prefer them to the static archives (unless static linking is enabled with the -static option) and the final link phase would be handled to the run-time link editor (RTLD) (/lib64/ld-linux-x86-64.so.2 on Ubuntu). In this case the same command line as in your question would actually succeed without link errors, despite the fact that both libraries are positioned before the code that references them, as the missing symbol references would be resolved by the RTLD while it is loading the executable file.
In Ubuntu 12.10, the order of the libraries is the trick (as Hristo suggested):
angelv#palas:~$ gfortran -o xy -I/usr/include/ -L/usr/lib/ -lnetcdf -lnetcdff simple_xy_wr.f90
/tmp/ccj95anF.o: In function `check.1847':
simple_xy_wr.f90:(.text+0x72): undefined reference to `__netcdf_MOD_nf90_strerror'
/tmp/ccj95anF.o: In function `MAIN__':
simple_xy_wr.f90:(.text+0x284): undefined reference to `__netcdf_MOD_nf90_create'
simple_xy_wr.f90:(.text+0x2b6): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x2e8): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x432): undefined reference to `__netcdf_MOD_nf90_def_var_manydims'
simple_xy_wr.f90:(.text+0x468): undefined reference to `__netcdf_MOD_nf90_enddef'
simple_xy_wr.f90:(.text+0x4aa): undefined reference to `__netcdf_MOD_nf90_put_var_2d_fourbyteint'
simple_xy_wr.f90:(.text+0x4cb): undefined reference to `__netcdf_MOD_nf90_close'
collect2: error: ld returned 1 exit status
angelv#palas:~$ gfortran -o xy -I/usr/include/ simple_xy_wr.f90 -L/usr/lib/ -lnetcdf -lnetcdff
angelv#palas:~$ ./xy
0 12 24 36
*** SUCCESS writing example file simple_xy.nc!

How to use GLEW with MinGW [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I was trying to use glew32.lib file to link in my project, than I compile Glew source by myself to get glew.a file. Now, I have these link errors in my project:
g++ -o Chapter10(OpenCLTest).exe src\Chapter10(OpenCLTest).o -lopengl32 -lglew -lglut32 -lglu32 -lopencl
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x167): undefined reference to `_imp____glewBindBuffer'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x39a): undefined reference to `_imp__glewInit'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x3a7): undefined reference to `_imp__glewIsSupported'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x48a): undefined reference to `_imp____glewGenBuffers'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x495): undefined reference to `_imp____glewBindBuffer'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x4dd): undefined reference to `_imp____glewBufferData'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x50b): undefined reference to `_imp____glewGetBufferParameteriv'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x1d67): undefined reference to `_imp____glewBindBuffer'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x1d7f): undefined reference to `_imp____glewDeleteBuffers'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x1d95): undefined reference to `_imp____glewBindBuffer'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x1dad): undefined reference to `_imp____glewDeleteBuffers'
src\Chapter10(OpenCLTest).o:Chapter10(OpenCLTest).cpp:(.text+0x2078): undefined reference to `_imp____glewBindBuffer'
collect2: ld returned 1 exit status
It is good to solve this problem but by the way I want to ask are there any other opengl implementaions of gl extentions?
I'm afraid you can't use glew.lib with g++ (because .lib is a proprietary Microsoft format). These errors you get are missing function entry points, meaning that you didn't compile GLEW correctly (the required functions are not exported in your .so - need to know more details in order to be able to solve this issue).
As for the other part of the question, you can try GLEH. It is still in the development phase and may need some tweaking to work for you, but we've been using it quite successfuly in linux so it shouldn't be too bad.
(I know this is a bit late, but I figured it might solve someone else's problem, so) I had a very similar problem compiling a program that linked to GLEW dynamically. It turns out that I had overlooked the libglew32.dll.a file - that also needed to be present (in addition to libglew32.a and glew32.dll that I had previously copied to my project folder.)
You could try GLee which essentially does the same thing as GLEW.
Strange nobody has said anything about this. By default on Windows, the GLEW headers use declspec(dllimport) for all of the external functions, which mangles all of their names. This is why all of the missing external symbol names all have _imp____ at the front.
If you wan't to use a static build of GLEW (you mentioned something about libglew.a), define GLEW_STATIC during the build of GLEW and during the build of your application. This will unmangle the names for static linking.
If you want to link to a shared library version of GLEW, make sure to build GLEW with GLEW_BUILD. I'm not sure if this is necessary with gcc but it is if the library is built with MSVC.
Furthermore, the GNU toolchain actually supports Microsoft's .lib format for linking. source
You may find it easiest to just compile GLEW yourself or even include it in your project. It is only one source file and a few headers. To compile the library manually, use something along the lines of gcc -shared -o libGLEW.dll -Wl,--out-implib=libGLEW.dll.a -O2 -DGLEW_BUILD glew.c. To get the static version use something like gcc -c -O2 -DGLEW_STATIC glew.c instead.