Skip to content

iwyu: Document or remove some pragma: export and other improvements#34639

Open
hebasto wants to merge 6 commits intobitcoin:masterfrom
hebasto:260220-iwyu-pragma
Open

iwyu: Document or remove some pragma: export and other improvements#34639
hebasto wants to merge 6 commits intobitcoin:masterfrom
hebasto:260220-iwyu-pragma

Conversation

@hebasto
Copy link
Member

@hebasto hebasto commented Feb 20, 2026

This PR is a prerequisite for #34448. It was split into a separate PR to limit the scope and minimize potential merge conflicts.

The first commit improves the accuracy of IWYU suggestions within our heavily templated code. Note that, for now, the serialize.h header itself is excluded from IWYU inspection because it lacks a corresponding source file.

The remaining commits follow the Developer Notes guidance:

Use IWYU pragma: export very sparingly, as this enforces transitive inclusion of headers and undermines the specific purpose of IWYU.

@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 20, 2026

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
Stale ACK w0xlt, ryanofsky, maflcko

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34793 (threading: never require logging from sync.h by theuni)
  • #34778 (logging: rewrite macros to add ratelimit option, avoid unused strprintf, clarify confusing errors by ryanofsky)
  • #34448 (ci, iwyu: Fix warnings in src/util and treat them as errors by hebasto)
  • #34435 (refactor: use _MiB/_GiB consistently for byte conversions by l0rinc)
  • #34038 (logging: replace -loglevel with -trace, various API improvements by ajtowns)
  • #30343 (wallet, logging: Replace WalletLogPrintf() with LogInfo() by ryanofsky)
  • #30342 (kernel, logging: Pass Logger instances to kernel objects by ryanofsky)
  • #29256 (log, refactor: Allow log macros to accept context arguments by ryanofsky)
  • #26812 (test: add end-to-end tests for CConnman and PeerManager by vasild)

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.

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

Personally I think it is fine to use export for headers that are always (possibly with a single exception) simply forwarded via another header.

I think this applies to all cases here, except for the chrono one?

@hebasto
Copy link
Member Author

hebasto commented Feb 27, 2026

@maflcko

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

@hebasto hebasto changed the title iwyu: Remove some pragma: export and other improvements iwyu: Document or remove some pragma: export and other improvements Feb 27, 2026
src/util/log.h Outdated
#ifndef BITCOIN_UTIL_LOG_H
#define BITCOIN_UTIL_LOG_H

// Export, as `logging/categories.h` is practically not used stand-alone.
Copy link
Member

Choose a reason for hiding this comment

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

is practically not used stand-alone.

Not sure I understand this comment. Why are we doing this, instead of including the things that we are using? Why does it matter if they might only be used when some other header is also used?

Copy link
Member

Choose a reason for hiding this comment

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

Also, has the rationale for when to do this (or not), been documented in the developer notes?

Copy link
Member Author

Choose a reason for hiding this comment

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

is practically not used stand-alone.

Not sure I understand this comment. Why are we doing this, instead of including the things that we are using? Why does it matter if they might only be used when some other header is also used?

I've reverted this change to its initial variant.

Also, has the rationale for when to do this (or not), been documented in the developer notes?

It seems reasonable to update the developer notes once we work through the entire codebase.

Copy link
Member

Choose a reason for hiding this comment

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

It seems reasonable to update the developer notes once we work through the entire codebase.

Why? The developer docs should reflect how we want new code to be written, and current code to be updated, otherwise you're just guaranteeing having to rework code again later on, rather than having it introduced/updated to how it should be, now.

Copy link
Member

Choose a reason for hiding this comment

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

If this is a blocker, maybe the dev notes can be updated to say that a comment with the rationale are required for exports?

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems reasonable to update the developer notes once we work through the entire codebase.

Why? The developer docs should reflect how we want new code to be written, and current code to be updated, otherwise you're just guaranteeing having to rework code again later on, rather than having it introduced/updated to how it should be, now.

If this is a blocker, maybe the dev notes can be updated to say that a comment with the rationale are required for exports?

Thanks! Done.

@hebasto
Copy link
Member Author

hebasto commented Feb 28, 2026

@theuni

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

@maflcko
Copy link
Member

maflcko commented Feb 28, 2026

review ACK 7713575 🦆

Show signature

Signature:

untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: review ACK 7713575cc83d44a9ffbd9d60ad34a3f49720139e 🦆
o4CFKfSlNayOksST4HbIfwGJA0virv5UET5Bo0O4srh70oXYZl6TmqhfNIvJrEgSZokTdwAo7DzOw9rtkFHnBA==

@hebasto
Copy link
Member Author

hebasto commented Mar 4, 2026

@fanquake @maflcko @theuni

Thank you for the review. The most recent @fanquake's comment has been addressed.

@theuni
Copy link
Member

theuni commented Mar 4, 2026

I don't understand what makes that handful of .cpp files special? Why do only a few require a direct logging/categories.h include?

@hebasto
Copy link
Member Author

hebasto commented Mar 4, 2026

