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