A g++ link error - why the workaround works - c++

I am working in a big project. And now encounter a link error.
This error can be avoided by a workaround but I can not figure out why it works.
Here is the file structure related to my problem:
project
|-package_a
|--a.cpp
|--...
|-package_b
|--b.cpp
|--c.cpp
|--...
|-package_others
All the *.o in package_a will be packed in to a.a and *.o in package_b
will be packed into b.a
"g++ -o exec -Bstatic b.a a.a ..." is used to generate the binary.
In package_b/b.cpp, I added a function foo().
And in package_a/a.cpp, I used this function.
But here I will get a link error saying undefined reference of foo() in a.o
I can verify (by objdump) that foo() is already in b.o.
By changing the link command into "g++ -o exec -Bstatic a.a b.a ...", the binary can be built successfully. I now understand that the linker do care about the order in linkage list. But please understand this is a big project I have no permission to change the project configuration so the original link order must be kept.
Then I added a dummy function bar() in package_b/c.cpp, which do nothing
but just calling foo(), then original "g++ -o exec -Bstatic b.a a.a ..." will run
through without any link error.
Can anybody show me some light why just adding a dummy function in
the same package will work in this case?
I'm using g++ 4.4.4 and linux 2.6.18-194.el5
Any comment will be appreciated

This is normal. When linking, the linker goes through the list of object files, finding undefined references which are then satisfied by other object files/libraries coming after it.
You can change this behaviour by either
including one of the archives twice, as in
g++ -o exec a.a b.a a.a
using the -( construct
g++ -o exec -( a.a b.a -)
But please understand this is a big project I have no permission to change the project configuration so the original link order must be kept.
Tough luck... Maybe the manager or whoever just doesn't want you to use functions in b from a.
Then I added a dummy function bar() in package_b/c.cpp, which do nothing but just calling foo(), then original "g++ -o exec -Bstatic b.a a.a ..." will run through without any link error.
Could be that another function of package_b/c.cpp was already referenced, and the linker took bar() with it (because they are in the same file) and this referenced foo(), which was subsequently included in the output, too. It succeeded, because foo was in b.a too.

You may like to read up on how linkers work. BTW, -Bstatic flag is unnecessary because .a. object file archives link statically only (as if the list of object files contained in .a was specified on the command line instead of .a).
Alternatively, you can always wrap a list of archives to link with --start-group/ --end-group options to make the linker scan the list of archives multiple times, so that no ordering of archives is required (like MS VC++ does):
g++ -o exec -Wl,--start-group a.a b.a -Wl,--end-group
See man ld:
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either
explicit file names, or -l options.
The specified archives are searched repeatedly until no new
undefined references are created. Normally, an archive is searched
only once in the order that it is specified on the command line.
If a symbol in that archive is needed to resolve an undefined
symbol referred to by an object in an archive that appears later on
the command line, the linker would not be able to resolve that
reference. By grouping the archives, they all be searched
repeatedly until all possible references are resolved.
Using this option has a significant performance cost. It is best
to use it only when there are unavoidable circular references
between two or more archives.

GCC, unlike the Visual-C++-linker, requires static libraries to be supplied in an order so that references are defined before they are used. Don't ask me why, but you will always have to check that you are listing the files to be linked in the correct order with GCC.
There is an in-depth explanation here.

When you are using a function from a static library, you must on the command line first place the file from which the function is used, then the library where the function is defined. Otherwise, if you place the definition first, gcc (or more specifically, ld) discards the "unused" function. That's how gcc works, sorry.

Related

Passing `-l<libname>` vs passing `lib<libname>.a` directly to linker?

Suppose I have two files
// a.c
int a() {return 1;}
// b.c
int a();
int b() {return a();}
and I compile them to a.o and b.o, respectively.
In an attempt to make an executable or shared library, one can call gcc a.o b.o -o libab.so -shared. But I also noticed that one can also call gcc b.o -L. -l:a.o -o libab.so -shared to generate (apparently) the same output. To my surprise, even running gcc a.o -L. -l:b.o -shared results in a library that has both a() and b(). (Shouldn't linker discard the unused library b.o since a.o does not depend on it?)
The latter two presumably pass a in as if a.o was a library. Now if I run ar rcs liba.a a.o, gcc b.o -L. -l:liba.a -shared and gcc b.o liba.a -shared both run without any problem and give the same output.
However, I have also seen case where this trick doesn't work and results undefined references. My question is therefore as the titles says: what are the differences between passing an object as a library and as a normal object file, and are there any differences when it comes to C++?
The problem arose in a much larger project. Sorry for lacking mcve because I can't seem to isolate the problem.
[How does] Passing -l<libname> vs [differ from] passing lib<libname>.a directly to linker?
Passing -llibname.so will make GNU linker traverse the library only once when searching for a symbol (when not after --whole-archive option). Specifying .a file directly to the linker makes it search for every symbol in all the object files inside the .a file for every symbol, not only once.
From the GCC Linker options (emphasis mine):
-llibrary
...
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
From binutils ld options:
-l namespec
...
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
what are the differences between passing an object as a library and as a normal object file, and are there any differences when it comes to C++?
That depends on the implementation. In the most general sense, Unix-style linkers such as you are asking about search for objects named via -l options in a library search path, whereas if you name a file directly, you must specify the exact file.
Additionally, if you use an -l option to specify a file to link then, in the general case, the linker constructs a filename from the argument by prepending "lib" and appending ".a", or in some other way, such as by searching also or instead for ".so" files. (The GNU linker that you appear to be using provides an exception to this behavior when the first character of the argument is :. In that case it takes the rest of the argument as an exact file name, and searches for that.)
Many linkers also accept explicit library names specified on the command line (e.g. libfoo.a instead of -lfoo), so these need to be able to determine what type of file each is. Normally this is by examining the file, not by relying on its name. And GNU ld, at least, extends this file type detection to files specified via -l options.
The order in which objects and libraries are specified on the command line, by whatever specific form, matters to typical linker implementations. For example, the docs for GNU ld specify that
options which refer to files, such as ‘-l’ or ‘-T’, cause the file to
be read at the point at which the option appears in the command line,
relative to the object files and other file options
which is important because
The linker will search an archive only once, at the location where it
is specified on the command line. If the archive defines a symbol
which was undefined in some object which appeared before the archive
on the command line, the linker will include the appropriate file(s)
from the archive. However, an undefined symbol in an object appearing
later on the command line will not cause the linker to search the
archive again.
But of course
You may list the same archive multiple times on the command line.
The docs are not altogether clear on this, but empirically, the use of the term "archive" in the above is significant. It is effectively only archive files -- static libraries -- to which the "searched only once" provision applies. To a first approximation, the relative order of different ordinary object files and shared libraries on the GNU linker's command line, no matter how designated, does not impact symbol resolution.
So yes, it does matter whether you specify regular object files or static archives or shared libraries to the (GNU) linker, and their order matters to some extent, but the manner in which you specify them does not matter.
I have also seen case where this trick doesn't work and results undefined references.
With the GNU linker, that will be because of genuinely missing libraries or objects, or because of an unsuitable order of static archives relative to other object files or archives. Some other linkers are more sensitive.
Short answers:
The -L and -l options provide a shortcut for locating library archives (and shared libraries). But once you've used -l to locate a library (in the standard locations, or in a location specified by -L), the reading of that library is identical to the way it would be read if you specified its filename (e.g. /lib/libx.a) at the same spot on the command line explicitly.
When you specify a single object (.o) file, the entire contents of that file get loaded unconditionally. When you specify a library archive (.a) file, only those objects within it that are necessary (to satisfy outstanding undefined references) are loaded.

C++ - Problem Undefined Reference to PCM::getInstance()

Before i ask a new question, i have read few or more question about this, but i keep confuse.
I Compile my program with :
g++ -std=c++11 -Wall -O3 -fopenmp main.cpp -o main -D WITH_COUNTER -I /usr/local/src/pcm -L /usr/local/src/pcm -L /usr/local/lib
Then, i found the error :
main.cpp:(.text.startup+0x27e): undefined reference to PCM::getInstance()
main.cpp:(.text.startup+0x289): undefined reference to PCM::resetPMU()
main.cpp:(.text.startup+0x310): undefined reference to PCM::program(PCM::ProgramMode, void const*)
So, can anyone explain to me how to solve this?
You don't actually link with the libraries themselves.
The -L option tells the linker to add a directory to its search-path, but the linker will not go through all libraries in its path to find which might be correct (there could be hundreds or even thousands).
Instead you need to explicitly specify libraries to link with using the -l (lower-case L) option.
For some example library foo, there will exist a file named libfoo.a or libfoo.so. To link with it you use -lfoo.
If the documentation for your library doesn't tell you which library you should link with, look for a suitable named file (as mentioned above) and use the correct option to link with the library.

Libquantum code Understanding Makefile

I tried to run .c file called grover.c in this C application libquantum
www.libquantum.de/files/libquantum-1.1.1.tar.gz
Now I this application already contains a Makefile.in and I can generate the executables called shor and grover using the command
./configure
make
make demos
But when I try to run grover.c using gcc or clan like this
clang grover.c
It gives me error of lots of undefined function reference.
In function oracle':
grover.c:(.text+0x50): undefined reference toquantum_sigma_x'
grover.c:(.text+0x89): undefined reference to quantum_toffoli'
grover.c:(.text+0xc8): undefined reference toquantum_toffoli'
grover.c:(.text+0xf2): undefined reference to quantum_cnot'
grover.c:(.text+0x137): undefined reference toquantum_toffoli'
grover.c:(.text+0x16b): undefined reference to quantum_toffoli'
grover.c:(.text+0x1b0): undefined reference toquantum_sigma_x'
I need to know how can I remove this error and if I can run this c code called grover.c in this application.
Thanks,
It looks like your compiler can not find one or more libraries to link to. My hunch is that the makefile has the appropriate commands to invoke the linker.
If you look at your makefile, you probably will see some commands like -L -l,
when the flag -L add a directory to the default search path for libraries and the flag -l is used to name the library to link.
for example -L/lib/openGL -lglut32 would cause the library libglut32.so.X.Y.Z which is found in the directory /lib/openGL. (not this is for a Linux system, but it should be fairly similar for Mac).
N.B. X.Y.Z are the version number of the library.
Once you work this out, there may be issues with the load finding the libraries, especially if they are in non-standard locations.
------------------------ edit --------------------------
After I posted this, and went to bed I realized that I missed a potential case (and thanks to Paul Griffiths for also noticing my omission.....teach me to do multiple things at once).
Any how, just compiling a simple file, say hello.c, as clang hello.c -o hello works because everything is in one file and clang will automatically link to the C run-time library.
If, in your case the code is spread across multiple files, say grover.c and file1.c you would need to do:
clang -c grover.c -o grover.o
clang -c file1.c -o file1.o
clang grover.o file1.o -o grover
(or alteratively clang grover.c file1.c -o grover)
SO what the first two lines are doing is translating the source-code files (grover.c and file1.c) into object files. THe third line covers the two object files into an executable.
Finally, both these cases can be involved. You could have multiple files as well as missing libraries.

Compiling C++ project with libraries

My friends developed a C++ game in Visual Studio on Windows, and I would like to compile it on my Linux x64 machine. I'm not very familiar with C++ but I'm trying g++ on command-line. However I only get a bunch of undefined reference errors.
The basic file structure is:
Libraries/SFML-2.0/lib
Libraries/SFML-2.0/include
Libraries/SFML_Linux64/lib
Libraries/SFML_Linux64/include
Libraries/Box2D/lib
Libraries/Box2D/include
Libraries/Box2DLinux/lib
Libraries/Box2DLinux/include
Game
Game/lib
Game/includes
Game/... (other subdirectories)
I tried the following command:
g++ -Wall Multiplaya/app.cpp -I Libraries/SFML_Linux64/include/ -I Libraries/Box2DLinux/include/ -L Libraries/SFML_Linux64/lib/ -L Libraries/Box2DLinux/lib/
This is the kind of errors I get (some lines snipped and replaced with ...):
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o: I funktionen "_start":
(.text+0x20): undefined reference to `main'
/tmp/ccFXe37c.o: I funktionen "mp::createNetworkThread(void*)":
app.cpp:(.text+0x10): undefined reference to `worldDataMutex'
app.cpp:(.text+0x15): undefined reference to `sf::Mutex::lock()'
...
/tmp/ccFXe37c.o: I funktionen "mp::App::exec()":
app.cpp:(.text+0x148): undefined reference to `mp::ResourceHandler::instance()'
app.cpp:(.text+0x15a): undefined reference to `mp::ResourceHandler::loadTexture(std::string)'
app.cpp:(.text+0x3d7): undefined reference to `mp::Window::Window(mp::WorldData*)'
app.cpp:(.text+0x406): undefined reference to `mp::Controller::Controller(mp::World*, mp::Window*)'
...
app.cpp:(.text+0x471): undefined reference to `sf::Mutex::unlock()'
app.cpp:(.text+0x4bb): undefined reference to `sf::Thread::launch()'
app.cpp:(.text+0x4d7): undefined reference to `sf::Clock::Clock()'
app.cpp:(.text+0x4e6): undefined reference to `sf::Clock::getElapsedTime() const'
...
collect2: fel: ld returnerade avslutningsstatus 1
(I hope you can look through the Swedish above.)
That's very courteous of you to provide library paths to the linker. However, linkers are ungrateful slobs and usually do not look for any library files on their own when they see an undefined reference to a function.
Like, undefined reference to `sf::Mutex::lock() — I bet there is libsfml-system.so.2.0 or whatever in the Libraries/SFML_Linux64/lib/ directory, with the definition for sf::Mutex::lock(). But the linker doesn't care. You have to say -lsfml-system at the end of your compile invocation.
This will make g++ understand to look for functions not only in libstdc++ library, but also in the libsfml-system file. And if g++ happen to find such a file in the default or additional (specified with -L flag) library directories, he will use it for resolving references to function calls.
But you have to say to it explicitly what library files you want to throw in, specifying only directories with libraries doesn't do much. So, try to use
g++ -Wall Multiplaya/app.cpp -I Libraries/SFML_Linux64/include/ -I Libraries/Box2DLinux/include/ -L Libraries/SFML_Linux64/lib/ -L Libraries/Box2DLinux/lib/ -lsfml-system
How to build C++ programs
C++ programs are built in two steps: the first step is compilation, and the second step is linking.
During compilation, you turn your source files into object files — things which contain compiled machine code. Now there is a trick you have to understand. Say, if you have a.cpp with
// a.cpp
int f(int x);
int main() {
return f(42);
}
you can compile it with g++ -c a.cpp and it will get you object file a.o (with compiled code), without any compilation errors. But wait! There is no actual definition of what f() is in a.cpp!
And now, when you go to the second step, linking, and invokes g++ -o test a.o, it will complain that there is undefined reference to f(). So let's make b.cpp with this text:
// b.cpp
int f(int x) {
return 2 * x - 3;
}
compile it with g++ -c b.cpp and then perform linking as g++ -o test a.o b.o — and wow, now it links without an error!
What happened? Well, when the compiler sees a function call, it puts in object file not an actual call instruction, but a placeholder that says "call a function with such and such name and such and such parameters". And then the linker takes a bunch of object files, and sews them together. When it sees such a placholder, it looks for the mentioned function in object files it was given, and puts actual call to it instead of the placeholder.
So, the building of C++ program looks something like this:
For each x.cpp file you have, call g++ -c x.cpp <bunch of flags> -I<include directories>
Then call g++ -o resultprogram a.o b.o c.o d.o ... <bunch of flags> -L<library directories> -l<additional libraries>
-l flag tells the linker that if he sees a call to a function, and there is no such function defined anywhere in the specified object files (a.o, b.o, etc), then it should look in this library. Please not, that the linker won't look in any object files and/or libraries except those you specified (okay, it will also look in standard C++ library libstdc++, but that's it).
However, this process is pretty boring to do by hand if you have 10 or more files. That's why people use "project files" and "build systems". When Visual Studio builds a project, it does all those steps I mentioned: it compiles every single file in a project, and then links the result together. On Linux, you don't have Visual Studio, but you have make utility. There are some utilities for converting VS projects to makefiles, I believe.

linking a self-registering, abstract factory

I've been working with and testing a self-registering, abstract factory based upon the one described here:
https://stackoverflow.com/a/582456
In all my test cases, it works like a charm, and provides the features and reuse I wanted.
Linking in this factory in my project using cmake has been quite tricky (though it seems to be more of an ar problem).
I have the identical base.hpp, derivedb.hpp/cpp, and an equivalent deriveda.hpp/cpp to the example linked. In main, I simply instantiate the factory and call createInstance() twice, once each with "DerivedA" and "DerivedB".
The executable created by the line:
g++ -o testFactory main.cpp derivedb.o deriveda.o
works as expected. Moving my derived classes into a library (using cmake, but I have tested this with ar alone as well) and then linking fails:
ar cr libbase.a deriveda.o derivedb.o
g++ -o testFactory libbase.a main.cpp
only calls the first static instantiation (from derivedA.cpp) and never the second static instantiation, i.e.
// deriveda.cpp (if listed first in the "ar" line, this gets called)
DerivedRegister<DerivedA> DerivedA::reg("DerivedA");
// derivedb.cpp (if listed second in the "ar" line, this does not get called)
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
Note that swapping the two in the ar line calls only the derivedb.cpp static instantiation, and not the deriveda.cpp instantiation.
Am I missing something with ar or static libraries that somehow do not play nice with static variables in C++?
Contrary to intuition, including an archive in a link command is not the same as including all of the objects files that are in the archive. Only those object files within the archive necessary to resolve undefined symbols are included. This is a good thing if you consider that once there was no dynamic linking and otherwise the entirety of any libraries (think the C library) would be duplicated into each executable. Here's what the ld(1) manpage (GNU ld on linux) has to say:
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
Unfortunately there's no standard way to include every member of an archive in the linked executable. On linux you can use g++ -Wl,-whole-archive and on Mac OS X you can use g++ -all_load.
So with GNU binutils ld, the link command should be
g++ -o testFactory -Wl,-whole-archive libbase.a -Wl,-no-whole-archive main.cpp
the -Wl,-no-whole-archive ensures that any archive appearing later in the final link command generated by g++ will be linked in the normal way.