Skip to content

Commit 9e6d1b0

Browse files
Merge #1367: build: Improvements to symbol visibility logic on Windows (attempt 3)
c6cd2b1 ci: Add task for static library on Windows + CMake (Hennadii Stepanov) 020bf69 build: Add extensive docs on visibility issues (Tim Ruffing) 0196e8a build: Introduce `SECP256k1_DLL_EXPORT` macro (Hennadii Stepanov) 9f1b190 refactor: Replace `SECP256K1_API_VAR` with `SECP256K1_API` (Hennadii Stepanov) ae9db95 build: Introduce `SECP256K1_STATIC` macro for Windows users (Hennadii Stepanov) Pull request description: Previous attempts: - #1346 - #1362 The result is as follows: 1. Simple, concise and extensively documented code. 2. Explicitly documented use cases with no ambiguities. 3. No workarounds for linker warnings. 4. Solves one item in #1235. ACKs for top commit: real-or-random: utACK c6cd2b1 Tree-SHA512: d58694452d630aefbd047916033249891bc726b7475433aaaa7c3ea2a07ded8f185a598385b67c2ee3440ec5904ff9d9452c97b0961d84dcb2eb2cf46caa171e
2 parents 0aacf64 + c6cd2b1 commit 9e6d1b0

10 files changed

+46
-41
lines changed

.cirrus.yml

+6-1
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,17 @@ task:
384384
# Ignore MSBuild warning MSB8029.
385385
# See: https://learn.microsoft.com/en-us/visualstudio/msbuild/errors/msb8029?view=vs-2022
386386
IgnoreWarnIntDirInTempDetected: 'true'
387+
matrix:
388+
- env:
389+
BUILD_SHARED_LIBS: ON
390+
- env:
391+
BUILD_SHARED_LIBS: OFF
387392
git_show_script:
388393
# Print commit to allow reproducing the job outside of CI.
389394
- git show --no-patch
390395
configure_script:
391396
- '%x64_NATIVE_TOOLS%'
392-
- cmake -E env CFLAGS="/WX" cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
397+
- cmake -E env CFLAGS="/WX" cmake -A x64 -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
393398
build_script:
394399
- '%x64_NATIVE_TOOLS%'
395400
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Document `doc/ellswift.md` which explains the mathematical background of the scheme.
1515
- The [paper](https://eprint.iacr.org/2022/759) on which the scheme is based.
1616

17+
#### Changed
18+
- When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`.
19+
1720
## [0.3.2] - 2023-05-13
1821
We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`.
1922

Makefile.am

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ endif
153153
if USE_EXAMPLES
154154
noinst_PROGRAMS += ecdsa_example
155155
ecdsa_example_SOURCES = examples/ecdsa.c
156-
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include
156+
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
157157
ecdsa_example_LDADD = libsecp256k1.la
158158
ecdsa_example_LDFLAGS = -static
159159
if BUILD_WINDOWS
@@ -163,7 +163,7 @@ TESTS += ecdsa_example
163163
if ENABLE_MODULE_ECDH
164164
noinst_PROGRAMS += ecdh_example
165165
ecdh_example_SOURCES = examples/ecdh.c
166-
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include
166+
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
167167
ecdh_example_LDADD = libsecp256k1.la
168168
ecdh_example_LDFLAGS = -static
169169
if BUILD_WINDOWS
@@ -174,7 +174,7 @@ endif
174174
if ENABLE_MODULE_SCHNORRSIG
175175
noinst_PROGRAMS += schnorr_example
176176
schnorr_example_SOURCES = examples/schnorr.c
177-
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include
177+
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
178178
schnorr_example_LDADD = libsecp256k1.la
179179
schnorr_example_LDFLAGS = -static
180180
if BUILD_WINDOWS

configure.ac

-6
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
127127
SECP_TRY_APPEND_CFLAGS([-wd4267], $1) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data".
128128
# Eliminate deprecation warnings for the older, less secure functions.
129129
CPPFLAGS="-D_CRT_SECURE_NO_WARNINGS $CPPFLAGS"
130-
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
131-
# importing variables from a statically linked secp256k1.
132-
# (See the libtool manual, section "Windows DLLs" for background.)
133-
# Unfortunately, libtool tries to be too clever and strips "-Xlinker arg"
134-
# into "arg", so this will be " -Xlinker -ignore:4217" after stripping.
135-
LDFLAGS="-Xlinker -Xlinker -Xlinker -ignore:4217 $LDFLAGS"
136130
fi
137131
])
138132
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)

examples/CMakeLists.txt

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ target_link_libraries(example INTERFACE
66
secp256k1
77
$<$<PLATFORM_ID:Windows>:bcrypt>
88
)
9-
if(NOT BUILD_SHARED_LIBS AND MSVC)
10-
target_link_options(example INTERFACE /IGNORE:4217)
11-
endif()
129

