Undefined references when statically linking C++ and C libraries - c++

I have 3 libraries I am trying to link (more than that, but all that is needed for this explanation). The "root" library is c++, which has the second library as a dependency for it and is also c++. The third library is c and is a dependent of the second library.
When linking this project I am getting undefined references to all methods in the third library(which is in c) being called from the second library(which is c++). The third library has it's headers properly enclosed in "extern "C"" as it should for this type of use.
While trying to troubleshoot this I found that the macro for notifying the library that it is being built as static wasn't properly set, so I fixed that and found that it changed another macro that was being placed in front of all c-style functions from an export to instead say "extern "C"". To recap, c-style methods in a c++ library were being declared with "extern "C"" in front of them after I fixed another macro. When I did this all of the c-style methods I was calling in the second library from the "root" library started getting undefined references.
I thought this was odd as I've seen no other library do this, so I commended out the portion of the line where the macro was defined to "extern "C"", instead leaving it blank. When I did this the undefined references to the c-style methods in the second library went away and the undefined references to the methods in the third library returned.
I have tried to research this myself and pretty much every result is "Put an "extern "C" in brackets around it!", however that is already the case here. I also considered it could be a linker order issue, and verified the linker order set in the command going to the linker is appropriate. So I am at a loss as to what is causing this. It seems to be a name mangling thing, but I can't for the life of me find how this is happening or how to fix it.
My question: What the hell is going on? What other avenues can I explore to try and resolve this?
I am on Windows XP 32-bit, compiling with MinGW. If you want to look at code...well that is a bit complicated since this is for a big project, but the root library is a game engine I am working on, the second library is cAudio, and the third library is OpenAL soft. Here is the root directory of the repo, here is the base directory for cAudio, and here is the base directory for OpenAL soft we are using.
I apologize for this being so long, thanks in advance to anyone that made it this far!

I managed to find the cause of the issue. The short version is that CMake was misconfigured.
The long version is that we had definitions being added manually via CMake when we try to build the library as static (which is the case here). There is one for cAudio, as well as OpenAL. When OpenAL compiled it was using definitions as provided in it's portion of the CMake script appropriately. These definitions were not shared with other projects in the hierarchy. So when it came time for cAudio to compile the export macro didn't resolve to being blank, instead resolving to have it set for "dllimport". When cAudio went to link it was expecting symbols prefixed with "_imp", which was not the case in the compiled library. Thus causing the undefined references I was getting.
I resolved this by adding the appropriate definition in the cAudio CMake so that the import macro's resolved correctly when cAudio was being compiled with OpenAL includes.

Related

How does C++ linkage works in this case?

I built a C++ library for making games in most known platforms and it works alright. However, I ran into a minor problem with the linker, which I can't live with myself without figuring the answer.
I have two separate classes in two separate files: KinesisWorld in KinesisWorld.h and ASEngine in ASEngine.h . Both of them have a similar behavior in terms of implementation, they encapsulate functionality provided by other libraries, KinesisWorld inherits and calls Box2D functions and ASEngine calls angelscript functions. So far so good.
Now, when I am building an application that uses my library, as long as I don't include or use KinesisWorld, the linker won't attempt to link the Box2D library. As soon as I simply include KinesisWorld.h somewhere in the final executable source, it immediately complains of undefined references until I add Box2D to the linker. This is the behavior I always known and observed with other libraries as well.
Though, with angelscript, without including ASEngine.h at all, it will always complain about undefined references to angelscript, even if the final executable doesn't make any reference to it whatsoever.
Any idea of what can cause such thing? I tested it on Linux 32 bit and Windows 32 bit, with GCC and Visual Studio respectively, same behavior.
The linker doesn't care until the offending (declared but undefined) functions are called.
In this case, you aren't using any Box2D functions anywhere except in KinesisWorld but you ARE using angelscript somewhere in your library. Double check your ASEngine facade but in particular everywhere else (using the "find" feature across your entire project might help).

How can I link with (or work around) two third-party static libraries that define the same symbols?

