/ src / secp256k1 / CMakeLists.txt
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()