Skip to content

Commit 7c33804

Browse files
Merge #1696: build: Refactor visibility logic and add override
c82d84b build: add CMake option for disabling symbol visibility attributes (Cory Fields) ce79238 build: Add SECP256K1_NO_API_VISIBILITY_ATTRIBUTES (Tim Ruffing) e5297f6 build: Refactor visibility logic (Tim Ruffing) Pull request description: This is less invasive than #1695. The latter might be the right thing in a new library (and then we'd probably not support autotools in the first place), but any semantic change to this code has the potential to create news bug, or at least breakages for downstream users. This is different from #1677 in that it does not set `hidden` explicitly. I agree with the comment in #1677 that setting `hidden` violates the principle of least surprise. So this similar in spirit to #1674. So I wonder if this should also include 3eef736. I'd say no, `fvisibility` should then set by the user. But can you, in CMake, set `CMAKE_C_VISIBILITY_PRESET` from a parent project? ACKs for top commit: hebasto: ACK c82d84b, I have reviewed the code and it looks OK. Tree-SHA512: dad36c32a108d813e8d4e1849260af43f79a9aa8fbfb9a42b07d737e0467924a511110df0a2c6761539a1587b617a1b11123610a3db9d4cdf2b985dfb3eb21da
2 parents 73a6959 + c82d84b commit 7c33804

File tree

3 files changed

+57
-38
lines changed

3 files changed

+57
-38
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ endif()
4242

4343
option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
4444

45+
option(SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES "Enable visibility attributes in the API." ON)
46+
4547
## Modules
4648

4749
# We declare all options before processing them, to make sure we can express
@@ -312,6 +314,7 @@ else()
312314
set(cross_status "FALSE")
313315
endif()
314316
message("Cross compiling ....................... ${cross_status}")
317+
message("API visibility attributes ............. ${SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES}")
315318
message("Valgrind .............................. ${SECP256K1_VALGRIND}")
316319
get_directory_property(definitions COMPILE_DEFINITIONS)
317320
string(REPLACE ";" " " definitions "${definitions}")

include/secp256k1.h

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -121,45 +121,57 @@ typedef int (*secp256k1_nonce_function)(
121121
#endif
122122

123123
/* Symbol visibility. */
124-
#if defined(_WIN32)
125-
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
126-
* for MSVC compatibility. A __declspec declaration implies (but is not
127-
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
128-
* actually want __declspec even on GCC, see "Microsoft Windows Function
129-
* Attributes" in the GCC manual and the recommendations in
130-
* https://gcc.gnu.org/wiki/Visibility. */
131-
# if defined(SECP256K1_BUILD)
132-
# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
133-
/* Building libsecp256k1 as a DLL.
134-
* 1. If using Libtool, it defines DLL_EXPORT automatically.
135-
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
136-
# define SECP256K1_API extern __declspec (dllexport)
137-
# else
138-
/* Building libsecp256k1 as a static library on Windows.
139-
* No declspec is needed, and so we would want the non-Windows-specific
140-
* logic below take care of this case. However, this may result in setting
141-
* __attribute__ ((visibility("default"))), which is supposed to be a noop
142-
* on Windows but may trigger warnings when compiling with -flto due to a
143-
* bug in GCC, see
144-
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */
145-
# define SECP256K1_API extern
146-
# endif
147-
/* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
148-
* library on Windows. */
149-
# elif !defined(SECP256K1_STATIC)
150-
/* Consuming libsecp256k1 as a DLL. */
151-
# define SECP256K1_API extern __declspec (dllimport)
152-
# endif
124+
#if !defined(SECP256K1_API) && defined(SECP256K1_NO_API_VISIBILITY_ATTRIBUTES)
125+
/* The user has requested that we don't specify visibility attributes in
126+
* the public API.
127+
*
128+
* Since all our non-API declarations use the static qualifier, this means
129+
* that the user can use -fvisibility=<value> to set the visibility of the
130+
* API symbols. For instance, -fvisibility=hidden can be useful *even for
131+
* the API symbols*, e.g., when building a static library which is linked
132+
* into a shared library, and the latter should not re-export the
133+
* libsecp256k1 API.
134+
*
135+
* While visibility is a concept that applies only to shared libraries,
136+
* setting visibility will still make a difference when building a static
137+
* library: the visibility settings will be stored in the static library,
138+
* solely for the potential case that the static library will be linked into
139+
* a shared library. In that case, the stored visibility settings will
140+
* resurface and be honored for the shared library. */
141+
# define SECP256K1_API extern
153142
#endif
154-
#ifndef SECP256K1_API
155-
/* All cases not captured by the Windows-specific logic. */
156-
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
157-
/* Building libsecp256k1 using GCC or compatible. */
158-
# define SECP256K1_API extern __attribute__ ((visibility ("default")))
159-
# else
160-
/* Fall back to standard C's extern. */
161-
# define SECP256K1_API extern
162-
# endif
143+
#if !defined(SECP256K1_API)
144+
# if defined(SECP256K1_BUILD)
145+
/* On Windows, assume a shared library only if explicitly requested.
146+
* 1. If using Libtool, it defines DLL_EXPORT automatically.
147+
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
148+
# if defined(_WIN32) && (defined(SECP256K1_DLL_EXPORT) || defined(DLL_EXPORT))
149+
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax for
150+
* MSVC compatibility. A __declspec declaration implies (but is not
151+
* exactly equivalent to) __attribute__ ((visibility("default"))),
152+
* and so we actually want __declspec even on GCC, see "Microsoft
153+
* Windows Function Attributes" in the GCC manual and the
154+
* recommendations in https://gcc.gnu.org/wiki/Visibility . */
155+
# define SECP256K1_API extern __declspec(dllexport)
156+
/* Avoid __attribute__ ((visibility("default"))) on Windows to get rid
157+
* of warnings when compiling with -flto due to a bug in GCC, see
158+
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */
159+
# elif !defined(_WIN32) && defined (__GNUC__) && (__GNUC__ >= 4)
160+
# define SECP256K1_API extern __attribute__ ((visibility("default")))
161+
# else
162+
# define SECP256K1_API extern
163+
# endif
164+
# else
165+
/* On Windows, SECP256K1_STATIC must be defined when consuming
166+
* libsecp256k1 as a static library. Note that SECP256K1_STATIC is a
167+
* "consumer-only" macro, and it has no meaning when building
168+
* libsecp256k1. */
169+
# if defined(_WIN32) && !defined(SECP256K1_STATIC)
170+
# define SECP256K1_API extern __declspec(dllimport)
171+
# else
172+
# define SECP256K1_API extern
173+
# endif
174+
# endif
163175
#endif
164176

165177
/* Warning attributes

src/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL
5454
# from being exported.
5555
target_sources(secp256k1 PRIVATE secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
5656

57+
if(NOT SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES)
58+
target_compile_definitions(secp256k1 PRIVATE SECP256K1_NO_API_VISIBILITY_ATTRIBUTES)
59+
endif()
60+
5761
# Create a helper lib that parent projects can use to link secp256k1 into a
5862
# static lib.
5963
add_library(secp256k1_objs INTERFACE)

0 commit comments

Comments
 (0)