I can't be the only one to run into this.
I have a C++ application that needs to link with one third-party and another static library set in an SDK. The SDK has, for some hideously frustrating reason, recompiled a subset of that same third-party library into their own (renamed) lib, although the symbols themselves are named the same and they are not encapsulated within a namespace. My application itself depends upon the same third-party library.
I've considered a few options, but maybe I'm missing something and hopefully a fresh look will help me out. Perhaps I'm close and someone will know the next step for one of these . I'll enumerate what I've tried and the shortcomings of each solution so far:
Link with both.
I get about 2500 lines of symbol redefinition / size change warnings and errors. This is when I first found that they defined the same symbols. I'm trying to recompile OpenSSL with g++ and drop it into a namespace at the moment...see edit below...
Link with the SDK only.
I get undefined symbols that my own code depends upon - this is when I found that their recompile of the third party lib is a subset, or at least was configured with one module disabled.
Link with the third party lib only.
I have a couple of undefined symbols reported by the SDK - one of them is actually a #define in a header file within the third party lib, so all references in the third party lib resolve to the definition, but references outside there do not. I moved that into the c file, which resolves that, however I still have two unresolved functions I can't find anywhere. This is the closest I've gotten so far.
Strip conflicting symbols from one lib and link in both.
So far this hasn't worked. It could be a version issue between the lib statically linked in the SDK and the versions I've tried using of the third-party lib, but it looks like some functions were moved between symbols, so by removing a symbol, I inadvertently remove a function that I need elsewhere. There doesn't seem to be a perfect mapping between functions in symbols in the SDK vs functions in symbols in the third-party lib. Is it plausible to strip functions without having to manually adjust addresses?
I've been examining symbols in libs with:
nm -C --defined-only lib<name>.a
And extracting entire objects with:
ar -x lib<name>.a <objname>.o
Hopefully this will also help others who have had to link with third-party libs that conflict with one another. For the sake of specifics, the third-party lib is OpenSSL, and the SDK is Opsec - libcpopenssl.a is the offending lib in Opsec.
**EDIT- A late entry possible workaround may be to recompile OpenSSL with g++ and put the whole thing in a namespace, and then link both libs. I'm trying that now...more to come...
A Google search indicate that SSL_get_peer_dh and DH_dup are really additions from libcpopenssl.a, and they don't exist in my copy of OpenSSL either. So you'll really have to link that library in. Mixing both libraries together (Approach 4 above) at binary level is unlikely to work -- OpenSSL is very picky about its ABI (they usually have .so files versioned down to the minor number) so you'd have to be very lucky to have an .so that's ABI-compatible to their .a file.
My suggestion is a variation of Approach 4, but at source level: you'll have link in the Opsec libcpopenssl.a, since it's a modified version of OpenSSL which include extra symbols (and possibly other modifications), and grab the extra functions you need from the OpenSSL sources and recompile those objects with libcpopenssl.a, so they can use the functions from the Opsec version. If you're only using a few OpenSSL functions which are not exported by libcpopenssl.a, this is quite doable.
Granted, that's still a cumbersome approach, but it's a guaranteed way to get symbol compatibility, provided of course that the Opsec SDK didn't make semantic changes to OpenSSL that will break the additional OpenSSL functions that you're pulling into your project.
(I'm new at StackOverflow so I don't know if this suggestion qualifies as a proper answer, but I don't have reputation points to post comments, anyway. I'll remove this if it's inappropriate.)
If you're morbidly curious, 249 files were modified in the most recent version of OpenSSL to get it to compile. The most common issue by far was the abundance of C-style pointer casts, particularly with void*. Now I see "reinterpret_cast" in my dreams.
This didn't solve it alone though - it still needs to be placed into a namespace in its entirety, which means modifying all of the files again as well as my own internal references to it. I think I'm going to pass on this for now.
Thanks for the help everyone.

Eclipse-CDT/C++: Undefined reference-errors although right .o-files are created and passed to the linker

At first: I am not using an already compiled library.
Here's the situation: I've got a C++ project in eclipse CDT that has a folder structure like this:
project
somefoldername
src
include
library
src
include
somefoldername/src and library/src are defined as source folders and somefoldername/include as well as library/include are defined as include folders (under C/C++ General->Paths and Symbols, which also affects the compilers -I option).
The "library" folder contains the source code of a library used by my own code (which can be found in "somefolder"). Well, compiling of the whole project works fine, but linking crashes with a whole bunch of "undefined reference" errors in the library's source.
The undefined reference errors occur, although *.o-files are created in which the missing functions should be found - and also are passed to the linker afterwards.
What am I doing wrong?
Edit: Updated to current configuration and the attempts to solve the problem.
Edit2: The accepted answer helped me out a bit, but the biggest problem seemed to be the "linking everything at once"-policy followed by eclipse. I went to autoconf and built the library first, before linking it to the main application. Although it's more work, it's a cleaner approach.
Three possibilities:
1) The "undefined" symbols aren't actually in your library
This is unlikely, but you can verify using the "nm" Linux command
2) You aren't setting the library search path ("dash-big-L") correctly in Eclipse
link static lib in eclipse cdt
... or ...
3) Perhaps you built the library with "C" linkage, but your program is using C++ linkage (or vice versa). If you're using the "C" (gcc") compiler, or have any "*.c" source files, then make sure all functions have prototypes in your .h header, and all prototypes use "extern "C"" as appropriate:
& http://msdn.microsoft.com/en-us/library/0603949d%28v=vs.80%29.aspx

