ebiggers / libdeflate

Heavily optimized library for DEFLATE/zlib/gzip compression and decompression
MIT License
992 stars 165 forks source link

Static builds and exported symbols #376

Open pictview opened 2 months ago

pictview commented 2 months ago

I think there is no need to export all symbols when building a static lib with clang. Hence I suggest to change the following

elif defined(_GNUC_)

#  define LIBDEFLATE_EXPORT_SYM _attribute_((visibility("default")))

else

#  define LIBDEFLATE_EXPORT_SYM

endif

to something like

elif defined(_GNUC_) || defined(_clang_)

#  if defined(LIBDEFLATE_DLL) #    define LIBDEFLATE_EXPORT_SYM _attribute_((visibility("default"))) #  else #    define LIBDEFLATE_EXPORT_SYM _attribute_((visibility("hidden"))) #  endif #else #  define LIBDEFLATE_EXPORT_SYM #endif

maybe then LIBDEFLATE_DLL should be renamed to something like LIBDEFLATE_SHARED.

ebiggers commented 2 months ago

So you'd like __attribute__((visibility("hidden"))) to be used when building a static library. Why? I didn't think it made a difference for static libraries.

pictview commented 2 months ago

It makes two differences: 1) hidden symbols make the binary somewhat smaller 2) more importantly, there can be clashes on some systems when multiple binaries export symbols of the same name. This can lead to crashes if the two symbols come from different library versions and expect different arguments. For example, on Windows, each module .EXE/.DLL strictly defines the name of the .DLL from which the imported symbol should come. If the symbols actually resides in the same .EXE/.DLL, then it is not imported, but the symbol in the same .EXE/.DLL is called.. However, it is very different for example on macOS. If two dylibs export a symbol of the same name, it is undefined which is used at runtime. Even when module A.dylib exports a symbol S and wants to use it, it may actually happen that the OS decides to pair the import of S from A.dylib with the export of the symbol S from B.dylib, i.e. A.dylib will actually call the implementation of S in B.dylib. Under which circumstances can a single process contain 2 dylibs exporting the same symbol but from different versions of the same static library? Think of plugins for e.g. Adobe products coming from different vendors.