mingw unresolved external when linking caused by naming convention confusion - c++

I am vainly trying to compile kmymoney using the emerge windows tool
all seems to go well until linking kmymoney
I get a huge number of unresolved references.
It appears the problem is that the libraries I am linking against are built without the windows specific "_imp__" on the exports but when I am compiling kmymoney the linker is expecting the "_imp__" + mangled name
For example the linker is looking for _imp___ZNK7KLocale28negativeMonetarySignPositionEv
but the export is called _ZNK7KLocale28negativeMonetarySignPositionEv
I assume I have to pass another flag or remove a flag from gcc to tell it to look for the correct export. but I am not sure how to do this. and cannot find the required documentation. even if I did I am not sure where to put it in the cmake file.
Any pointers would be greatly appreciated.
EDIT:
I have discovered that the libraries in fact do have the _imp__ prefix
it appears there is a missing underscore
when I grep for one of the missing functions I get the following
r:\lib>nm *.a | grep _ZNK7KLocale28negativeMonetarySignPositionEv
00000000 T __ZNK7KLocale28negativeMonetarySignPositionEv
00000000 I __imp___ZNK7KLocale28negativeMonetarySignPositionEv
Clearly the prefix is there. but it looks like its missing the first underscore
The prefix is __imp__ whereas the linker is looking for _imp__
Any ideas how I can resolve this??

Related

Unresolved external symbol linking to a VS6 library

I've got an NIUSB8452 DAQ, with which the vendor thoughtfully provided ni845x.lib and ni845x.h so I could use C instead of LabView to do my data reading. However, I'm having some problems with getting the lib working in VisualStudio 2015. The first point of alarm is probably that their documentation says it is compatible with VS6, but I've seen other people on here successfully use libraries for VS6 on VS15, so, I hope I can also be so beautiful.
The problem that I am having right now is that on a build, I'm getting linker errors that read something like
unresolved external symbol #ni845xStatusToString#12 referenced in function (function name follows)
While googling around, I found this question which mentioned dumpbin /exports. To check that I wasn't running into a 32/64 bit error like the poster described (since I wasn't really sure how to diagnose this, it seemed as good a place to start as any), I ran dumpbin /exports on the external lib. I got a pile of public symbols, including
FF06 __imp__ni845xStatusToString#12
FF06 _ni845xStatusToString#12
I'm definitely not seeing #ni845xStatusToString#12, which is what VisualStudio is complaining about being unresolved.
What's the difference between #ni845xStatusToString#12 and _ni845xStatusToString12? What does the presence of the latter and the absence of the former indicate that I am doing wrong with this import?
Notes
The lib and header have been included in the file as described in this question, with the exception that I gave a full path to the lib for #4, which I think implies you only need the filename.
I'm using extern "C" { #include ni845x.h } in my cpp file, although ni845x.h does have the #ifdef __cplusplus boilerplate in there.

rogue missing c++ symbol - debugging strategies?

