kspalaiologos / bzip3

A better and stronger spiritual successor to BZip2.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Properly hide private symbols and export public symbols if shared

SpaceIm opened this issue · comments

This logic is broken for MinGW static & doesn't support msvc shared:

bzip3/include/common.h

Lines 49 to 53 in 98f8e50

#ifdef __MINGW32__
#define PUBLIC_API __declspec(dllexport)
#else
#define PUBLIC_API
#endif

Could be improved:

  • hide all symbols
  • export public symbols if shared (not for static build): PUBLIC_API (too generic name by the way) set to __declspec(dllexport) if _WIN32, __attribute__((visibility("default"))) otherwise
  • these keywords must appear in declaration at build time, not in front of definition (specially for msvc).

It's pretty strange that libtool doesn't allow to define separate flags for building static and shared objects, which would make solving this issue with moderate portability way easier.

i have pushed a fix using libtool export-symbols-regex, which seems to work for non-LTO builds:

% nm -D .libs/libbzip3.so
0000000000004670 T bz3_decode_block
0000000000006210 T bz3_decode_blocks
00000000000014d0 T bz3_encode_block
0000000000005ef0 T bz3_encode_blocks
00000000000014a0 T bz3_free
0000000000001360 T bz3_last_error
00000000000013a0 T bz3_new
0000000000001370 T bz3_strerror
                 U calloc@GLIBC_2.2.5
                 w __cxa_finalize@GLIBC_2.2.5
                 U free@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U malloc@GLIBC_2.2.5
                 U memcpy@GLIBC_2.14
                 U memmove@GLIBC_2.2.5
                 U memset@GLIBC_2.2.5
                 U pthread_create@GLIBC_2.34
                 U pthread_exit@GLIBC_2.2.5
                 U pthread_join@GLIBC_2.34

I would have expected something more portable:

in libbz3.h:

#ifdef bzip3_EXPORTS
#ifdef _WIN32
    #define BZIP3_API __declspec(dllexport)
#else
    #define BZIP3_API __attribute__((visibility("default")))
#endif
#else
    #define BZIP3_API
#endif

and:

  • hide all symbols
  • define bzip3_EXPORTS (or whatever other definition name you prefer) at compilation time of the shared flavor.
  • add BZIP3_API in front of declarations of public functions.

I'm not an expert of autotools, we compile bzip3 with CMake in conan package manager because it's too tedious to use autotools with msvc.

cc: @alerque - I'm not sure how step2 should be performed with our current autotools setup.

the first step can be done by adding -fvisibility=hidden to the compiler flags.

I'm sorry I only have a few short brain waves to spare but I'll try to help. Which step 2 do you mean, the #ifdef _WIN32 bit? And you're looking for something that is defined when either compiling on or for the windows side of things? Or when doing a shared rather than static build?

define bzip3_EXPORTS (or whatever other definition name you prefer) at compilation time of the shared flavor

- wondering how to disambiguate shared and static builds.

Not a full answer, but research so far before I run off...

The last half or so of this manual page seems to be relevant. The issue I see (if I'm understanding this correctly) is that by default unless ./configured otherwise the autotools build will build both static and shared libraries. You can disable either one (see ./configure --help). The last code snippet on that page suggests how to add a define macro for use when something is enabled. I don't think that helps at all to understand which one is being built at a given moment unless the user has only one mode enabled.

To be continued...

Would it be possible to at least move definitions of PUBLIC_API to libbz3.h, rename it BZIP3_API and put this definition in front of each declaration please?

Something like this in libbz3.h:

#ifndef BZIP3_API
    #define BZIP3_API
#endif

Because I would like to avoid patching bzip3 in conan-center forever. At least with this workaround I can inject BZIP3_API definition with appropriate value at compile time if built as a shared library. It's an ugly workaround but at least we can live with this.

I guess you don't test msvc build, otherwise you would have seen this bug.