Skip to content

cmake: Add option to generate precomputed files#1791

Open
hebasto wants to merge 2 commits into
bitcoin-core:masterfrom
hebasto:251220-cmake-precomputed
Open

cmake: Add option to generate precomputed files#1791
hebasto wants to merge 2 commits into
bitcoin-core:masterfrom
hebasto:251220-cmake-precomputed

Conversation

@hebasto

@hebasto hebasto commented Dec 20, 2025

Copy link
Copy Markdown
Member

Using the CMake-based build system enables smoother integration with parent projects by providing both CMake package configuration files and the traditional libsecp256k1.pc.

However, packagers on some systems, such as Gentoo and Guix, insist on recreating the precomputed files, which is not currently supported by the CMake-based build system.

This PR addresses the issue by introducing a new SECP256K1_BUILD_PRECOMPUTED option (OFF by default) that generates precomputed_ecmult.c and precomputed_ecmult_gen.c in the build tree. Those files are then compiled instead of the ones checked into the source tree.

Here is an example:

$ cmake -B build -G Ninja -DSECP256K1_BUILD_PRECOMPUTED=ON
$ ninja -C build src/precomputed_ecmult.c src/precomputed_ecmult_gen.c | cat
ninja: Entering directory `build'
[1/6] Building C object src/CMakeFiles/secp256k1_precompute_ecmult.dir/precompute_ecmult.c.o
[2/6] Building C object src/CMakeFiles/secp256k1_precompute_ecmult_gen.dir/precompute_ecmult_gen.c.o
[3/6] Linking C executable secp256k1_precompute_ecmult_gen
[4/6] Linking C executable secp256k1_precompute_ecmult
[5/6] Generating precomputed_ecmult_gen.c
[6/6] Generating precomputed_ecmult.c

When configuring with CMake 3.31 or newer, the built-in codegen target can be used to generate those files:

$ cmake -B build -G Ninja -DSECP256K1_BUILD_PRECOMPUTED=ON
$ cmake --build build -t codegen | cat
[1/6] Building C object src/CMakeFiles/secp256k1_precompute_ecmult.dir/precompute_ecmult.c.o
[2/6] Building C object src/CMakeFiles/secp256k1_precompute_ecmult_gen.dir/precompute_ecmult_gen.c.o
[3/6] Linking C executable secp256k1_precompute_ecmult_gen
[4/6] Linking C executable secp256k1_precompute_ecmult
[5/6] Generating precomputed_ecmult_gen.c
[6/6] Generating precomputed_ecmult.c

@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch 2 times, most recently from cbc6679 to 5373c6a Compare December 20, 2025 23:52
@kevkevinpal

Copy link
Copy Markdown
Contributor

are we able to do this via ./configure?

or is this meant to be only done for CMake?

@hebasto

hebasto commented Dec 24, 2025

Copy link
Copy Markdown
Member Author

are we able to do this via ./configure?

Yes. Run make clean-precomp && make precomp.

@real-or-random real-or-random left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

Comment thread src/CMakeLists.txt Outdated
Comment thread src/CMakeLists.txt Outdated
@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 5373c6a to f9eeb11 Compare January 6, 2026 18:08
@hebasto

hebasto commented Jan 6, 2026

Copy link
Copy Markdown
Member Author

@real-or-random

Thank you for the review! Your feedback has been addressed.

@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from f9eeb11 to fdfda7b Compare January 7, 2026 12:52
real-or-random added a commit that referenced this pull request Jan 27, 2026
47eb709 ecmult: Use size_t for array indices in _odd_multiplies_table (Tim Ruffing)
bb1d199 ecmult: Use size_t for array indices into tables (Tim Ruffing)

Pull request description:

  I don't think the current code is incorrect, but using `size_t` improves readability because the type makes it clear that we're dealing with array indices.

  Also, making the result of the `ECMULT_TABLE_SIZE` macro (hopefully) a `size_t` fixes a compiler warning on MSVC, see #1791.

ACKs for top commit:
  hebasto:
    re-ACK 47eb709.
  jonasnick:
    ACK 47eb709
  theStack:
    ACK 47eb709

Tree-SHA512: e484fd610d50e972021c0184a683993364290eb58e09b65f9521b4507ec8d0639b402c67002005630b389bc863a7aa05b75f7224524dbcbafbfa5f9a4812b4a5
@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from fdfda7b to 8b58c55 Compare January 27, 2026 11:25
@hebasto

hebasto commented Jan 27, 2026

Copy link
Copy Markdown
Member Author

Rebased on the top of the first commit from #1794.

Rebased on top of the merged #1794.

@theStack

theStack commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Concept ACK

Tested quickly that

$ cmake -B build -DSECP256K1_ECMULT_WINDOW_SIZE=16 -DSECP256K1_BUILD_PRECOMPUTED=ON && cmake --build build

succeeds on the PR branch as expected, while on master

$ cmake -B build -DSECP256K1_ECMULT_WINDOW_SIZE=16 && cmake --build build

fails (error: #error configuration mismatch, invalid ECMULT_WINDOW_SIZE).

The generated files precomputed_ecmult{,gen}.c files are created within the build directory. Given the out-of-tree build nature of CMake, I guess this is intended and there are no plans to support directly modifying the source tree? (Which is no big deal, developers can simply do a $ cp ./build/src/precomputed_ecmult*.c ./src/ after manually or just re-run the precompute binaries).

@hebasto

hebasto commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

Given the out-of-tree build nature of CMake, I guess this is intended and there are no plans to support directly modifying the source tree?

That's correct. We have to assume the source tree might be strictly read-only.

@theStack theStack left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Light ACK 8b58c55

I'm not too familiar with the ins and outs of CMake, but the changes look good and I tested the new build setting both with higher ecmult window sizes (as shown above) and with different ecmult_gen CONFIGS table values (taken from theStack@3421153), and everything seems to work as expected.

// EDIT: I guess this is worth a release note

Comment thread CMakeLists.txt Outdated
@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 8b58c55 to 8460c59 Compare June 9, 2026 11:04
@hebasto

hebasto commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

The most recent feedback has been addressed.

@theStack theStack left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK 8460c59

Verified that the only change since my last review was the more detailed build option description (+"in the build tree"), which I agree makes sense.

@real-or-random

Copy link
Copy Markdown
Contributor

fails (error: #error configuration mismatch, invalid ECMULT_WINDOW_SIZE).

The truth is that it also outputs Try deleting precomputed_ecmult.c before the build. And this is not true for the approach in this PR. With Automake, we construct real dependencies, i.e., the main artifact depends on the pregenerated files. Here, this is just a build option.

I think either approach is fine. I guess even mixing them is fine. Maybe we should just change the error message for now? "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."


Further thoughts:

I'm wondering if I like the "build option" approach as in this PR more. It's easier for those users who need it, and the code is simpler. And even for contributors working on changes to the generation binaries, they can just set -DSECP256K1_BUILD_PRECOMPUTED=ON in their cache.

If others agree, this raises the question of whether we want to get rid of that stuff in autotools. It never worked 100%. And it seems that all users who want this feature use CMake. (@kevkevinpal Why did you ask about autotools? Do you need this feature in autotools?)

@real-or-random real-or-random left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider rebasing this. The branch is way behind (for our standards ;)).

Comment thread CMakePresets.json Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new CMake build option, SECP256K1_BUILD_PRECOMPUTED, to optionally regenerate the precomputed_ecmult*.c sources in the build tree for packagers that require recreating these generated files.

Changes:

  • Introduces SECP256K1_BUILD_PRECOMPUTED (default OFF) and wires it into the src/ CMake logic to switch between in-tree vs build-tree precomputed sources.
  • Adds a new cmake/Precompute.cmake helper that builds/runs precompute_* generators to produce src/precomputed_*.c in the build directory.
  • Enables the option in the dev-mode CMake preset and in the Windows CMake CI job to exercise the path.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/CMakeLists.txt Switches secp256k1_precomputed object sources between shipped and regenerated precomputed .c files based on the new option.
CMakePresets.json Enables precompute regeneration in the dev-mode preset.
CMakeLists.txt Adds the new SECP256K1_BUILD_PRECOMPUTED option definition.
cmake/Precompute.cmake Adds a precompute() helper to build generator executables and register custom commands for generated .c outputs.
.github/workflows/ci.yml Turns on SECP256K1_BUILD_PRECOMPUTED for Windows CMake CI configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmake/Precompute.cmake
Comment thread src/CMakeLists.txt
Comment on lines +49 to +52
if(SECP256K1_BUILD_PRECOMPUTED)
include(Precompute)
precompute(ecmult)
precompute(ecmult_gen)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The current CMake implementation doesn't support cross-compiling. And neither does Autotools.

FWIW, I have a branch that introduces this support, but I'm not sure whether the extra complexity is justified.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I have a branch that introduces this support, but I'm not sure whether the extra complexity is justified.

Ah please don't. :D Years ago, when we always ran the precomputation during the build (no precomputed files in repo), we had support for this in Autotools. But handling the different compilers (one for host and one for target) was a nightmare for users who wanted to cross-compile and for us to maintain. It's one of the reasons why added the precomputed files to the repo.

I think if we really want to support this during cross-compilation, we'd rather rewrite the precomputation helpers in python or sage.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah please don't. :D Years ago, when we always ran the precomputation during the build (no precomputed files in repo), we had support for this in Autotools.

TIL. Not arguing, but CMake has built-in ways to achieve this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMake has built-in ways to achieve this.

autoconf has this here: https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html (not exactly built-in but that's the standard way on autoconf)

I totally believe that the CMake way of doing this is much cleaner, but I think part of the problem is on a conceptual level. Now you get effectively two build configs with all their complexity. You have separate CFLAGS, CPPFLAGS, LDFLAGS, which raises all kinds of questions, e.g., which warning options do you want to set on the compiler for the build machine? Maybe the compiler is entirely different, e.g., you have a new clang for the build machine but an old gcc for the target, etc... And some of this complexity is necessarily pushed down to the user.

Just assuming the existence of Python or similar is probably simpler. Back then we had already considered using Python instead, but approach to add the precomputed files to the repo was just less work, so we went with this instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But do you think some error message like suggested by the LLM makes sense for now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But do you think some error message like suggested by the LLM makes sense for now?

Done.

@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 8460c59 to 80edad3 Compare June 9, 2026 15:59
@hebasto

hebasto commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

Consider rebasing this. The branch is way behind (for our standards ;)).

Rebased. The recent feedback has been addressed.

Maybe we should just change the error message for now? "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."

Done.

@kevkevinpal

Copy link
Copy Markdown
Contributor

If others agree, this raises the question of whether we want to get rid of that stuff in autotools. It never worked 100%. And it seems that all users who want this feature use CMake. (@kevkevinpal Why did you ask about autotools? Do you need this feature in autotools?)

Trying to remember why but I think was just trying to understand why it wasn't available. If anything I agree with you and also prefer CMake.

@real-or-random

Copy link
Copy Markdown
Contributor

Maybe we should just change the error message for now? "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."

Done.

We have the same message in precomputed_ecmult_gen.c. Sorry, I assumed that's implied. I should have mentioned this explicitly.

@real-or-random

Copy link
Copy Markdown
Contributor

For autotools builds on CI, we have git diff that checks the files in the repo are not outdated. We could do the same on CI for CMake, i.e., copy the files back to the source tree and run git diff --exit-code.

secp256k1/ci/ci.sh

Lines 138 to 147 in 0f4a7e6

# Rebuild precomputed files (if not cross-compiling).
if [ -z "$HOST" ]
then
make clean-precomp clean-testvectors
make precomp testvectors
fi
# Check that no repo files have been modified by the build.
# (This fails for example if the precomp files need to be updated in the repo.)
git diff --exit-code

@hebasto

hebasto commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

Maybe we should just change the error message for now? "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."

Done.

We have the same message in precomputed_ecmult_gen.c. Sorry, I assumed that's implied. I should have mentioned this explicitly.

Of course, I've regenerated precomputed_ecmult_gen.c in the source tree :)

@real-or-random

Copy link
Copy Markdown
Contributor

Maybe we should just change the error message for now? "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."

Done.

We have the same message in precomputed_ecmult_gen.c. Sorry, I assumed that's implied. I should have mentioned this explicitly.

Of course, I've regenerated precomputed_ecmult_gen.c in the source tree :)

Oops, we're talking past each other. Sorry, I meant to write precompute_ecmult_gen.c (without the d).

So you've changed precompute_ecmult.c and precomputed_ecmult.c but not precompute_ecmult_gen.c and precomputed_ecmult_gen.c.

@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 80edad3 to 37152af Compare June 11, 2026 12:55
@hebasto hebasto changed the title cmake: Add option to recreate precomputed files cmake: Add option to generate precomputed files Jun 11, 2026
@hebasto

hebasto commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

Reworked per recent feedback. Added CODEGEN support for modern CMake.

The PR description has been updated.

So you've changed precompute_ecmult.c and precomputed_ecmult.c but not precompute_ecmult_gen.c and precomputed_ecmult_gen.c.

My bad. Fixed.

For autotools builds on CI, we have git diff that checks the files in the repo are not outdated. We could do the same on CI for CMake, i.e., copy the files back to the source tree and run git diff --exit-code.

Done.

Comment thread CMakePresets.json Outdated
Comment thread .github/workflows/ci.yml
Comment on lines +543 to +544
# Enforce fail-fast behavior for PowerShell.
shell: pwsh -Command "$PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be implied according to the docs?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be implied according to the docs?

The docs state: "Fail-fast behavior when possible." Effectively, it works for cmdlets only. Non-zero exit codes from native commands are ignored unless $PSNativeCommandUseErrorActionPreference is also set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigh, why can't we just have nice things...

@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 37152af to 9c08b45 Compare June 11, 2026 13:53
hebasto added 2 commits June 25, 2026 15:50
Add a new `SECP256K1_BUILD_PRECOMPUTED` option (`OFF` by default) that
generates `precomputed_ecmult.c` and `precomputed_ecmult_gen.c` in the
build tree. Those files are then compiled instead of the ones checked
into the source tree.

When configuring with CMake 3.31 or newer, the built-in `codegen` target
can be used to generate those files.
@hebasto
hebasto force-pushed the 251220-cmake-precomputed branch from 9c08b45 to 00b73a4 Compare June 25, 2026 14:50
@hebasto

hebasto commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

Rebased on top of the recent CI changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants