On 2014-03-27 17:04, Trevor Saunders wrote:
On Thu, Mar 27, 2014 at 02:12:54PM +0400, izbyshev wrote:
Well, actually the documentation at
http://gcc.gnu.org/wiki/Visibility
states:
#pragma GCC visibility is stronger than -fvisibility; it affects
extern
declarations as well. -fvisibility only affects definitions, so that
existing code can be recompiled with minimal changes.
that seems kind of crazy and unfortunate.
Well, the last sentence hints that the reason is to allow people to
easily use shared libraries that don't use visibility attribute (yet).
If -fvisibility=hidden acted like #pragma, all symbols declared in
public headers of such libraries would become hidden, and the binary of
any project that includes such headers could not be linked. In firefox,
this behavior is emulated by including #pragma before every translation
unit and then solving the described problem via system wrappers. So,
even if -fvisibility and #pragma were equivalent (and had the "strong"
meaning), we would still have had to use system wrappers!
All in all, it seems that system wrappers are superior (but not
dramatically) unless all internal data used across units is
explicitly
marked with 'hidden' attribute and issues like with libopus are
resolved (by
either changing such libs so they don't export symbols when they are
built
statically or explicitly marking function declarations as hidden at
use
sites).
or we get gcc / clang to make -fvisibility=hidden do what we want /
add
some new option that does.
Even if we put aside issues with .rela.plt (I agree they are kind of
library problem in the case of opus, and I should probably investigate
other cases further), we still have a data declarations problem, and IMO
we can't make the compiler do what we want since we want too much.
Suppose we have a translation unit that includes a bunch of headers
containing only declarations. To get the least possible number of data
relocations, we'd like to have the following visibility:
1. The public headers from our project with symbols that we want to
export: default.
2. The internal headers from our project: hidden.
3. The public headers from libraries that we will be statically
linked to: hidden.
4. The public headers from libraries that we will be dynamically
linked to: default.
If we are a good project, we should have explicitly specified default
visibility for all declarations from 1, so they are not a problem. But
the compiler has no way to distinguish (2, 3) and 4 without some help.
So the compiler has to use the same policy for all of them, and the
extremes are:
* Hide all declarations (#pragma). In this case we have to explicitly
exclude 4 (hello, system wrappers).
* Hide nothing (-fvisibility=hidden - doesn't affect declarations).
Here we get the overhead from 2 and 3.
I can't think of any 'mixed' policy that the compiler could use. One
alternative would be to use the 'hide nothing' policy and wrap headers
from 2 and 3 with 'push(hidden)' and 'pop' pragmas. I'm not sure that
this is better than system wrappers, but it is probably easier to track
headers from firefox tree than external ones. I should see how the
system wrappers generator is implemented to check this out.
--
Alexey Izbyshev
_______________________________________________
dev-builds mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-builds