CMakeLists.txt raw
1 cmake_minimum_required(VERSION 3.22)
2
3 #=============================
4 # Project / Package metadata
5 #=============================
6 project(libsecp256k1
7 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
8 # the API. All changes in experimental modules are treated as
9 # backwards-compatible and therefore at most increase the minor version.
10 VERSION 0.7.2
11 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
12 HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
13 LANGUAGES C
14 )
15 enable_testing()
16 include(CTestUseLaunchers) # Allow users to set CTEST_USE_LAUNCHERS in custom `ctest -S` scripts.
17 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
18
19 # The library version is based on libtool versioning of the ABI. The set of
20 # rules for updating the version can be found here:
21 # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
22 # All changes in experimental modules are treated as if they don't affect the
23 # interface and therefore only increase the revision.
24 set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6)
25 set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
26 set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
27
28 #=============================
29 # Language setup
30 #=============================
31 set(CMAKE_C_STANDARD 90)
32 set(CMAKE_C_EXTENSIONS OFF)
33
34 #=============================
35 # Configurable options
36 #=============================
37 if(libsecp256k1_IS_TOP_LEVEL)
38 option(BUILD_SHARED_LIBS "Build shared libraries." ON)
39 endif()
40
41 option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
42
43 option(SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES "Enable visibility attributes in the API." ON)
44
45 ## Modules
46
47 # We declare all options before processing them, to make sure we can express
48 # dependencies while processing.
49 option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON)
50 option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF)
51 option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON)
52 option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON)
53 option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON)
54 option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON)
55
56 option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
57 if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
58 add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1)
59 endif()
60
61 set(SECP256K1_ECMULT_WINDOW_SIZE 15 CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. The default value is a reasonable setting for desktop machines (currently 15). [default=15]")
62 set_property(CACHE SECP256K1_ECMULT_WINDOW_SIZE PROPERTY STRINGS 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
63 include(CheckStringOptionValue)
64 check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE)
65 add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE})
66
67 set(SECP256K1_ECMULT_GEN_KB 86 CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. The default value is a reasonable setting for desktop machines (currently 86). [default=86]")
68 set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS 2 22 86)
69 check_string_option_value(SECP256K1_ECMULT_GEN_KB)
70 if(SECP256K1_ECMULT_GEN_KB EQUAL 2)
71 add_compile_definitions(COMB_BLOCKS=2)
72 add_compile_definitions(COMB_TEETH=5)
73 elseif(SECP256K1_ECMULT_GEN_KB EQUAL 22)
74 add_compile_definitions(COMB_BLOCKS=11)
75 add_compile_definitions(COMB_TEETH=6)
76 elseif(SECP256K1_ECMULT_GEN_KB EQUAL 86)
77 add_compile_definitions(COMB_BLOCKS=43)
78 add_compile_definitions(COMB_TEETH=6)
79 endif()
80
81 set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]")
82 set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64")
83 check_string_option_value(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
84 if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
85 string(TOUPPER "${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}" widemul_upper_value)
86 add_compile_definitions(USE_FORCE_WIDEMUL_${widemul_upper_value}=1)
87 endif()
88 mark_as_advanced(FORCE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
89
90 set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm32\" (experimental). [default=AUTO]")
91 set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm32")
92 check_string_option_value(SECP256K1_ASM)
93 if(SECP256K1_ASM STREQUAL "arm32")
94 enable_language(ASM)
95 include(CheckArm32Assembly)
96 check_arm32_assembly()
97 if(HAVE_ARM32_ASM)
98 add_compile_definitions(USE_EXTERNAL_ASM=1)
99 else()
100 message(FATAL_ERROR "ARM32 assembly requested but not available.")
101 endif()
102 elseif(SECP256K1_ASM)
103 include(CheckX86_64Assembly)
104 check_x86_64_assembly()
105 if(HAVE_X86_64_ASM)
106 set(SECP256K1_ASM "x86_64")
107 add_compile_definitions(USE_ASM_X86_64=1)
108 elseif(SECP256K1_ASM STREQUAL "AUTO")
109 set(SECP256K1_ASM "OFF")
110 else()
111 message(FATAL_ERROR "x86_64 assembly requested but not available.")
112 endif()
113 endif()
114
115 option(SECP256K1_EXPERIMENTAL "Allow experimental configuration options." OFF)
116 if(NOT SECP256K1_EXPERIMENTAL)
117 if(SECP256K1_ASM STREQUAL "arm32")
118 message(FATAL_ERROR "ARM32 assembly is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
119 endif()
120 endif()
121
122 set(SECP256K1_VALGRIND "AUTO" CACHE STRING "Build with extra checks for running inside Valgrind. [default=AUTO]")
123 set_property(CACHE SECP256K1_VALGRIND PROPERTY STRINGS "AUTO" "OFF" "ON")
124 check_string_option_value(SECP256K1_VALGRIND)
125 if(SECP256K1_VALGRIND)
126 find_package(Valgrind MODULE)
127 if(Valgrind_FOUND)
128 set(SECP256K1_VALGRIND ON)
129 include_directories(${Valgrind_INCLUDE_DIR})
130 add_compile_definitions(VALGRIND)
131 elseif(SECP256K1_VALGRIND STREQUAL "AUTO")
132 set(SECP256K1_VALGRIND OFF)
133 else()
134 message(FATAL_ERROR "Valgrind support requested but valgrind/memcheck.h header not available.")
135 endif()
136 endif()
137
138 option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." ON)
139 option(SECP256K1_BUILD_TESTS "Build tests." ON)
140 option(SECP256K1_BUILD_EXHAUSTIVE_TESTS "Build exhaustive tests." ON)
141 option(SECP256K1_BUILD_CTIME_TESTS "Build constant-time tests." ${SECP256K1_VALGRIND})
142 option(SECP256K1_BUILD_EXAMPLES "Build examples." OFF)
143
144 # Redefine configuration flags.
145 # We leave assertions on, because they are only used in the examples, and we want them always on there.
146 if(MSVC)
147 string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
148 string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
149 string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
150 # Match GCC/Clang's size-optimization macro for the inline guard
151 add_compile_definitions($<$<CONFIG:MinSizeRel>:__OPTIMIZE_SIZE__=1>)
152 else()
153 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
154 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
155 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
156 # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
157 string(REGEX REPLACE "-O3( |$)" "-O2\\1" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
158 endif()
159
160 # Define custom "Coverage" build type.
161 set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O0 -DCOVERAGE=1 --coverage" CACHE STRING
162 "Flags used by the C compiler during \"Coverage\" builds."
163 FORCE
164 )
165 set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING
166 "Flags used for linking binaries during \"Coverage\" builds."
167 FORCE
168 )
169 set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING
170 "Flags used by the shared libraries linker during \"Coverage\" builds."
171 FORCE
172 )
173 mark_as_advanced(
174 CMAKE_C_FLAGS_COVERAGE
175 CMAKE_EXE_LINKER_FLAGS_COVERAGE
176 CMAKE_SHARED_LINKER_FLAGS_COVERAGE
177 )
178
179 if(PROJECT_IS_TOP_LEVEL)
180 get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
181 set(default_build_type "RelWithDebInfo")
182 if(is_multi_config)
183 set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING
184 "Supported configuration types."
185 FORCE
186 )
187 else()
188 set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
189 STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage"
190 )
191 if(NOT CMAKE_BUILD_TYPE)
192 message(STATUS "Setting build type to \"${default_build_type}\" as none was specified")
193 set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING
194 "Choose the type of build."
195 FORCE
196 )
197 endif()
198 endif()
199 endif()
200
201 include(TryAppendCFlags)
202 if(MSVC)
203 # For both cl and clang-cl compilers.
204 try_append_c_flags(/W3) # Production quality warning level.
205 # Eliminate deprecation warnings for the older, less secure functions.
206 add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
207 else()
208 try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers.
209 endif()
210 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
211 # Keep the following commands ordered lexicographically.
212 try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned".
213 try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data".
214 try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data".
215 else()
216 # Keep the following commands ordered lexicographically.
217 try_append_c_flags(-pedantic)
218 try_append_c_flags(-Wcast-align) # GCC >= 2.95.
219 try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0.
220 try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only.
221 try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
222 try_append_c_flags(-Wleading-whitespace=spaces) # GCC >= 15.0
223 try_append_c_flags(-Wnested-externs)
224 try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
225 try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
226 try_append_c_flags(-Wno-unused-function) # GCC >= 3.0, -Wunused-function is implied by -Wall.
227 try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only.
228 try_append_c_flags(-Wshadow)
229 try_append_c_flags(-Wstrict-prototypes)
230 try_append_c_flags(-Wtrailing-whitespace=any) # GCC >= 15.0
231 try_append_c_flags(-Wundef)
232 endif()
233
234 set(print_msan_notice)
235 if(SECP256K1_BUILD_CTIME_TESTS)
236 include(CheckMemorySanitizer)
237 check_memory_sanitizer(msan_enabled)
238 if(msan_enabled)
239 try_append_c_flags(-fno-sanitize-memory-param-retval)
240 set(print_msan_notice YES)
241 endif()
242 unset(msan_enabled)
243 endif()
244
245 set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
246 if(SECP256K1_APPEND_CFLAGS)
247 # Appending to this low-level rule variable is the only way to
248 # guarantee that the flags appear at the end of the command line.
249 string(APPEND CMAKE_C_COMPILE_OBJECT " ${SECP256K1_APPEND_CFLAGS}")
250 endif()
251
252 set(SECP256K1_APPEND_LDFLAGS "" CACHE STRING "Linker flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
253 if(SECP256K1_APPEND_LDFLAGS)
254 # Appending to this low-level rule variable is the only way to
255 # guarantee that the flags appear at the end of the command line.
256 string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " ${SECP256K1_APPEND_LDFLAGS}")
257 string(APPEND CMAKE_C_LINK_EXECUTABLE " ${SECP256K1_APPEND_LDFLAGS}")
258 endif()
259
260 if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
261 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
262 endif()
263 if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
264 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
265 endif()
266 if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
267 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
268 endif()
269 add_subdirectory(src)
270 if(SECP256K1_BUILD_EXAMPLES)
271 add_subdirectory(examples)
272 endif()
273
274 message("\n")
275 message("secp256k1 configure summary")
276 message("===========================")
277 message("Build artifacts:")
278 if(BUILD_SHARED_LIBS)
279 set(library_type "Shared")
280 else()
281 set(library_type "Static")
282 endif()
283
284 message(" library type ........................ ${library_type}")
285 message("Optional modules:")
286 message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}")
287 message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}")
288 message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}")
289 message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}")
290 message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}")
291 message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}")
292 message("Parameters:")
293 message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}")
294 message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB")
295 message("Optional features:")
296 message(" assembly ............................ ${SECP256K1_ASM}")
297 message(" external callbacks .................. ${SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS}")
298 if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
299 message(" wide multiplication (test-only) ..... ${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}")
300 endif()
301 message("Optional binaries:")
302 message(" benchmark ........................... ${SECP256K1_BUILD_BENCHMARK}")
303 message(" noverify_tests ...................... ${SECP256K1_BUILD_TESTS}")
304 set(tests_status "${SECP256K1_BUILD_TESTS}")
305 if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
306 set(tests_status OFF)
307 endif()
308 message(" tests ............................... ${tests_status}")
309 message(" exhaustive tests .................... ${SECP256K1_BUILD_EXHAUSTIVE_TESTS}")
310 message(" ctime_tests ......................... ${SECP256K1_BUILD_CTIME_TESTS}")
311 message(" examples ............................ ${SECP256K1_BUILD_EXAMPLES}")
312 message("")
313 if(CMAKE_CROSSCOMPILING)
314 set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
315 else()
316 set(cross_status "FALSE")
317 endif()
318 message("Cross compiling ....................... ${cross_status}")
319 message("API visibility attributes ............. ${SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES}")
320 message("Valgrind .............................. ${SECP256K1_VALGRIND}")
321 get_directory_property(definitions COMPILE_DEFINITIONS)
322 string(REPLACE ";" " " definitions "${definitions}")
323 message("Preprocessor defined macros ........... ${definitions}")
324 message("C compiler ............................ ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}, ${CMAKE_C_COMPILER}")
325 message("CFLAGS ................................ ${CMAKE_C_FLAGS}")
326 get_directory_property(compile_options COMPILE_OPTIONS)
327 string(REPLACE ";" " " compile_options "${compile_options}")
328 message("Compile options ....................... " ${compile_options})
329 if(NOT is_multi_config)
330 message("Build type:")
331 message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
332 string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
333 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${build_type}}")
334 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}")
335 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}")
336 else()
337 message("Supported configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
338 message("RelWithDebInfo configuration:")
339 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
340 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
341 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}")
342 message("Debug configuration:")
343 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_DEBUG}")
344 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
345 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
346 endif()
347 if(SECP256K1_APPEND_CFLAGS)
348 message("SECP256K1_APPEND_CFLAGS ............... ${SECP256K1_APPEND_CFLAGS}")
349 endif()
350 if(SECP256K1_APPEND_LDFLAGS)
351 message("SECP256K1_APPEND_LDFLAGS .............. ${SECP256K1_APPEND_LDFLAGS}")
352 endif()
353 message("")
354 if(print_msan_notice)
355 message(
356 "Note:\n"
357 " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to compile options\n"
358 " to avoid false positives in ctime_tests. Pass -DSECP256K1_BUILD_CTIME_TESTS=OFF to avoid this.\n"
359 )
360 endif()
361 if(SECP256K1_EXPERIMENTAL)
362 message(
363 " ******\n"
364 " WARNING: experimental build\n"
365 " Experimental features do not have stable APIs or properties, and may not be safe for production use.\n"
366 " ******\n"
367 )
368 endif()
369