[Gdal-dev] Reducing number of exported symbols

Even Rouault even.rouault at mines-paris.org
Sun Sep 9 08:25:43 EDT 2007


Hello,

Pre-scriptum : it may be usefull to read http://gcc.gnu.org/wiki/Visibility to 
understand some points of this discussion.

Reducing the number of symbols has a lot of benefits as stated in the above 
link :
* speed up loading of shared objects
* better opportunities for code optimizations 
* reduce the size of SO.
* much lower chance of symbol collisions.

I've looked at the number of exported symbols by libgdal.so. It reaches the 
impressive number of 10 000 on my Linux system ! You can test on your own 
system with : nm -C -D libgdal.so | wc -l
Then, I've grabbed FWTools136.exe and looked at gdal_fw.so. It "only" exports 
3 549 symbols.
The reason is that on Windows, you have to explicitely declare that a symbol 
is visible from outside the library. This is done in GDAL with the CPL_DLL 
macro that expands to __declspec(dllexport) for MSC.
However with GCC, symbols are implicitely considered as public/exported unless 
otherwise specified. Since GCC 4.0, we have a way to change that behaviour 
through the -fvisibility=hidden flag. Thus we can define this flag and modify 
the CPL_DLL declaration in cpl_port.h like hereafter to explicitely export 
public symbols:

#ifndef CPL_DLL
#if defined(_MSC_VER) && !defined(CPL_DISABLE_DLL)
#  define CPL_DLL     __declspec(dllexport)
#else
#  if defined(__GNUC__) && __GNUC__ >= 4
#    define CPL_DLL     __attribute__ ((visibility("default")))
#  else
#    define CPL_DLL
#  endif
#endif
#endif

I give it a try on my system. This required only another change in shapefil.h 
that doesn't use CPL_DLL but SHPAPI_CALL that is equivalent.

#ifndef SHPAPI_CALL
#  if defined(__GNUC__) && __GNUC__ >= 4
#    define SHPAPI_CALL     __attribute__ ((visibility("default")))
#    define SHPAPI_CALL1(x) __attribute__ ((visibility("default")))     x
#  else
#    define SHPAPI_CALL
#  endif
#endif

Result : only 3 442 symbols ! Roughly like on Windows :-)

Another great benefit is that it should prevent subtle and annoying problems 
when linking an executable with a GDAL library build with internal 
libtiff/libpng/libjpeg/etc... and one of these libraries.Now most of them 
have disappeared form libgdal.so. This may be becoming necessary with new 
libtiff 4.0 that has become the internal GDAL libtiff, whereas most *nix 
systems/distributios still uses 3.8.2. People will probably want to use 
BigTIFF capabilities without messing up their system libtiff. Mixing symbols 
from both versions is definitely not a good idea as there has been ABI 
changes.
The case for internal libgeotiff is a bit different since it uses CPL_DLL too 
in its header. So, symbols for internal libgeotiff are still exported. We 
should fine a way to distinguish the case when it's built in GDAL tree from 
when it's build standalone.

So, to sum up, if we want to integrate this in GDAL, we have to :
* change cpl_port.h and shapefil.h
* add a test for the support of -fvisibility=hidden in configure

Any thoughts on all of this ?

(I also tried to use -fvisibility-inlines-hidden but it fails on my system 
since there's a bug in GCC 4.1 (apparently fixed in GCC 4.2). Anyway, it 
should not make a large difference since GDAL code is not using lot of inline 
functions.)

Best regards,
Even





More information about the Gdal-dev mailing list