-
Notifications
You must be signed in to change notification settings - Fork 37.7k
build, ci: Fix linking bitcoin-chainstate.exe
to bitcoinkernel.dll
on Windows
#31158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31158. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
bitcoin-chainstate.exe
to bticoinkernel.dll
on Windowsbitcoin-chainstate.exe
to bitcoinkernel.dll
on Windows
37ebd77
to
ca9554f
Compare
ca9554f
to
822780c
Compare
src/kernel/cs_main.h
Outdated
@@ -17,6 +17,6 @@ | |||
* The transaction pool has a separate lock to allow reading from it and the | |||
* chainstate at the same time. | |||
*/ | |||
extern RecursiveMutex cs_main; | |||
inline RecursiveMutex cs_main; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked if this could also be a problem for other extern symbols that are currently not used in bitcoin-chainstate
, but still part of the kernel library. For example in src/validation.h
we have extern const std::vector<std::string> CHECKLEVEL_DOC;
, and it looks like using it is indeed problematic too if it were used externally: https://github.com/TheCharlatan/bitcoin/actions/runs/11531552497/job/32102377337#step:10:425.
There are a bunch of other such cases, where I'm not entirely sure how to handle them. Could just ignore them for now, but it is a bit annoying that the library might contain symbols that you couldn't just use.
EDIT: I guess this is another argument for having a clear list of exports from the lib.
822780c
to
fc3a37d
Compare
Rebased due to the conflict with the merged #31130. |
Concept ACK and code review ACK. This needs a more useful commit message though. I wasn't familiar with this c++17 functionality, and at first glance it looked scary to me (as though we might get multiple This stackoverflow question/answers also covers our use-case exactly. Agree with @TheCharlatan that we should track down other cases as well. |
Wait, I take that back. It seems like we could still get 2 separate |
Generally I would prefer if we weren't making source code changes to fix (currently edge-case) Windows linking errors; especially if there are more complete fixes we could be making (even if later-on). It'd be good if all commits explained the problem, and fix. i.e the first commit 4a1accd |
fc3a37d
to
82429ba
Compare
Rebased. The commit messages have been amended.
That's an interesting observation. Could you elaborate on how you think the two separate If there's a relevant section in the documentation or standard that you believe applies, pointing it out would be helpful for clarity. |
clang 21 (git) has introduced a new warning for this! And turns out, yeah, it is problematic for us with this PR:
master currently does not have this issue. also (unrelated to this PR, but of interest)
(maybe more) This warning shows for bitcoind when REDUCE_EXPORTS is on, but not for the kernel because it currently overrides that. I have verified that this does work though: __attribute__ ((visibility ("default"))) inline RecursiveMutex cs_main; But I'm not sure if that's what we want to be doing. Need to think this through some more. |
To clarify this discussion, which binary you are referring to— |
Mind sharing a link? |
Yes. But when inlining, it's free to generate its own as opposed to using the kernel's. Which is the opposite of what we want.
Sorry, I meant to link there. Updated. Give me a few min, I'm testing over here :) |
Please give https://github.com/theuni/bitcoin/commits/pr31158/ a shot. It's not meant to be robust, but it should illustrate the fix (using dllimport for bitcoin-chainstate.exe). |
CI fails: https://github.com/theuni/bitcoin/actions/runs/13163570761/job/36738155052 |
Yeah, the above is only enough to test |
Converting to a draft after today's offline discussion with @theuni. |
82429ba
to
fe79ea0
Compare
Thank you for your insight! This PR has been reworked based on your branch. The |
Thank you @hebasto! We had a pretty long discussion about this. I think that hebasto's approach is probably fine and would never be an issue in the real world. I'll admit that I'm being overly paranoid and probably wrong about the guarantees that linkers provide... But still, I'm not alone in my paranoia. For example, Google has banned non-constexpr inline header variables for Chromium out of similar concerns. This reddit thread also contains a discussion from which illustrates some of my concerns and made me nervous. For reference, the original proposal was: -extern RecursiveMutex cs_main;
+inline RecursiveMutex cs_main; And here's how the binaries changed in Linux: extern (as-in current master): $ nm -C src/kernel/libbitcoinkernel.so | grep cs_main
00000000003b3028 D cs_main
$ nm -C src/bitcoin-chainstate | grep cs_main
U cs_main header-inline (this PR's original proposal): $ nm -C src/kernel/libbitcoinkernel.so | grep cs_main
00000000003b3010 V cs_main
00000000003b35f0 V guard variable for cs_main
$ nm -C src/bitcoin-chainstate | grep cs_main
000000000000e010 V cs_main
000000000000e048 V guard variable for cs_main Notice that the symbols, now weak, now exist in the shared lib as well as the binary. The runtime loader should pick one to use on both sides of the binary boundary, but technically the link/load behaviors here are platform-specific. The root cause of the link failure being addressed here is that CMake's visibility machinery handles functions but not variables. So there are basically 3 potential solutions:
I pretty strongly prefer the 3rd as it's minimally invasive and leaves no potential for regressions in bitcoind/kernel. Will review in detail. |
src/kernel/symbol_visibility.h
Outdated
#else | ||
#define BITCOINKERNEL_EXPORT __attribute__ ((visibility ("default"))) | ||
#endif | ||
#elif defined(_WIN32) && !defined(BITCOINKERNEL_STATIC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The meaning of BITCOINKERNEL_STATIC
here is overloaded. Just to differentiate the use-cases, I'd prefer to have a 3rd define here:
#elif defined(_WIN32) && !defined(BITCOIN_BUILD_INTERNAL) && !defined(BITCOINKERNEL_STATIC)
BITCOINKERNEL_STATIC
: I'm a user of the kernel building against a static kernel.
BITCOIN_BUILD_INTERNAL
: I'm a component of Core who's not building against the kernel at all, I just happen to be seeing this header.
The former should stay as-is for bitcoin-chainstate, the latter is what we should be defining for the other internal libs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BITCOIN_BUILD_INTERNAL
: I'm a component of Core who's not building against the kernel at all, I just happen to be seeing this header.
BITCOIN_INTERNAL_BUILD
was in my draft of the updated branch this morning :)
Will rework the PR shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Reworked.
To enable linking to `bitcoinkernel.dll`, temporarily enable the CMake's `WINDOWS_EXPORT_ALL_SYMBOLS` property. Global data symbols, such as `cs_main`, must still be properly attributed with `__declspec(dllexport)` and `__declspec(dllimport)`. This change can be reconsidered once the kernel API headers become available. Co-authored-by: Cory Fields <cory-nospam-@coryfields.com>
This change expands the matrix jobs for the native Windows builds to test shared and static `bitcoinkernel` libraries. To conserve resources, the functional tests are enabled for a single job only.
This change prevents issues related to the `__declspec(dllimport)` attribute, such as LNK4217 or LNK4286.
fe79ea0
to
939e8e9
Compare
(Probably out-of-scope for this pull, but there is already a getter for cs_main: |
Ran into this linker error when attempting to test #31161 on Windows yesterday. The kernel library exposing Concept ACK. |
#endif | ||
|
||
#ifndef BITCOINKERNEL_EXPORT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Less confusing for every branch in the block to result in #define
:
#endif | |
#ifndef BITCOINKERNEL_EXPORT | |
#else |
# Temporarily enable WINDOWS_EXPORT_ALL_SYMBOLS until a dedicated | ||
# header with __declspec(dllexport) directives is available. | ||
WINDOWS_EXPORT_ALL_SYMBOLS TRUE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't symbol_visibility.h this dedicated header?
🐙 This pull request conflicts with the target branch and needs rebase. |
I'm not sure about the current approach of this change. I think we could go the way of manually exporting symbols in our c++ code, but then I would call into question the need for this project to ship a C header in the first place. Having two symbol-exporting headers, one for our internal code, and one for a potential future C header seems very confusing. Also, as maflcko already said, we could just not directly use these globals from code that links to the shared library. If I understand the problem correctly, in the case of cs_main the required change is very small, and taking a similar approach for the other ones (if we ever run into them) seems reasonable. |
I agree. There's no rush or need to do anything here, and doing something just to "make things green/compile" seems like the wrong choice, rather than making some good design decisions. |
Converted to a draft for now. |
⌛ There hasn't been much activity lately and the patch still needs rebase. What is the status here?
|
On the master branch @ 9a7206a, linking
bitcoin-chainstate.exe
tobitcoinkernel.dll
fails:This PR fixes this issue and enables the same scenario in the "Win64 native" CI job.