Milan Radovich <> writes:
> Hello,
>
> I have 2 files:
>
> a.cc:
> ---------------------------------------
> int main()
> {
> return 0;
> }
> ---------------------------------------
>
> b.cc:
> ---------------------------------------
> #include <iostream>
>
> bool foo()
> {
> std::cout << "foo" << std::endl;
> return true;
> }
>
> const bool bar = foo();
> ---------------------------------------
>
> If I compile the application like that:
>
> g++ -c a.cc b.cc
> g++ a.o b.o -o a
>
> then when application is executed, it outputs a string "foo".
>
> But if I create a static library from b.cc and then link application
> with that library, like that:
>
> g++ -c a.cc b.cc
> ar rcs libb.a b.o
> g++ -L. -lb a.o -o a2
Although this has no effect in relation to your current issue, you will
need to change the ordering here in the second invocation of g++. As
described in the documentation for gcc, "The linker handles an archive
file by scanning through it for members which define symbols that have
so far been referenced but not defined." What this means is, you have
to be correct as to ordering in supplying libraries and object files to
g++. As you have it above, you are passing g++ libb.a (-lb) *before* it
has seen your object file, a.o. Were you to require any library code
from libb.a in a.o (though you don't in the example given) this would
not be linked in because it would not "have so far been referenced but
not defined" at this point. This needs to be:
g++ -L. a.o -o a2 -lb
(As I have mentioned, the difference is not apparent in the example as
given, but will be an issue in more complete code).
> then when application is ran, it doesn't print anything.
>
> After I searched for the reason why this happens, I found that
> when linking with static libraries, linker omits code which is not
> reachable through any execution path.
>
> The question is:
>
> 1) Is it a correct behaviour according to a Standard?
It is correct in the sense that the Standard puts little to no
requirements on static libraries; indeed it hardly mentions them at
all. In effect, it is an implementation detail. The difference you are
experinecing is not an inconsistency either, since you are applying two
different build models and the Standard, as mentioned, puts no
requirements on their `effect' being the same.
> 2) Is there is a pattern which forces linker to add such a code to an
> executable?
If I understand it correctly, you can view a static library (an
`archive') as a collection of the object files from which it is
composed. The linker will make the code from any one of the archived
object files available *only* if your program requires the code. By
`required', I mean that your user code references a symbol in that
archive file that is defined there. Currently, your code does not
reference any symbol in libb.a:b.o. The `pattern', then, is to ensure
that it does.
Note: this does not necessarily mean that your user code must reference
either bool foo() or const bool bar. It must, however, reference
/something/ in libb.a:b.o, or this won't be linked in. Indeed, why
should it? If you are not actually making any use of /any/ of the code
in libb.a:b.o, then what is the point of that code? Why would you want
const bool bar initialized and bool foo() called in doing so?
> A case where such an idiom is very usefull is described in Chapter 8.3 of
> Andrei Alexandrescu's "Modern C++ Design".
I am not familiar with this work and hence am not aware of how this
idiom is used here. Perhaps if you give a little more context about
what it is this idiom is intended to achieve, more concrete help can be
given.
Regards
Paul Bibbings
|