2

Suppose I want to version the libs in binaries made. For static libs, I thought this approach would work but it does not:

LibInfo.h - Base class for all libinfo classes. Registers an object in gvLibInfo vector when a child is constructed.

#ifndef IFACE_H
#define IFACE_H

#include <vector>

class LibInfo;
extern std::vector<LibInfo*> gvLibInfo;

class LibInfo
{
    public:
        virtual int getversion() = 0;
        void reglib()
        {
            gvLibInfo.push_back(this);
        }

        LibInfo()
        {
            reglib();
        }
        virtual ~LibInfo()
        {}
};


#endif

Lib1.h - Derived from LibInfo and creates an object l1. Lib2.h is the same except getversion returns 2.

#ifndef LIB1_H
#define LIB1_H

#include "LibInfo.h"

class Lib1 : public LibInfo
{
    public:
        int getversion()
        {
            return 1;
        }

    private:
};

Lib1 l1;

#endif

main.cpp

#include "Lib1.h"
#include <iostream>
using namespace std;

vector<LibInfo*> gvLibInfo;

int main()
{       
    for(vector<LibInfo*>::iterator it = gvLibInfo.begin(); it != gvLibInfo.end(); it++)
    {       
        cout << (*it)->getversion() << endl;
    }

    return 0;
}

Compiling -

g++ -c Lib1.h -o Lib1.o
g++ -c Lib2.h -o Lib2.o
ar cr lib.a Lib1.o Lib2.o
g++ main.cpp -o app -L/home/duminda/statictest/lib.a

When I run, nothing happens. I thought this maybe due to one of several reasons:

  1. At the time Lib1 l1 is made, gvLibInfo has not been constructed.
  2. I saw somewhere that the linker will remove any unused variables from a static lib. However, when I run on the binary nm it shows up this :

0000000000603280 B gvLibInfo

0000000000603270 B l1

0000000000603278 B l2

I guess l1 & l2(The corresponding object of class Lib2 are there but what does that 'B' flag mean? 3. Something else I don't know.

halfer
  • 19,824
  • 17
  • 99
  • 186
nakiya
  • 14,063
  • 21
  • 79
  • 118
  • I ran a gdb session. It does indeed seems that the vector gets constructed after static lib is loaded. Then, 1. Can I delay the lib load or force vector to be constructed earlier somehow? 2. Or, do I just have to use primitive data types? – nakiya Oct 07 '10 at 09:58
  • Further, if I remove `#include "Lib1.h"` from main.cpp and replace it with `#include "LibInfo.h"` then I `nm` does not show the symbols `l1` and `l2`. – nakiya Oct 07 '10 at 10:22
  • :D. My first problem is solved. `__attribute__((init_priority()))` took care of that. Now I want someone to help me with the problem above. :) – nakiya Oct 07 '10 at 10:26
  • This is the question where you should update with the --whole-archive thing. – shodanex Oct 08 '10 at 09:36
  • But, if I did, no one will notice would they? – nakiya Oct 08 '10 at 09:44
  • You can comment under the answers, just to say you updated your question. the people who already answered will notice. And I think updating your questions pops it up, but I am not sure. You can also do the opposite, and replace your dummy Test classes in the other questions with your more meaningful libinfo. People can come up with alternative design, or find the question more interesting. They first reaction won't be : why would you do that in the first place. – shodanex Oct 08 '10 at 11:04

2 Answers2

1

Change the top of main.cpp to look like this, so that the vector is created before the derived instances.

#include "LibInfo.h"

std::vector<LibInfo*> gvLibInfo;

#include "Lib1.h"
#include "Lib2.h"

BTW, the 'B' from nm indicates symbol in BSS (uninitialized data). The man page for nm has all the symbol types listed.

erich
  • 11
  • 1
0

The first answer to this question propose to use the --whole-archive flag. The main difference is, instead of referring to an external object, the library refers to an external function.

Linking does not occur with -L, but with -l, i.e. it should be :

-L/path/to/libdir -lname

If your library is :

/path/to/libdir/libname.a
Community
  • 1
  • 1
shodanex
  • 14,975
  • 11
  • 57
  • 91