I am building/using the python module for LAMMPS, which is the open source Molecular Dynamics simulator (project home, source).
The python module works by compiling the C++ application as a library, and using CDLL/ctypes to call a C function interface. When you call the CDLL() function in python, the load fails if there are any missing symbols that the OS doesn't find in the library itself, and can't load from other available libraries.
The particular symbol I'm getting as missing is a C++ mangled name __ZN3MPI3Win14Set_errhandlerERKNS_10ErrhandlerE, which is probably MPI_Win_set_errhandler (or some namespaced/object oriented equivilent with a similar name). For context, I've compiled it using the python/setup_serial.py file, which should build with a dummy MPI interface, and shouldn't reference any real MPI symbols at all; so this is a rogue reference that's crept in somewhere. I've also made some modifications to the source, but I get the same error when I disable all my changes.
My question is, what is the best debugging strategy for finding out where a symbol is referenced in a dynamic library giving this sort of error? So far, I've tried searching the source for references to this symbol (or parts of the name,) but I'm not finding any instances (in fact, the only results are the binary files from the python build process, of the library I'm having trouble importing.)
My next step is to search inside the binary somehow, I guess, but I have no idea where to begin that (or some other strategy).
c++filt is your friend
$ c++filt __ZN3MPI3Win14Set_errhandlerERKNS_10ErrhandlerE
MPI::Win::Set_errhandler(MPI::Errhandler const&)
Now do a quick google search on that library
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=512616
Looks like there is a case where parts are upgraded but not recompiled. The second thing is to look at the link line for the complier and see what libraries it includes.
Final last resort is to do something like:
readelf -s /path/to/libfoo.so
And start grepping around to see if it's defined somewhere.

How to handle linker errors in C++/GNU toolchain?

Given a C++/GNU toolchain, what's a good method or tool or strategy to puzzle out linker errors?
Not sure exactly what you mean but if you are talking about cryptic linker symbols like:
mylib.so: undefined symbol: _ZN5CandyD2Ev
you can use c++filt to do the puzzling for you.
c++filt _ZN5CandyD2Ev
will return Candy::~Candy() so somehow Candy's destructor didn't get linked.
With gcc toolchain, I use:
nm: to find the symbols in object files
ld: to find how a library links
c++filt: to find the C++ name of a symbol from its mangled name
Check this for details.
Well the first thing would be RTFM. No, seriously, read the documentation.
If you don't want to do that, try a search on the error that comes up.
Here are a few other things to remember: "missing" symbols are often an indication that you haven't included the appropriate source or library; "missing" symbols are sometimes an indication that you're attempting to link a library created with a different mangling convention (or a different compiler); make sure that you have extern "C" where appropriate; declaring and defining aren't the same thing; if your compiler doesn't support "export" make sure your template code is available for when you instantiate objects.
Look at the names of the symbols that are reported to be problematic.
If there are missing symbols reported, find out in which source files or libraries those function/... should be defined in. Inspect the compilation/linker settings to find out why these files aren't compiled or linked.
If there are multiply defined symbols the linker usually mentions which object files or libraries contain them. Look at those files/their sources to find out why the offending functions/... are included in both of them.

Troubleshooting compile time link errors

I'm trying to statically link to libcrypto.a (from the openssl library) after building it from source with a new toolchain. However whenever I try to use any of the functions from that library, I keep receiving "undefined reference" errors. I've made sure the right header file was included. I've also double checked the symbol table of libcrypto.a and made sure these functions are indeed defined.
Is there anything else I can do to debug this error- like getting more info out of the linker or examining libcrypto.a itself, to find out why the linker is spitting out "undefined reference" error when the indicted symbols shows up in the symbol table?
Undefined reference/symbol is a linker error indicating that the linker can't find the specified symbol in any of the object modules being linked. This indicates one or more of the following:
The specified class/method/function/variable/whatever is not defined anywhere in the project.
The symbol is inaccessible, probably due to an access specifier (in C++, doesn't apply to ANSI C)
The reference is incorrect. This can be due to a spelling error or similar problem. (unlikely)
You've neglected to include the required library in your build script when calling the linker.
I see your post is tagged c++. OpenSSL is written in C.
Did you remember to do
extern "C" {
#include <various SSL files>
}
?
grep the symbol out of libcrypto using nm
so you can see if its there - probably not (duh)
ssl has 2 libs , maybe you are using the wrong one
what exectly is the missing symbol

how to avoid "already defined error" in C++

I am gettings these type of errors in a MFC VS6 project while linking the application:
msvcrt.lib(MSVCRT.dll) : error LNK2005: _atoi already defined in LIBC.lib(atox.obj)
I know what it means (a function exists in 2 different libraries); to solve it I should have to exclude one of the 2 libraries (msvcrt.lib or libc.lib).
But if I do this there are all kinds of unresolved external errors. So I would like to keep using both libraries.
Is there any way to tell the linker that I want to use the _atoi function in libc.lib and not in msvcrt.lib (or the other way around)?
Any help or direction would be great.
This error certainly means that you're linking two pieces of codes that have been compiled using distinct runtime libraries. MSVCRT.dll is the dynamic version, while LIBC.lib is the static one. If you do this, all hell break loose. Try finding which parts of your code use which version, and sort this out.
You have a runtime clash. Using multiple runtime libraries is generally a bad thing.
You can use /nodefaultlib:msvcrt (or /nodefaultlib:libc) in your linker options to exclude one or the other.
Actually, before resorting to that, check your project settings. If I recall correctly, libc is the single-threaded runtime in VS6, and msvcrt is the multi-threaded runtime. If you have multiple projects in your solution, make sure they're all using one or the other.
There seems to be an option which you can use to ignore errors like this: in projectsettings > link > check 'Force file output'. This will generate the program even if there are linkerrors.
The Build output gives something like this:
msvcrt.lib(MSVCRT.dll) : warning LNK4006: _atoi already defined in LIBC.lib(atox.obj); second definition ignored
Of course you will need to use this option with care as it can generate an application which won't work in some cases, but here it probably doesn't do any harm (I hope).
Thank you for the other replies, but that didn't seem to be an option in my particular case.