CMakeLists.txt
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 else() 151 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") 152 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") 153 string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") 154 # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.) 155 string(REGEX REPLACE "-O3( |$)" "-O2\\1" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") 156 endif() 157 158 # Define custom "Coverage" build type. 159 set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O0 -DCOVERAGE=1 --coverage" CACHE STRING 160 "Flags used by the C compiler during \"Coverage\" builds." 161 FORCE 162 ) 163 set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING 164 "Flags used for linking binaries during \"Coverage\" builds." 165 FORCE 166 ) 167 set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING 168 "Flags used by the shared libraries linker during \"Coverage\" builds." 169 FORCE 170 ) 171 mark_as_advanced( 172 CMAKE_C_FLAGS_COVERAGE 173 CMAKE_EXE_LINKER_FLAGS_COVERAGE 174 CMAKE_SHARED_LINKER_FLAGS_COVERAGE 175 ) 176 177 if(PROJECT_IS_TOP_LEVEL) 178 get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 179 set(default_build_type "RelWithDebInfo") 180 if(is_multi_config) 181 set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING 182 "Supported configuration types." 183 FORCE 184 ) 185 else() 186 set_property(CACHE CMAKE_BUILD_TYPE PROPERTY 187 STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" 188 ) 189 if(NOT CMAKE_BUILD_TYPE) 190 message(STATUS "Setting build type to \"${default_build_type}\" as none was specified") 191 set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING 192 "Choose the type of build." 193 FORCE 194 ) 195 endif() 196 endif() 197 endif() 198 199 include(TryAppendCFlags) 200 if(MSVC) 201 # For both cl and clang-cl compilers. 202 try_append_c_flags(/W3) # Production quality warning level. 203 # Eliminate deprecation warnings for the older, less secure functions. 204 add_compile_definitions(_CRT_SECURE_NO_WARNINGS) 205 else() 206 try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. 207 endif() 208 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") 209 # Keep the following commands ordered lexicographically. 210 try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". 211 try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". 212 try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". 213 else() 214 # Keep the following commands ordered lexicographically. 215 try_append_c_flags(-pedantic) 216 try_append_c_flags(-Wcast-align) # GCC >= 2.95. 217 try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. 218 try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. 219 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. 220 try_append_c_flags(-Wleading-whitespace=spaces) # GCC >= 15.0 221 try_append_c_flags(-Wnested-externs) 222 try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic. 223 try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic. 224 try_append_c_flags(-Wno-unused-function) # GCC >= 3.0, -Wunused-function is implied by -Wall. 225 try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only. 226 try_append_c_flags(-Wshadow) 227 try_append_c_flags(-Wstrict-prototypes) 228 try_append_c_flags(-Wtrailing-whitespace=any) # GCC >= 15.0 229 try_append_c_flags(-Wundef) 230 endif() 231 232 set(print_msan_notice) 233 if(SECP256K1_BUILD_CTIME_TESTS) 234 include(CheckMemorySanitizer) 235 check_memory_sanitizer(msan_enabled) 236 if(msan_enabled) 237 try_append_c_flags(-fno-sanitize-memory-param-retval) 238 set(print_msan_notice YES) 239 endif() 240 unset(msan_enabled) 241 endif() 242 243 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.") 244 if(SECP256K1_APPEND_CFLAGS) 245 # Appending to this low-level rule variable is the only way to 246 # guarantee that the flags appear at the end of the command line. 247 string(APPEND CMAKE_C_COMPILE_OBJECT " ${SECP256K1_APPEND_CFLAGS}") 248 endif() 249 250 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.") 251 if(SECP256K1_APPEND_LDFLAGS) 252 # Appending to this low-level rule variable is the only way to 253 # guarantee that the flags appear at the end of the command line. 254 string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " ${SECP256K1_APPEND_LDFLAGS}") 255 string(APPEND CMAKE_C_LINK_EXECUTABLE " ${SECP256K1_APPEND_LDFLAGS}") 256 endif() 257 258 if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) 259 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) 260 endif() 261 if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) 262 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) 263 endif() 264 if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) 265 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) 266 endif() 267 add_subdirectory(src) 268 if(SECP256K1_BUILD_EXAMPLES) 269 add_subdirectory(examples) 270 endif() 271 272 message("\n") 273 message("secp256k1 configure summary") 274 message("===========================") 275 message("Build artifacts:") 276 if(BUILD_SHARED_LIBS) 277 set(library_type "Shared") 278 else() 279 set(library_type "Static") 280 endif() 281 282 message(" library type ........................ ${library_type}") 283 message("Optional modules:") 284 message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}") 285 message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}") 286 message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}") 287 message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") 288 message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") 289 message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") 290 message("Parameters:") 291 message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") 292 message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB") 293 message("Optional features:") 294 message(" assembly ............................ ${SECP256K1_ASM}") 295 message(" external callbacks .................. ${SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS}") 296 if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY) 297 message(" wide multiplication (test-only) ..... ${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}") 298 endif() 299 message("Optional binaries:") 300 message(" benchmark ........................... ${SECP256K1_BUILD_BENCHMARK}") 301 message(" noverify_tests ...................... ${SECP256K1_BUILD_TESTS}") 302 set(tests_status "${SECP256K1_BUILD_TESTS}") 303 if(CMAKE_BUILD_TYPE STREQUAL "Coverage") 304 set(tests_status OFF) 305 endif() 306 message(" tests ............................... ${tests_status}") 307 message(" exhaustive tests .................... ${SECP256K1_BUILD_EXHAUSTIVE_TESTS}") 308 message(" ctime_tests ......................... ${SECP256K1_BUILD_CTIME_TESTS}") 309 message(" examples ............................ ${SECP256K1_BUILD_EXAMPLES}") 310 message("") 311 if(CMAKE_CROSSCOMPILING) 312 set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}") 313 else() 314 set(cross_status "FALSE") 315 endif() 316 message("Cross compiling ....................... ${cross_status}") 317 message("API visibility attributes ............. ${SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES}") 318 message("Valgrind .............................. ${SECP256K1_VALGRIND}") 319 get_directory_property(definitions COMPILE_DEFINITIONS) 320 string(REPLACE ";" " " definitions "${definitions}") 321 message("Preprocessor defined macros ........... ${definitions}") 322 message("C compiler ............................ ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}, ${CMAKE_C_COMPILER}") 323 message("CFLAGS ................................ ${CMAKE_C_FLAGS}") 324 get_directory_property(compile_options COMPILE_OPTIONS) 325 string(REPLACE ";" " " compile_options "${compile_options}") 326 message("Compile options ....................... " ${compile_options}) 327 if(NOT is_multi_config) 328 message("Build type:") 329 message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") 330 string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) 331 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${build_type}}") 332 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}") 333 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}") 334 else() 335 message("Supported configurations .............. ${CMAKE_CONFIGURATION_TYPES}") 336 message("RelWithDebInfo configuration:") 337 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}") 338 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}") 339 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}") 340 message("Debug configuration:") 341 message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_DEBUG}") 342 message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") 343 message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") 344 endif() 345 if(SECP256K1_APPEND_CFLAGS) 346 message("SECP256K1_APPEND_CFLAGS ............... ${SECP256K1_APPEND_CFLAGS}") 347 endif() 348 if(SECP256K1_APPEND_LDFLAGS) 349 message("SECP256K1_APPEND_LDFLAGS .............. ${SECP256K1_APPEND_LDFLAGS}") 350 endif() 351 message("") 352 if(print_msan_notice) 353 message( 354 "Note:\n" 355 " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to compile options\n" 356 " to avoid false positives in ctime_tests. Pass -DSECP256K1_BUILD_CTIME_TESTS=OFF to avoid this.\n" 357 ) 358 endif() 359 if(SECP256K1_EXPERIMENTAL) 360 message( 361 " ******\n" 362 " WARNING: experimental build\n" 363 " Experimental features do not have stable APIs or properties, and may not be safe for production use.\n" 364 " ******\n" 365 ) 366 endif()