8000
Skip to content

[api] Fix missing ifdef guards for field_ifdef fields in protobuf base classes - #9693

Merged
jesserockz merged 2 commits into
devfrom
missing_ifdef_member_vars
Jul 20, 2025
Merged

[api] Fix missing ifdef guards for field_ifdef fields in protobuf base classes#9693
jesserockz merged 2 commits into
devfrom
missing_ifdef_member_vars

Conversation

@bdraco
@bdraco bdraco commented Jul 18, 2025
Copy link
Copy Markdown
Member

Not for backport. can wait for 2025.8.x as it just uses more memory than needed but not a lot.

What does this implement/fix?

This PR fixes the protobuf code generation script to properly wrap fields with their corresponding ifdef guards in base classes. Previously, fields marked with field_ifdef options in the proto file (such as [(field_ifdef) = "USE_DEVICES"] for device_id and [(field_ifdef) = "USE_ENTITY_ICON"] for icon) were not getting ifdef guards when they appeared in generated base classes like InfoResponseProtoMessage, StateResponseProtoMessage, and CommandProtoMessage.

The fix ensures that when common fields are extracted into base classes, their field_ifdef options are preserved if all derived classes have the same ifdef value.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Code quality improvements to existing code or addition of tests
  • Other

Related issue or feature (if applicable):

  • Reduces memory usage by properly excluding optional fields when their corresponding features are not defined

Pull request in esphome-docs with documentation (if applicable):

  • N/A (internal code generation change)

Test Environment

  • ESP32
  • ESP32 IDF
  • ESP8266
  • RP2040
  • BK72xx
  • RTL87xx
  • nRF52840

Example entry for config.yaml:

# No configuration changes needed - this is an internal code generation fix

Checklist:

  • The code change is tested and works locally.
  • Tests have been added to verify that the new 8000 code works (under tests/ folder).

If user exposed functionality or configuration variables are added/changed:

Additional details

The change includes two fixes:

  1. Protobuf generation fix: Adds a get_common_field_ifdef() helper function that checks if all messages sharing a common field have the same field_ifdef option. If they do, the base class field declaration is wrapped with the appropriate ifdef guard.

  2. API connection fix: Wraps the icon field access in api_connection.h with #ifdef USE_ENTITY_ICON to match the generated protobuf headers.

This reduces memory usage by excluding fields when their features are disabled:

  • device_id field (4 bytes + padding) when USE_DEVICES is not defined
  • icon field (string object overhead) when USE_ENTITY_ICON is not defined

This is particularly important for memory-constrained devices where every byte counts.

@github-actions
Copy link
Copy Markdown
Contributor

To use the changes from this PR as an external component, add the following to your ESPHome configuration YAML file:

external_components:
  - source: github://pr#9693
    components: [api]
    refresh: 1h

(Added by the PR bot)

@codecov-commenter
codecov-commenter commented Jul 18, 2025
Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 59.94%. Comparing base (60350e8) to head (8593da7).
Report is 3 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev    #9693   +/-   ##
=======================================
  Coverage   59.94%   59.94%           
=======================================
  Files          50       50           
  Lines   
8000
    10293    10293           
  Branches     1381     1381           
=======================================
  Hits         6170     6170           
  Misses       3762     3762           
  Partials      361      361           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bdraco
bdraco commented Jul 18, 2025
Copy link
Copy Markdown
Member Author

Also for a followup, we still generate

class AreaInfo : public ProtoMessage {
 public:
  uint32_t area_id{0};
  std::string name{};
  void encode(ProtoWriteBuffer buffer) const override;
  void calculate_size(uint32_t &total_size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
  void dump_to(std::string &out) const override;
#endif

 protected:
};

But it should have an ifdef

I can't fix it without conflicting with other PRs though so I'll leave it for later

@bdraco
bdraco marked this pull request as ready for review July 18, 2025 23:10
Copilot AI review requested due to automatic review settings July 18, 2025 23:10
@bdraco
bdraco requested a review from OttoWinter as a code owner July 18, 2025 23:10
@github-actions
Copy link
Copy Markdown
Contributor

👋 Hi there! I've automatically requested reviews from codeowners based on the files changed in this PR.

@OttoWinter - You've been requested to review this PR as codeowner(s) of 2 file(s) that were modified. Thanks for your time! 🙏

Copilot AI 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.

Pull Request Overview

This PR fixes the protobuf code generation script to properly wrap fields with ifdef guards when they are extracted into base classes. Previously, fields marked with field_ifdef options (like USE_DEVICES for device_id and USE_ENTITY_ICON for icon) were losing their conditional compilation guards when moved to generated base classes.

  • Adds a helper function to detect consistent field_ifdef options across messages sharing common fields
  • Updates base class generation to preserve ifdef guards for fields when all derived classes agree on the same ifdef condition
  • Fixes API connection code to properly wrap icon field access with the corresponding ifdef guard

Reviewed Changes

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

File Description
script/api_protobuf/api_protobuf.py Adds logic to preserve field_ifdef guards in generated base classes
esphome/components/api/api_pb2.h Generated protobuf headers with proper ifdef guards around conditional fields
esphome/components/api/api_connection.h Wraps icon field access with USE_ENTITY_ICON ifdef guard

Comment thread script/api_protobuf/api_protobuf.py
Comment thread script/api_protobuf/api_protobuf.py
@jesserockz
jesserockz merged commit 5b3d61b into dev Jul 20, 2025
35 checks passed
@jesserockz
jesserockz deleted the missing_ifdef_member_vars branch July 20, 2025 03:41
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 22, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

0