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:
Lines 49 to 53 in 98f8e50
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 ./configure
d 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.