I have a plugin-like architecture in a program where the video abstraction implementations are defined in shared libraries. I also have a common static library used by all of them:
- myProgram (executable) -> Links against libutil (static)
- libFoo (shared lib) -> Links against libutil (static)
- libBar (shared lib) -> Links against libutil (static)
myProgram
will load dynamically (at runtime) exactly one of libFoo or libBar.
Furthermore there is a Log
class in libutil which has in its public part an include to an interface class IWriter
, and in its implementation an include to a concrete class derived from IWriter
named StdStreamWriter
.
Both myProgram
and the shared libs use this Log
class. The shared libs are also compiler with -fvisibility=hidden
as is the current best practice (e.g. Boost did a considerable amount of work to make this work)
Now the problem: With ASAN I get an ODR error:
SUMMARY: AddressSanitizer: odr-violation: global 'vtable for StdStreamWriter' at /path/to/StdStreamWriter.cpp
I solved similar errors by decorating the class with BOOST_SYMBOL_VISIBLE
like: class BOOST_SYMBOL_VISIBLE StdStreamWriter : public IWriter
.
This makes the vtable of the class "exported" so the runtime can match the vtables on loading the shared library and NOT create another one which would cause the ODR violation reported.
However here it clearly does not work.
I assume the problem is, that the class header is never included in libFoo/libBar so when compiling the shared library -fvisibility=hidden
is also in effect for that class causing the vtable to not be exported.
However it does not make sense to include the class header anywhere in the shared libs, as the code doesn't use that class directly (only through the Log class where the usage is hidden in the implementation)
Is it anyhow possible to make the visibility setting of a class in a static library "transitive" so that that class is also "visible" in shared libraries linking that class/static lib?
Using Clang++8 on Linux Mint 19.2.