clemens
clemens

Reputation: 422

Undefined symbols: for -fvisibility=hidden

I am having a linker problem that I can't fix (using MacOS and xcode).

First off, when I compile with -fvisibility=hidden all is fine. If I omit that flag, I get

"XYZ::IPlugView::iid", referenced from:
     __ZN9XYZ9IPlugView3iidE$non_lazy_ptr in pluginview.o
     (maybe you meant: __ZN9XYZ9IPlugView3iidE$non_lazy_ptr)

I don't know if this is related, but before that are a couple warnings like

ld: warning: non-virtual thunk to XYZ...::release()has different visibility (hidden) in xyz/foo.o and (default) in xyz/bar.o

Any Ideas would be greatly appreciated.... Thanks!

Upvotes: 0

Views: 2042

Answers (1)

Mecki
Mecki

Reputation: 132869

The warnings might in fact be related. What these warnings are trying to tell you is that there is a symbol named XYZ...::release() and this symbol is defined twice, once in the file xyz/foo.o (probably compiled from xyz/foo.cc) and one in the file xyz/bar.o (probably compiled from xyz/bar.cc), however, the symbol is not twice defined with the same visibility, one symbol is default (visible outside the current binary/library you are compiling) and one is hidden (only visible within the current binary/library you are compiling). The same symbol cannot have two different visibilities, of course.

By using -fvisibility=hidden you tell the compiler: Whenever there is no code annotation that would otherwise define the visibility of a symbol, make this symbol hidden. This probably solves your problem as the duplicate symbols that used to be once hidden and once default are now twice hidden, because the definition that used to be default was probably implicitly made default and now its implicitly made hidden, which means the symbol is twice hidden and this resolves the conflict, since the two symbols are probably treated like a single one by the linker.

Within your source code, there are two ways to set the visibility of a symbol, either by attribute or by pragma. To make a symbol hidden, you can either append __attribute__ ((visibility ("hidden"))) in front of its definition or you can place a pragma #pragma GCC visibility push(visibility) somewhere in your source file, causing all symbol definitions below it to be set hidden until you either use the pragma #pragma GCC visibility pop to return to the previous visibility state (or back to the default one if there wasn't a previous one), use another pragma to change the visibility to something else or to the end of the file, whatever comes first.

I think in your case the symbol in question is once defined in foo.cc with an explicit visibility (which is hidden) and once in bar.cc with no explicit visibility, so it's either default or hidden, depending on your -fvisibility flag.

Upvotes: 3

Related Questions