symbol visibility via defs or attributes?
I thought I'd split off a new issue from #2057 (closed) to have a longer term discussion of what is the right way to handle symbol visibility. The remainder of this description is going to assume you have read the following:
- #205 (closed)
- !1760 (merged)
- #1940 (closed)
So Graphviz (or really any C/C++ app+lib project) needs to manage visibility wrt linkage that is outside the C and C++ standards. To reiterate and stress that last part, there is currently no way to control this kind of symbol visibility with ISO standardized mechanisms.¹ Here is the ideal state for the end user, using the GCC visibility terms:
|compiling foo, an app that links against libfoo||
|compiling foo||a symbol from foo itself||hidden|
There are a number of ways to control symbol visibility:
- Command line options, e.g.
- GNU attributes,
- MSVC defs file
(1) is not useful for controlling symbol-by-symbol visibility. (2) is understood by GCC and Clang, but not MSVC. (3) is understood by GCC and MSVC, but not Clang.² (4) is hard to keep in sync with the source.
So essentially I think what we want to aim for is something like the following in a library’s API header:
#ifdef FOO_EXPORT #ifdef _WIN32 #define FOO_API __declspec(dllexport) #elif defined(__GNUC__) #define FOO_API __attibute__((visibility("default"))) #else #define FOO_API /* nothing; suboptimal build with everything visible */ #endif #else #ifdef _WIN32 #define FOO_API __declspec(dllimport) #elif defined(__GNUC__) #define FOO_API __attribute__((visibility("hidden"))) #else #define FOO_API /* nothing; suboptimal build with everything visible */ #endif #endif
FOO_EXPORT is only defined when compiling the library itself. There are some additional complications for C++,³ but for the most part I think this is it. Please comment if you think we should be moving towards something different.
CC @magjac, @compnerd_
static is the droid we are looking for.
² However, in practice the GCC interpretation of this is not so useful as e.g.
__declspec(dllimport) does not imply
extern as it does under MSVC.
³ As https://gcc.gnu.org/wiki/Visibility discusses, things that need RTTI typically need to be visible across SOs.