Skip to content

MinGW GCC does not emit vtable for client applications #214

@ashtum

Description

@ashtum

Considering the following example:

widget.hpp:

#pragma once

#ifdef BUILDING_LIB
#define BOOST_WIDGET_DECL __declspec(dllexport)
#else
#define BOOST_WIDGET_DECL __declspec(dllimport)
#endif

class Widget
{
public:
    BOOST_WIDGET_DECL
    Widget();

    BOOST_WIDGET_DECL
    virtual void f();
};

widget.cpp:

#include "widget.hpp"

Widget::Widget()
{
}

void Widget::f()
{
}

main.cpp:

#include "widget.hpp"

int main()
{
    Widget w;
    Widget w2(w);
    w.f();
}

It builds and links correctly in MSVC using the following commands:

cl /LD widget.cpp /Fe:widget.dll /DBUILDING_LIB
cl main.cpp /link widget.lib

However, it fails in MinGW GCC:

g++ -shared widget.cpp -o widget.dll -DBUILDING_LIB
g++ main.cpp -L. -lwidget

with the following link error:

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible ./widget.lib when searching for -lwidget
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\cc2HbjyL.o:main.cpp:(.rdata$.refptr._ZTV6Widget[.refptr._ZTV6Widget]+0x0): undefined reference to `vtable for Widget'
collect2.exe: error: ld returned 1 exit status

Examining the MSVC build reveals that it emits the vtable inside the client application when a class has a defined virtual function but is not itself marked with __declspec(dllexport): https://godbolt.org/z/odc7arefz

However, this does not occur in MinGW GCC builds, which instead expect the vtable to be defined inside the DLL (similar to the Itanium ABI): https://godbolt.org/z/hWa9dfr3v

Interestingly, MinGW Clang behaves like MSVC and emits the missing vtable: https://godbolt.org/z/1xYdcEv5v. The application links and runs correctly in MinGW Clang even when using the DLL built with MinGW GCC.

Possible solutions:

  • Mark the entire class with BOOST_FOO_DECL so that RTTI and the vtable are always exported. However, this triggers the C4251 warning in MSVC when the class contains member variables, requiring those types to be marked with BOOST_FOO_DECL as well. This becomes problematic for large class hierarchies because it effectively forces every class to be decorated.

  • Introduce a new macro, BOOST_FOO_SYMBOL_VISIBLE, which unlike BOOST_SYMBOL_VISIBLE that expands to nothing on MinGW GCC this new macro should expand to the same value as BOOST_FOO_DECL when MinGW GCC is detected. This would ensure the vtable is visible in MinGW GCC without affecting other compilers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions