diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b836cd6d6..1a4387ee5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -538,6 +538,10 @@ jobs: name: ${{ matrix.configuration.job_name }} # See: https://github.com/actions/runner-images#available-images. runs-on: windows-2022 + defaults: + run: + # Enforce fail-fast behavior for PowerShell. + shell: pwsh -Command "$PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'" strategy: fail-fast: false @@ -570,7 +574,13 @@ jobs: - *CHECKOUT - name: Generate buildsystem - run: cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" cmake -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON ${{ matrix.configuration.cmake_options }} + run: | + cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" ` + cmake -B build ` + -DSECP256K1_BUILD_PRECOMPUTED=ON ` + -DSECP256K1_ENABLE_MODULE_RECOVERY=ON ` + -DSECP256K1_BUILD_EXAMPLES=ON ` + ${{ matrix.configuration.cmake_options }} - name: Build run: cmake --build build --config RelWithDebInfo -- /p:UseMultiToolTask=true /maxCpuCount @@ -596,6 +606,11 @@ jobs: build\bin\RelWithDebInfo\bench_internal.exe build\bin\RelWithDebInfo\bench.exe + - name: Check precomputed files + run: | + cmake -E copy build/src/precomputed_ecmult.c build/src/precomputed_ecmult_gen.c -t src + git diff --exit-code + win64-native-headers: name: "x64 (MSVC): C++ (public headers)" # See: https://github.com/actions/runner-images#available-images. diff --git a/CMakeLists.txt b/CMakeLists.txt index a84305c340..1e7caaed94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.22) +if(POLICY CMP0171) + # `codegen` is a reserved target name. + # See: https://cmake.org/cmake/help/latest/policy/CMP0171.html + cmake_policy(SET CMP0171 NEW) +endif() + #============================= # Project / Package metadata #============================= @@ -141,6 +147,11 @@ option(SECP256K1_BUILD_EXHAUSTIVE_TESTS "Build exhaustive tests." ON) option(SECP256K1_BUILD_CTIME_TESTS "Build constant-time tests." ${SECP256K1_VALGRIND}) option(SECP256K1_BUILD_EXAMPLES "Build examples." OFF) +option(SECP256K1_BUILD_PRECOMPUTED "Generate the precomputed files in the build tree." OFF) +if(SECP256K1_BUILD_PRECOMPUTED AND CMAKE_CROSSCOMPILING) + message(FATAL_ERROR "SECP256K1_BUILD_PRECOMPUTED requires executing precompute tools, which is not supported when cross compiling.") +endif() + # Redefine configuration flags. # We leave assertions on, because they are only used in the examples, and we want them always on there. if(MSVC) diff --git a/cmake/Precompute.cmake b/cmake/Precompute.cmake new file mode 100644 index 0000000000..7192af637b --- /dev/null +++ b/cmake/Precompute.cmake @@ -0,0 +1,21 @@ +function(precompute base_name) + add_executable(secp256k1_precompute_${base_name} EXCLUDE_FROM_ALL precompute_${base_name}.c) + set_target_properties(secp256k1_precompute_${base_name} PROPERTIES + COMPILE_DEFINITIONS VERIFY + RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR} + ) + set(CODEGEN_OPT "") + if(POLICY CMP0171) + cmake_policy(GET CMP0171 _cmp0171_status) + if(_cmp0171_status STREQUAL "NEW") + set(CODEGEN_OPT CODEGEN) + endif() + endif() + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/src/precomputed_${base_name}.c + COMMAND secp256k1_precompute_${base_name} + DEPENDS secp256k1_precompute_${base_name} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ${CODEGEN_OPT} + ) +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a45eeb93e4..3293e5a7e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,10 +45,22 @@ if(SECP256K1_ENABLE_MODULE_ECDH) set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h) endif() -add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL - precomputed_ecmult.c - precomputed_ecmult_gen.c -) +add_library(secp256k1_precomputed OBJECT) +if(SECP256K1_BUILD_PRECOMPUTED) + include(Precompute) + precompute(ecmult) + precompute(ecmult_gen) + target_sources(secp256k1_precomputed PRIVATE + ${PROJECT_BINARY_DIR}/src/precomputed_ecmult.c + ${PROJECT_BINARY_DIR}/src/precomputed_ecmult_gen.c + ) + target_include_directories(secp256k1_precomputed PRIVATE ${CMAKE_CURRENT_LIST_DIR}) +else() + target_sources(secp256k1_precomputed PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/precomputed_ecmult.c + ${CMAKE_CURRENT_LIST_DIR}/precomputed_ecmult_gen.c + ) +endif() # Add objects explicitly rather than linking to the object libs to keep them # from being exported. diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c index 8579c85f22..62938c9468 100644 --- a/src/precompute_ecmult.c +++ b/src/precompute_ecmult.c @@ -75,7 +75,7 @@ int main(void) { fprintf(fp, "#include \"precomputed_ecmult.h\"\n"); fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); fprintf(fp, "#if ECMULT_WINDOW_SIZE > %d\n", window_g); - fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.\n"); + fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. If this is an Autotools build, try deleting precomputed_ecmult.c before the build. If this is a CMake build, pass -DSECP256K1_BUILD_PRECOMPUTED=ON to cmake.\n"); fprintf(fp, "#endif\n"); fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); fprintf(fp, "# error Cannot compile precomputed_ecmult.c in exhaustive test mode\n"); diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index a03abdb548..d09e3ffa77 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -90,7 +90,7 @@ int main(int argc, char **argv) { print_table(fp, COMB_BLOCKS, COMB_TEETH); } fprintf(fp, "#else\n"); - fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build.\n"); + fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. If this is an Autotools build, try deleting precomputed_ecmult_gen.c before the build. If this is a CMake build, pass -DSECP256K1_BUILD_PRECOMPUTED=ON to cmake.\n"); fprintf(fp, "#endif\n"); fprintf(fp, "};\n"); diff --git a/src/precomputed_ecmult.c b/src/precomputed_ecmult.c index cbd030ce50..491c497ee5 100644 --- a/src/precomputed_ecmult.c +++ b/src/precomputed_ecmult.c @@ -7,7 +7,7 @@ #include "precomputed_ecmult.h" #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) #if ECMULT_WINDOW_SIZE > 15 - #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build. + #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. If this is an Autotools build, try deleting precomputed_ecmult.c before the build. If this is a CMake build, pass -DSECP256K1_BUILD_PRECOMPUTED=ON to cmake. #endif #ifdef EXHAUSTIVE_TEST_ORDER # error Cannot compile precomputed_ecmult.c in exhaustive test mode diff --git a/src/precomputed_ecmult_gen.c b/src/precomputed_ecmult_gen.c index 248fb077e5..6cbf37759d 100644 --- a/src/precomputed_ecmult_gen.c +++ b/src/precomputed_ecmult_gen.c @@ -1773,7 +1773,7 @@ S(2934de46,a6d921f8,720567e6,b46e6362,36a7ed53,483b13ed,20958452,3225accd,597969 S(4e9991b,92fa8c4e,4e8efe45,66966073,319e80d3,a54d4b7a,b61cfcc4,7ddaa5d5,9d03ea22,21d4d80e,261952e2,73f6a8cf,c31f6091,e5aa0a8f,2281ffbf,1345df9e), S(ff3d6136,ffac5b0c,bfc6c5c0,c30dc01a,7ea3d56c,20bd3103,b178e3d3,ae180068,eccdc641,7b1bfff1,bf2fc8d3,2269523e,ab89890d,bffe0a19,8f594490,e7739bb8)} #else -# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build. +# error Configuration mismatch, invalid COMB_* parameters. If this is an Autotools build, try deleting precomputed_ecmult_gen.c before the build. If this is a CMake build, pass -DSECP256K1_BUILD_PRECOMPUTED=ON to cmake. #endif }; #undef S