tags:

views:

185

answers:

4

I'm trying something spooky here. I'm trying to write C++ programs, compiled with GNU's g++, but without a dependency on libstdc++ :) but it seems that I need that for even the most basic things need it.

A libstdc++ with a configurable feature set would be acceptable.

The command I use is

g++ -nodefaultlibs -fno-rtti -fno-exceptions -lc

Without libstdc++, I get:

undefined reference to `operator delete(void*)'  
undefined reference to `operator new(unsigned int)'  
undefined reference to `vtable for __cxxabiv1::__class_type_info'  
undefined reference to `vtable for __cxxabiv1::__si_class_type_info'  
undefined reference to `__cxa_pure_virtual'

These aren't in libc, so is there a really light libstdc++ that implements just these things?

My test code which I want to build this way currently looks like this:

#include <stdio.h>

template <class T>
class X
{
    public:
    T a;
};

class A1
{
    public:
        virtual void f() = 0;
        virtual ~A1() {}
};

class A2 : public A1
{
    public:
        virtual void f() {};
        virtual ~A2() {}
};

class Y
{
    public:
        ~Y() {}
};

int main()
{
    X<int> A;
    X<float> B;
    Y *C = new Y;

    A.a = 12;
    B.a = 2.3;

    printf("A: %d; B: %f\n", A.a, B.a);

    A2 *a2 = new A2;
    a2->f();

    return 0;
}
A: 

Here's a good explanation:

http://www.trilithium.com/johan/2005/06/static-libstdc/

The article explains in more detail but one key reason for doing this is the C++ specific libraries tend to be less stable than the base libc stuff. This may help reduce dependency issues.

seand
It's not the ABI stability I'm worried about, since in this case I compile the entire Linux distro (embedded firmware). I just need to clear up some space. If I can't, then c'est la vie :) I'll have to go the hard way and actually fix the code :D
Radu C
If you're very space-constrained going bare C may be a good choice. (you can readily 'fake' OOP).
seand
@seand: If I could just rewrite the application I want to do this for, I wouldn't be asking this question. I'm open to a very configurable libstdc++ where I can take out everything I don't need using a `make menuconfig` or similar.
Radu C
+4  A: 

Yes, things like operator new and operator delete are indeed defined in C++, not in C, so it would be absurd to have them in the runtime library for C as opposed to the one for C++ (same for the "pure virtual" used to clearly diagnose wrongful calls to pure virtual methods, and so on). If you link your whole executable without dynamic library access, the linker should (one hopes -- depending on how modularly the C++ runtime library is coded) pick and choose the bare minimum portion of the standard C++ library that you use in your code (and the fewer C++ specific features you use -- such as new implying delete for destructor calls, and so forth -- the greater your chances to avoid pulling in larger chunks of the library, of course;-).

Alex Martelli
I'm curious why you say it's wrongful what I did with the pure virtual there. I just wanted a pure virtual in order to trigger a linker error, but since you say it's wrongful, I wonder why, just in case I have a deeper understanding problem of pure virtuals. Thanks.
Radu C
It does make sense that those aren't in libc, but I'm looking for a libstdc++ that I tailor to my needs. I.e. take out everything but the minimum. uClibc++ winks at me.
Radu C
@Radu, nothing wrong with having a pure virtual (but there's no reason the error should be at _link_ time!), but it _will_ require C++-specific support (just like `new` will).
Alex Martelli
@Alex Martelli: Well, there's a symbol that the compiler puts in when a pure virtual is used, and that symbol needs to be linked to something, which is why the linker fails without libstdc++ (which contains said symbol). Nothing strange here.
Radu C
@Radu, I haven't spotted any pure virtual in your posted code, which is what makes it more than strange -- positively weird (have I just missed it?).
Alex Martelli
@Alex, Sorry about that :D I thought I posted the one with the pure virtual. I removed it just before I copied the code. It was `virtual void f() = 0` in `class A1`, so I'll make that edit now.
Radu C
A: 

Try linking against libsupc++.a. It is the bare C++ support library, without heavyweight iostreams functions or anything.

I'm not sure, but I believe using this instead of libstdc++.a would obtain a "freestanding" C++ implementation, as opposed to "hosted" or complete implementation, as defined in Clause 1 of the Standard.

Potatoswatter
Just tried linking against libsupc++.a and it didn't change anything.
Radu C
If you've looked at the code in libsupc++ (don't ask why), you'll see it's more to support libstdc++ than it is a subset of a C++ runtime. It's like a C++ runtime runtime if you will, and I don't think it is going to get you very far.
Logan Capaldo
@Radu: Really? Using GCC 4.2.1 `g++ -nostdlib -lsupc++ -lc -lcrt1.o barenew.cpp` compiles your code just fine. Leaving out `-lsupc++` I get several errors matching yours.
Potatoswatter
@Logan: Well, when I look at the code I see definitions for operator new and delete (new_op.cc), typeinfo's vtable (tinfo.cc), exception-support code, etc.
Potatoswatter
@Potatoswatter: GCC 4.4.3 here. I'll try GCC 4.2.1 or similar and see if that changes anything, as my GCC so far doesn't like -lcrt1.o at all, and replacing that with /usr/lib/crt1.o and re-adding -lsupc++ doesn't change anything.
Radu C
@Radu: Looks like I used -nostdlib and you used -nodefaultlibs which explains the difference with -crt1.o.
Potatoswatter
@Potatoswatter: Tried this too, ended up with more linker errors, like `undefined reference to '_Unwind_Resume'`. I still didn't try GCC 4.2.1 though.
Radu C
@Radu: That sounds really weird. Perhaps there's something going on with your library paths, where it simply isn't loading that library at all. Version mismatch or something.
Potatoswatter
A: 

Another approach could be to "statifie" your program. It means to embed all the libraries in an static executable and that way your code will always use the glibc that was in the machined you used to compile. The only thing you will need is a compatible kernel in the running machine. I know two programs to do that, one is open source:

and the other one is commercial software:

Of course this approach has drawbacks like for instance if you update a dynamic library that your application is using to fix a bug, because in the executable that library is embedded, you are going to have to compile you application again.

fco.javier.sanz
forget about it, If your are very space-constrained this is not going to fix your problem.
fco.javier.sanz