LNK2038, iterator mismatch error, need to ignore

I'm getting the linker error LNK2038 when trying to convert a VS2008 project to VS2010. This error occurs when two different projects are compiled in which one is using _DEBUG preprocessor macro, and the other is not. Basically I have a 3rd party library that only has release .libs, so when I try and use that library when building my project in debug mode I get this mismatch.
I understand why Microsoft is giving this error (STL iterator safety), however our project does not use Microsoft's STL, we use STLPort, so this error means nothing to our project. I just need a way to prevent it from doing this check.
Inside of the STL includes there is a file called yvals.h, which includes the #pragma detect_mismatch definition for the various _ITERATOR_DEBUG_LEVEL settings. That set of definitions is wrapped in an #ifndef _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH, #endif. However, even if I define _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH as a preprocessor macro for my entire project I'm still getting the same linker error. I can even alter yvals.h to define that macro and it does nothing (I'm assuming because the STL itself would need to be recompiled).
So my question is basically, what steps can I take make _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH actually work as intended so that my project doesn't do this check anywhere when compiling in VS2010?
EDIT: I know this is a late response but I just found this post and realized I didn't post the solution. As others mentioned there was a mismatch in the libraries. As it turns out VS2010 changes the default directories for certain projects (I found a thread on MSDN at one point full of complaints about it), and that directory change had caused VS2010 to look in the wrong directory for the debug library, and it was finding the release library instead.
You must use the same version of the standard library, compiled with the
same options, if you expect to successfully link. If you use STLPort,
then you can only link with libraries which use the STLPort, not with
libraries which use the VC++ standard implementation. If you mix,
either you will fail to link, or you will get strange runtime errors.
The problem is that things like std::vector<>::iterator may be defined
completely differently; depending on where and how they are used, you
will find yourself using an instance constructed in a different library,
with a different layout.

Can I ask VC++ linker to ignore unresolved externals?

I'm trying to build a very complex open-source project with VC++. The project consists of dozens of libraries and one executable depending on those libraries.
For some reasons VC++ linker doesn't want to see about 40 functions implemented in one of those libraries and reports "unresolved external reference" on each, so I can't link. I don't want to waste time resolving the problem - those functions are likely never called.
I'd like to just ask the linker to link what it sees and insert some reasonable error handling (like reporting an error and terminating the program) instead of missing functions. How can I do that?
You can use the /FORCE:UNRESOLVED linker option.
The documentation for that contains the rather understated warning:
A file created with this option may
not run as expected.
In pratice, there'll be no error handling - just a crash.
If the functions are truly never called, then create actual libraries (.lib files) for the libraries. Then the linker will only extract from the libraries what's needed.
The linker's job is to resolve all references, so I don't think you're going to get it to insert error handling code.
P.S. The first thing I'd check is to see if C functions got compiled as C++, leading to the missing symbols.
If they're never called, remove the references from your project. If they are called, then fix the damn problem. There's no real other option here.
There are some notable exceptions, but most OpenSource projects are not designed to be built under VisualStudio.
Generally for a Windows port you are better off using either cygwin or the mingw system. My advice is usually for mingw, unless the program uses a lot of Unix OSey calls like pipes and signals.