I don't understand what makes that handful of .cpp files special? Why do only a few require a direct logging/categories.h include?

They are not special rather ones where IWYU warnings are treated as errors:

FILES_WITH_ENFORCED_IWYU="/src/((crypto|index|kernel|primitives|univalue/(lib|test)|zmq)/.*\\.cpp|node/blockstorage\\.cpp|node/utxo_snapshot\\.cpp|core_io\\.cpp|signet\\.cpp)"

It is assumed that this will be enforced for the entire codebase in the future.

@maflcko
Copy link
Member

maflcko commented Mar 4, 2026

Only change is in the last commit.

review ACK 9791771 💧

Show signature

Signature:

untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: review ACK 979177154a48388f1f771c65a135aca545099c75 💧
mcOxsGIg9Bf9IzlarH+8Z035ibkFUaV9qoTlMFanEmgSm+Zh42G/NGqvRYPOMReL6abMsbDLFDlkVqrojI57Aw==

@theuni
Copy link
Member

theuni commented Mar 4, 2026

I don't understand what makes that handful of .cpp files special? Why do only a few require a direct logging/categories.h include?

They are not special rather ones where IWYU warnings are treated as errors:

FILES_WITH_ENFORCED_IWYU="/src/((crypto|index|kernel|primitives|univalue/(lib|test)|zmq)/.*\\.cpp|node/blockstorage\\.cpp|node/utxo_snapshot\\.cpp|core_io\\.cpp|signet\\.cpp)"

It is assumed that this will be enforced for the entire codebase in the future.

Sorry, but this progression just doesn't make sense to me. As @maflcko said, the categories are needed any time a log macro is used. Using both includes everywhere (eventually) would be redundant and confusing.

It seems the original intent of logging/categories.h was to move them out of logging.h so that the kernel can use them without our logger impl. That makes sense.

But fundamentally, Category, Level, and SourceLocation are tied together.

util/log.h is the home of Level, and SourceLocation. It's also barebones and leaves out the implementation details of the logger.

So it makes sense to me to either:

  • just move LogFlags into there directly and be done with it
  • pragma export logging/categories.h from util/log.h

I don't see any harm in keeping the enum in a separate header for cleanliness, so I'd prefer the latter.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 9791771.

I agree with @theuni it could be a good idea to just document the export in the last commit 9791771 instead of removing it because right now the util/log.h header explicitly references BCLog::LogFlags::ALL, so it has a hard dependency on the categories.h include.

(We could break the util/log.h dependency on categories.h by defining Category as std::optional<uint64_t> instead of uint64_t and using nullopt to represent an unset category instead of BCLog::LogFlags::ALL. Or we could go the other direction and move the categories into util and drop the idea of having an opaque category field. @stickies-v introduced the opaque category field in 5b01eae from #34374 so I'm not actually sure about reasons it is opaque. But if seems like either the field should be opaque OR util/log.h should depend on the non-opaque enum, but not both.)

@hebasto hebasto force-pushed the 260220-iwyu-pragma branch from 9791771 to 6a27dcd Compare March 10, 2026 18:04
@hebasto
Copy link
Member Author

hebasto commented Mar 10, 2026

Since most reviewers agreed to export <logging/categories.h> from <util/log.h>, we are moving forward with this approach.

Let me know if you have a specific alternative in mind for the inline comment.

Copy link
Contributor

@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

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

ACK 6a27dcd

@DrahtBot DrahtBot requested review from maflcko and ryanofsky March 10, 2026 18:11
Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 6a27dcd, just keeping the log.h categories export and documenting it which makes sense for now.

As mentioned previously in longer term I think it'd make sense to either (1) drop the log.h dependency on categories.h if category is supposed to be opaque within util (easy to do with std::optiona) or (2) move categories into util and drop the idea that categories should be opaque. The current middle ground doesn't seem to make a lot of sense. The util library should either know about category values or not know about them. It shouldn't pretend to not know about them and also directly reference one of the values it doesn't know about.

@maflcko
Copy link
Member

maflcko commented Mar 10, 2026

Only change is the last commit, again

review ACK 6a27dcd 😌

Show signature

Signature:

untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: review ACK 6a27dcd99701aa3d776b837d400776129b53a29e 😌
kXDWNUlHQ6UOufO/FEtKNbnhJ8IbuIu1jnVaNlymzYsHtv8MlhVbfwdsai6rZx/jEUevrhTD0JHiIzrBBfxoCA==


// This header declares threading primitives compatible with Clang
// Thread Safety Analysis and provides appropriate annotation macros.
#include <threadsafety.h> // IWYU pragma: export
Copy link
Member

Choose a reason for hiding this comment

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

nit: I wonder if src/sync_unlogged.h should not be moved into src/util/sync_unlogged.h, because it seems like a low-level utility. Same for threadsafety.h. No need to re-touch here, but the move should be trivial, because the files are now basically only used in two places.

@hebasto
Copy link
Member Author

hebasto commented Mar 13, 2026

A commit updating Developer Notes has been added.

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.

7 participants