1310
add_executable(ecdsa_example ecdsa.c)
1411
target_link_libraries(ecdsa_example example)

include/secp256k1.h

+26-20
Original file line numberDiff line numberDiff line change
@@ -133,29 +133,35 @@ 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)
139-
# ifdef SECP256K1_BUILD
140-
# ifdef DLL_EXPORT
141-
# define SECP256K1_API __declspec (dllexport)
142-
# define SECP256K1_API_VAR extern __declspec (dllexport)
138+
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
139+
* for MSVC compatibility. A __declspec declaration implies (but is not
140+
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
141+
* actually want __declspec even on GCC, see "Microsoft Windows Function
142+
* Attributes" in the GCC manual and the recommendations in
143+
* https://gcc.gnu.org/wiki/Visibility. */
144+
# if defined(SECP256K1_BUILD)
145+
# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
146+
/* Building libsecp256k1 as a DLL.
147+
* 1. If using Libtool, it defines DLL_EXPORT automatically.
148+
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
149+
# define SECP256K1_API extern __declspec (dllexport)
143150
# endif
144-
# elif defined _MSC_VER
145-
# define SECP256K1_API
146-
# define SECP256K1_API_VAR extern __declspec (dllimport)
147-
# elif defined DLL_EXPORT
148-
# define SECP256K1_API __declspec (dllimport)
149-
# define SECP256K1_API_VAR extern __declspec (dllimport)
151+
/* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
152+
* library on Windows. */
153+
# elif !defined(SECP256K1_STATIC)
154+
/* Consuming libsecp256k1 as a DLL. */
155+
# define SECP256K1_API extern __declspec (dllimport)
150156
# endif
151157
#endif
152158
#ifndef SECP256K1_API
153159
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
154-
# define SECP256K1_API __attribute__ ((visibility ("default")))
155-
# define SECP256K1_API_VAR extern __attribute__ ((visibility ("default")))
160+
/* Building libsecp256k1 on non-Windows using GCC or compatible. */
161+
# define SECP256K1_API extern __attribute__ ((visibility ("default")))
156162
# else
157-
# define SECP256K1_API
158-
# define SECP256K1_API_VAR extern
163+
/* All cases not captured above. */
164+
# define SECP256K1_API extern
159165
# endif
160166
#endif
161167

@@ -227,10 +233,10 @@ typedef int (*secp256k1_nonce_function)(
227233
*
228234
* It is highly recommended to call secp256k1_selftest before using this context.
229235
*/
230-
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_static;
236+
SECP256K1_API const secp256k1_context *secp256k1_context_static;
231237

232238
/** Deprecated alias for secp256k1_context_static. */
233-
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_no_precomp
239+
SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp
234240
SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
235241

236242
/** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
@@ -627,10 +633,10 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
627633
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
628634
* extra entropy.
629635
*/
630-
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
636+
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
631637

632638
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
633-
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_default;
639+
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default;
634640

635641
/** Create an ECDSA signature.
636642
*

include/secp256k1_ecdh.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ typedef int (*secp256k1_ecdh_hash_function)(
2727

2828
/** An implementation of SHA256 hash function that applies to compressed public key.
2929
* Populates the output parameter with 32 bytes. */
30-
SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
30+
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
3131

3232
/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256).
3333
* Populates the output parameter with 32 bytes. */
34-
SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
34+
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
3535

3636
/** Compute an EC Diffie-Hellman secret in constant time
3737
*

include/secp256k1_ellswift.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ typedef int (*secp256k1_ellswift_xdh_hash_function)(
7272
/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses
7373
* SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte
7474
* array pointed to by data. */
75-
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
75+
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
7676

7777
/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with
7878
* BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the
7979
* BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent
8080
* to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to
8181
* SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh").
8282
* The data argument is ignored. */
83-
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
83+
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
8484

8585
/** Construct a 64-byte ElligatorSwift encoding of a given pubkey.
8686
*

include/secp256k1_schnorrsig.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ typedef int (*secp256k1_nonce_function_hardened)(
6161
* Therefore, to create BIP-340 compliant signatures, algo must be set to
6262
* "BIP0340/nonce" and algolen to 13.
6363
*/
64-
SECP256K1_API_VAR const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
64+
SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
6565

6666
/** Data structure that contains additional arguments for schnorrsig_sign_custom.
6767
*

src/CMakeLists.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ if(SECP256K1_ASM STREQUAL "arm32")
2020
target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
2121
endif()
2222

23-
# Define our export symbol only for Win32 and only for shared libs.
24-
# This matches libtool's usage of DLL_EXPORT
2523
if(WIN32)
26-
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
24+
# Define our export symbol only for shared libs.
25+
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT)
26+
target_compile_definitions(secp256k1 INTERFACE $<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:SECP256K1_STATIC>)
2727
endif()
2828

2929
# Object libs don't know if they're being built for a shared or static lib.

0 commit comments

Comments
 (0)