aklomp / base64

Fast Base64 stream encoder/decoder in C99, with SIMD acceleration
BSD 2-Clause "Simplified" License
866 stars 162 forks source link

Replace exports.txt with compiler visibility flags #54

Open aklomp opened 4 years ago

aklomp commented 4 years ago

When providing a library, it is good practice to only globally export symbols that the user is expected to link against. All other symbols should be hidden from view so that they do not pollute the global symbol namespace.

This is currently done by using the linker to roll all object files into a single object file, and instructing the linker to remove all symbols from that file except for those whitelisted in exports.txt.

This works nicely on GNU-based platforms, but is not really portable to OSes like Windows, the BSD's, and MacOS. It also will not be compatible with cmake when we change to that build system (#7), because cmake scripts are written at a level of abstraction where such platform dependent hacks should not exist. Also, weird linking problems such as #50 may arise. A better solution is needed.

These days it is common to declare symbol visibility at the source code level by using a compiler option to hide all symbols by default. Builtin functions are used to tag specific symbols as having global visibility. In GCC, this can be achieved by compiling with the -fvisibility=hidden flag, and whitelisting user-visible symbols with __attribute__((visibility("default"))).

This method is supported by GCC and Clang, and works along the same lines in MSVC with different builtins (__declspec(dllexport)). It will also be forward compatible with the way cmake handles symbol visibility.

Older compilers may not have such builtins, and our library may end up exporting all global symbols. While not great, the pain can be alleviated by ensuring that all symbols with global scope at least have the base64_ prefix. (This is currently true for all global symbols except codec_choose.)