'Undefined reference' despite class being linked properly - gcc

I have the following problem - I'm trying a sort of bastardized build of the poco library for C++ (ie, using a premake-generated makefile instead of the poco makefile because I'm building on windows without msvc)
I've actually managed to get all the libraries built into .a files. The problem arises when I try to actually use classes - and then gcc swears up and down that it can't find the reference. This despite the fact that I have checked the libraries with ar -t and seen that the classes in question do indeed exist there.
In general, what could be the problem? I have a library that at least claims to have the requisite .o files, yet the references are still undefined.
For example, I have an undefined reference to Poco::XML::InputSource::InputSource(std::istream&), yet "InputSource.o" is in the linked library, and the requisite ctor is in the header file.

Related

Proper link order for gcc

ALL,
I'm trying to figure out a proper link order when I build my software on Linux with gcc.
I have an .a library, which export an interface class (class with a lot of pure virtuals).
This a library is linked to libraryA.so and libraryB.so, because both those libraries have an actual implementation for the interface.
Now libraryB is also linked to unixODBC.
Now, both libraryA and libraryB are linked to libraryC, which actually instantiates the classes from them.
If I understand correctly the linking order should be as follows:
librarya.a libraryA odbc odbcinst libraryB
for libraryC.
But after successful build and running make install, trying to load libraryC fails, because libraryB is not visible.
Is my linking correct? Or better yet - is my understanding of the linking is correct - the referenced library should be first and then follows referencing libraries and I just need to update the LD_LIBRARY_PATH variable.
Thank you for clarifying.

How to build and Interface a Fortran95 library with C

I'm porting an old C++ project to run on RHEL 6.7 with gcc 4.4.7. The code was originally made to run on an SGI machine.
I have a library .a which is presumed to have been compiled on the old machine (and thus there's no hope of running it in the new one) however, along with this .a file I also have the headers and source files. I am assuming that these are the ones that are used to make the .a file. The Makefile that was used is now long gone, I just have the source code.
My question is, is there a way to "reverse engineer" the library? I would like to know what functions the .a library contains so I can make it on my machine.
I will add that I am new to static and shared libraries so I'm not entirely sure what the .a file contains or how it is any different from including the headers.
Update:
I have looked into the included code and realized that the C files only work to interface with functions defined using Fortran95. I think that now I'm supposed to build the Fortran95 codebase and somehow interface that with the C code. Once I do that I will have a library that should (hopefully) compile in my native system. How can I do this?

How to statically link a library to another library with all symbols resolved

I have some XML parsing utility functions written inside C headers and source files based on expat library.
For this I have compiled my source files to a static library with expat statically linked to it.
I am able to use and the functions from the resulting xml utilities library with my applications only if I statically link both the utility library and expat with my application. I was of the view that I should be able to get my application built with only statically linking my utility library without requiring to statically link expat again with the application executable. Only linking my application with the utility library gives undefined symbol error for expat.
Can someone please guide me what am I missing ? I am using gcc compiler.
Thanks....
"I have compiled my source files to a static library with expat statically linked to it."
I'm fraid you haven't. A static library is not produced by the linker; no linkage is involved, so nothing can be linked to it.
A static library is nothing but a bag of object files in ar archive format.
When you are linking something that is produced by the linker - namely a program or a shared library -
you may offer such a bag to the linker. It will look in the bag and take out just the object files it needs to
carry on the linkage and link them into the target. The bag spares you the difficulty of
needing to know exactly which of the object files in it the linker will need, but the bag itself contributes nothing at all to the linkage.
Later
How can I get expat static library included in my utilities library, so that I only need to link my executable with a single static library. I don't want to extract the two archives and merge the object files together.
There is no other way of combining two ar archives.
Your resistance to linking libexpat is puzzling, without further context. It is available
through the package manager on any distro. You've made a library that depends on libexpat. Clients that link your
library will need also need to link libexpat. This is an utterly routine sort of dependency
that you should simply document and - if you are packaging your library - include
in the package dependencies. Almost invariably when we write new libraries we are augmenting the
libraries already available to our target users. If every library statically
incorporated all of its own dependencies then they would all be the size of an
operating system and of no practical use.

Proper way to link a static library using GCC

Why is it that some static libraries (lib*.a) can be linked in the same way that shared libraries (lib*.so) are linked (ld -l switch), but some can not?
I had always been taught that all libraries, static or not, can be linked with -l..., however I've run into one library so far (GLFW), which does nothing but spew "undefined reference" link errors if I attempt to link it this way.
According to the response on this question, the "proper" way to link static libraries is to include them directly, along with my own object files, rather than using -l. And, in the case of the GLFW library, this certainly solves the issue. But every other static library I'm using works just fine when linked with -l.
So:
What could cause this one library to not work when linked rather than included directly? If I knew the cause, maybe I could edit and recompile the library to fix the issue.
Is it true that you're not supposed to link static libraries the same way you link shared libraries? (And if not, why not?)
Is the linker still able to eliminate unused library functions from the output executable when the library is directly included in this way?
Thanks for the replies! Turns out the problem was due to link order. Apparently, if you use a library which in turn has other library dependencies, those other dependencies must be listed after the library, not before as I had been doing. Learned something new!
Have you cared to indicate to GCC the path of your library (using -L) ? By using -l solely, GCC will only be able to link libraries available in standard directories.
-L[path] -l[lib]
The correct way to link a static library is using -l, but that only works if the library can be found on the search path. If it's not then you can add the directory to the list using -L or name the file by name, as you say.
The same is true for shared libraries, actually, although they're more likely to be found, perhaps.
The reason is historical. The "ar" tool was original the file archive tool on PDP11 unix, though it was later replaced entirely by "tar" for that purpose. It stores files (object files, in this case) in a package. And there's a separate extension containing the symbol table for the linker to use. It's possible if you are manually managing files in the archive that the symbol table can get out of date.
The short answer is that you can use the "ranlib" tool on any archive to recreate the symbol table. Try that. More broadly, try to figure out where the corrupt libraries are coming from and fix that.

Cmake add_library with boost source files introduces references to non-existant files

we're building a cross-platform utility which must have a small footprint. We've been pulling header files from boost as and when we need them but now we must link against some boost C++ thread code. The easiest immediate solution was to create our own custom library using CMake's "add_library" command to create a static library composed of some boost thread source files. These compile without any problems.
The difficulty arises when I try to link to this library from an executable. Visual Studio 2008 returns an error saying that it cannot link to "libboost_thread-vc90-mt-sgd-1_40.lib". What really puzzles me is that I've grepped through all the source code and CMake config files and I can't find any reference to this libboost library, leading me to think that this has been autogenerated in some way.
This works OK in Linux, can anyone point out why I'm experiencing these issues in Windows?
#Gearoid
You found the correct reason for your problem, but not the correct solution. The BOOST_AUTO_LINK_NOMANGLE is an internal, i.e. for library authors, definition to control the auto-linking. The user level definition is BOOST_ALL_NO_LIB which when defined disables the auto-linking feature for all Boost Libraries code you use. This is described in the user.hpp configuration header (see user.hpp near the bottom and the Boost Config documentation). You can also control this on a per library level as describe in that header.
Ok, well, it turns out that Boost uses this auto-link feature for Visual Studio which embeds references to a mangled (ie, platform-compiler-mult-threaded, etc) boost library name.
The header file which controls this is called "auto_link.hpp" which lives in the config directory of the boost include tree. There's a special preprocessor definition called "BOOST_AUTO_LINK_NOMANGLE" which toggles this behaviour.
Another triumph of mediocrity for Microsoft.

Resources