Skip to content

Commit ac5bbc8

Browse files
build: Add extensive docs on visibility issues
1 parent 297c85a commit ac5bbc8

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

include/secp256k1.h

+27-6
Original file line numberDiff line numberDiff line change
@@ -133,36 +133,57 @@ typedef int (*secp256k1_nonce_function)(
133133
# define SECP256K1_NO_BUILD
134134
#endif
135135

136-
/* Symbol visibility. See https://gcc.gnu.org/wiki/Visibility */
137-
/* DLL_EXPORT is defined internally for shared builds */
136+
/* Symbol visibility. */
138137
#if defined(_WIN32) || defined(__CYGWIN__)
139138
# if defined(SECP256K1_STATICLIB) && defined(SECP256K1_DLL)
140139
# error "At most one of SECP256K1_STATICLIB and SECP256K1_DLL must be defined."
141140
# endif
142-
# ifdef SECP256K1_BUILD
143-
# ifdef DLL_EXPORT
141+
/* GCC for Windows (e.g., MinGW) and for Cygwin accept the __declspec syntax
142+
* for MSVC compatibility. A __declspec declaration implies (but is not
143+
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
144+
* actually want __declspec even on GCC, see "Microsoft Windows Function
145+
* Attributes" in the GCC manual and the recommendations in
146+
* https://gcc.gnu.org/wiki/Visibility. */
147+
# if defined(SECP256K1_BUILD)
148+
# if defined(DLL_EXPORT)
149+
/* Building libsecp256k1 as a DLL. (DLL_EXPORT is a libtool convention.) */
144150
# define SECP256K1_API __declspec (dllexport)
145151
# define SECP256K1_API_VAR extern __declspec (dllexport)
146152
# endif
147153
# elif defined(SECP256K1_STATICLIB)
154+
/* Linking against static libsecp256k1 requested explicitly. */
148155
# define SECP256K1_API
149156
# define SECP256K1_API_VAR extern
150157
# elif defined(SECP256K1_DLL)
158+
/* Linking against a libsecp256k1 DLL requested explicitly. */
151159
# define SECP256K1_API __declspec (dllimport)
152160
# define SECP256K1_API_VAR extern __declspec (dllimport)
153-
# elif defined _MSC_VER
161+
# elif defined(_MSC_VER)
162+
/* No method requested explicitly. The following works on MSVC for both
163+
* static and dynamic linking, as long as if at least one function is
164+
* imported (i.e., not only variables are imported), which should be the case
165+
* for any meaningful program that uses the libsecp256k1 API. The drawback of
166+
* the following is that it may provoke linker warnings LNK4217 and LNK4286.
167+
* See "Windows DLLs" in the libtool manual. */
154168
# define SECP256K1_API
155169
# define SECP256K1_API_VAR extern __declspec (dllimport)
156-
# elif defined DLL_EXPORT
170+
# elif defined(DLL_EXPORT)
171+
/* No method requested explicitly and we're not on MSVC. We make an educated
172+
* guess based on libtool's DLL_EXPORT convention: If the importing program
173+
* is itself a DLL, then it is likely that it also wants to consume
174+
* libsecp256k1 as a DLL. See "Windows DLLs" in the libtool manual. */
157175
# define SECP256K1_API __declspec (dllimport)
158176
# define SECP256K1_API_VAR extern __declspec (dllimport)
159177
# endif
160178
#endif
161179
#ifndef SECP256K1_API
162180
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
181+
/* Building libsecp256k1 on non-Windows using GCC or compatible. */
163182
# define SECP256K1_API __attribute__ ((visibility ("default")))
164183
# define SECP256K1_API_VAR extern __attribute__ ((visibility ("default")))
165184
# else
185+
/* All other cases, e.g., linking against static libsecp256k1,
186+
or building libsecp256k1 using an unknown compiler. */
166187
# define SECP256K1_API
167188
# define SECP256K1_API_VAR extern
168189
# endif

0 commit comments

Comments
 (0)