g++ without libstdc++ - can it be done? - a very configurable lightweight libstdc++ where I can take stuff out easily would also do the trick
Asked Answered
D

5

14

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;
}
Danika answered 15/9, 2010 at 1:57 Comment(12)
If you can limit yourself to malloc/free, you might be able to cut out even those dependencies. That said, not sure what your goal here is in the first place.Yeoman
It's not clear to me why libc is ok but not libstdc++, if that is really the case, just write in C, you'll have fewer headaches than trying to use an arbitrary crippled subset of C++.Oratorian
libc is very stable and you often don't have to worry about dependencies; libstd++ less so. This can be an issue if you ship C++ apps on various machines. I don't think you can completely avoid linking the libstd++ though; it needs things like the startup logic for invoking global ctors and so on.Prudy
@aaa carp I'm actually trying to get rid of libstdc++ for space constraint reasonsDanika
@Drew Hall Unfortunately, malloc/free don't call constructors/destructors, so I can't limit myself to them.Danika
@Radu: No, but you can use malloc together with placement new/delete (maybe). My thoughts lie with Logan here--it'll probably be less frustrating to use C directly if you're going to cripple C++ to that extent. BTW, you might be able to try "gcc -std=c++98" to get C++ with no libstdc++ dependencies.Yeoman
@Drew Hall: I can probably fiddle with operator new, since it seems to complain about allocating integers, but operator delete may be a bit tricky, unless the void * it wants is just a malloc region. That would leave me with the vtables (the pure virtual test is just an afterthought, and I think I can just make the code worse and add empty inline bodies to those declarations)Danika
@Logan Capaldo: Wish it were that easy to rewrite what I have in C. Personally, that's exactly what I'd like to do, since I'm a C fan, not a C++ fan, but it would be quite difficult, and if it gets to that I'll get someone else to do it :)Danika
@seand: It's not the ABI stability I'm worried about, since this is for an embedded project for which I compile the entire Linux distro (OpenWRT) myself. I'm just stuck with some C++ code that outgrew the device.Danika
Well, C++ code won't run unless the features it makes use of is provided by the runtime. Either strip down your C++ code to something much more basic (and C-like), or include the C++ runtime. (perhaps you could statically link to the runtime? That allows the linker to remove all unused symbols)Humour
@jalf: I'm open to a lightweight very configurable by make menuconfig libstdc++ that people have used before (i.e. they know it works already, rather than taking a guess and pray).Danika
This article (wiki.osdev.org/C%2B%2B_Bare_Bones) has some information on using C++ without runtime support in a kernel environment, or more accurately getting you started on writing your own runtime support, and this article (wiki.osdev.org/C%2B%2B) has the rest. It's very low-level, but perhaps it'll be of use.Melina
R
10

Maybe this answer is a bit too late, but...

Writing c++ programs without libstdc++ is easy. I'm doing it for decades. Just avoid linking with libstdc++. That's easy: either use gcc for linking instead of g++, or provide a fake libstdc++ with only new, del and a few other functions.

Here's a example how you can replace the basic libstdc++ functionality with a transparent wrapper around malloc:

#include <stdlib.h>

// MSVC uses __cdecl calling convention for new/delete :-O
#ifdef _MSC_VER
#  define NEWDEL_CALL __cdecl
#else
#  define NEWDEL_CALL
#endif

extern "C" void __cxa_pure_virtual ()
{
    abort ();
}

void * NEWDEL_CALL operator new (size_t size)
{
    return malloc (size);
}

void * NEWDEL_CALL operator new [] (size_t size)
{
    return malloc (size);
}

void NEWDEL_CALL operator delete (void *p)
{
    if (p) free (p);
}

void NEWDEL_CALL operator delete [] (void *p)
{
    if (p) free (p);
}

void NEWDEL_CALL operator delete (void *p, size_t)
{
    if (p) free (p);
}

Now put that into a file named, say, libstd--.cpp, and build your own libstdc++.a:

gcc -c -O libstdc--.cpp
ar crs libstdc++.a libstdc--.o

Then you can try a simple test:

class A
{
    int *x;

public:
    A () { x = new int [10]; }
    ~A () { delete [] x; }
};

int main ()
{
    A a;
    return 0;
}

Compile and look what's got linked:

g++ -g test.cpp -o test -L.

# ldd ./test
    linux-vdso.so.1 (0x00007ffed0b8d000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f4d18df0000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4d18bd9000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4d18823000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4d1913b000)

Hey, look, ma, no libstdc++!

As an alternative, you may avoid using a fake libstdc++ by linking with gcc instead of g++ and by providing libstdc--.o on the linker command line so that your code may find the replacement news and deletes.

Robillard answered 3/11, 2018 at 13:17 Comment(0)
S
6

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;-).

Slacken answered 15/9, 2010 at 2:13 Comment(6)
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.Danika
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.Danika
@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).Slacken
@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.Danika
@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?).Slacken
@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.Danika
M
2

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.

Mckeever answered 15/9, 2010 at 2:36 Comment(8)
Just tried linking against libsupc++.a and it didn't change anything.Danika
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.Oratorian
@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.Mckeever
@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.Mckeever
@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.Danika
@Radu: Looks like I used -nostdlib and you used -nodefaultlibs which explains the difference with -crt1.o.Mckeever
@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.Danika
@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.Mckeever
P
1

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.

Prudy answered 15/9, 2010 at 2:10 Comment(3)
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 :DDanika
If you're very space-constrained going bare C may be a good choice. (you can readily 'fake' OOP).Prudy
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.Danika
C
0

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.

Contraceptive answered 16/9, 2010 at 11:59 Comment(1)
forget about it, If your are very space-constrained this is not going to fix your problem.Contraceptive

© 2022 - 2024 — McMap. All rights reserved.