mirror of
https://github.com/esphome/esphome.git
synced 2026-09-24 13:34:07 +00:00
simplify approach
This commit is contained in:
+15
-15
@@ -519,43 +519,43 @@ def compile_program(args: ArgsProtocol, config: ConfigType) -> int:
|
||||
if rc != 0:
|
||||
return rc
|
||||
|
||||
# Check if firmware was rebuilt and emit buildinfo + create manifest
|
||||
_check_and_emit_buildinfo()
|
||||
# Check if firmware was rebuilt and emit build_info + create manifest
|
||||
_check_and_emit_build_info()
|
||||
|
||||
idedata = platformio_api.get_idedata(config)
|
||||
return 0 if idedata is not None else 1
|
||||
|
||||
|
||||
def _check_and_emit_buildinfo() -> None:
|
||||
"""Check if firmware was rebuilt and emit buildinfo."""
|
||||
def _check_and_emit_build_info() -> None:
|
||||
"""Check if firmware was rebuilt and emit build_info."""
|
||||
import json
|
||||
|
||||
firmware_path = CORE.firmware_bin
|
||||
buildinfo_json_path = CORE.relative_build_path("buildinfo.json")
|
||||
build_info_json_path = CORE.relative_build_path("build_info.json")
|
||||
|
||||
# Check if both files exist
|
||||
if not firmware_path.exists() or not buildinfo_json_path.exists():
|
||||
if not firmware_path.exists() or not build_info_json_path.exists():
|
||||
return
|
||||
|
||||
# Check if firmware is newer than buildinfo (indicating a relink occurred)
|
||||
if firmware_path.stat().st_mtime <= buildinfo_json_path.stat().st_mtime:
|
||||
# Check if firmware is newer than build_info (indicating a relink occurred)
|
||||
if firmware_path.stat().st_mtime <= build_info_json_path.stat().st_mtime:
|
||||
return
|
||||
|
||||
# Read buildinfo from JSON
|
||||
# Read build_info from JSON
|
||||
try:
|
||||
with open(buildinfo_json_path, encoding="utf-8") as f:
|
||||
buildinfo = json.load(f)
|
||||
with open(build_info_json_path, encoding="utf-8") as f:
|
||||
build_info = json.load(f)
|
||||
except (OSError, json.JSONDecodeError) as e:
|
||||
_LOGGER.debug("Failed to read buildinfo: %s", e)
|
||||
_LOGGER.debug("Failed to read build_info: %s", e)
|
||||
return
|
||||
|
||||
config_hash = buildinfo.get("config_hash")
|
||||
build_time = buildinfo.get("build_time")
|
||||
config_hash = build_info.get("config_hash")
|
||||
build_time = build_info.get("build_time")
|
||||
|
||||
if config_hash is None or build_time is None:
|
||||
return
|
||||
|
||||
# Emit buildinfo
|
||||
# Emit build_info
|
||||
_LOGGER.info(
|
||||
"Build Info: config_hash=0x%08x build_time=%s", config_hash, build_time
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#endif
|
||||
#include "esphome/components/network/util.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -1472,7 +1473,10 @@ bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) {
|
||||
|
||||
resp.set_esphome_version(ESPHOME_VERSION_REF);
|
||||
|
||||
resp.set_compilation_time(App.get_compilation_time_ref());
|
||||
// Stack buffer for build time string
|
||||
char build_time_str[BUILD_TIME_STR_SIZE];
|
||||
get_build_time_string(build_time_str);
|
||||
resp.set_compilation_time(StringRef(build_time_str));
|
||||
|
||||
// Manufacturer string - define once, handle ESP8266 PROGMEM separately
|
||||
#if defined(USE_ESP8266) || defined(USE_ESP32)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#ifdef USE_MQTT
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/version.h"
|
||||
@@ -154,7 +154,9 @@ bool MQTTComponent::send_discovery_() {
|
||||
device_info[MQTT_DEVICE_MANUFACTURER] =
|
||||
model == nullptr ? ESPHOME_PROJECT_NAME : std::string(ESPHOME_PROJECT_NAME, model - ESPHOME_PROJECT_NAME);
|
||||
#else
|
||||
device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_VERSION " (" + App.get_compilation_time_ref() + ")";
|
||||
char build_time_str[BUILD_TIME_STR_SIZE];
|
||||
get_build_time_string(build_time_str);
|
||||
device_info[MQTT_DEVICE_SW_VERSION] = str_sprintf(ESPHOME_VERSION " (%s)", build_time_str);
|
||||
device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD;
|
||||
#if defined(USE_ESP8266) || defined(USE_ESP32)
|
||||
device_info[MQTT_DEVICE_MANUFACTURER] = "Espressif";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "sen5x.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -154,10 +155,10 @@ void SEN5XComponent::setup() {
|
||||
if (this->voc_sensor_ && this->store_baseline_) {
|
||||
uint32_t combined_serial =
|
||||
encode_uint24(this->serial_number_[0], this->serial_number_[1], this->serial_number_[2]);
|
||||
// Hash with compilation time and serial number
|
||||
// Hash with build time and serial number
|
||||
// This ensures the baseline storage is cleared after OTA
|
||||
// Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict
|
||||
uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(combined_serial));
|
||||
uint32_t hash = static_cast<uint32_t>(get_build_time()) ^ combined_serial;
|
||||
this->pref_ = global_preferences->make_preference<Sen5xBaselines>(hash, true);
|
||||
|
||||
if (this->pref_.load(&this->voc_baselines_storage_)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "sgp30.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -72,10 +72,10 @@ void SGP30Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hash with compilation time and serial number
|
||||
// Hash with build time and serial number
|
||||
// This ensures the baseline storage is cleared after OTA
|
||||
// Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict
|
||||
uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(this->serial_number_));
|
||||
uint32_t hash = static_cast<uint32_t>(get_build_time()) ^ static_cast<uint32_t>(this->serial_number_);
|
||||
this->pref_ = global_preferences->make_preference<SGP30Baselines>(hash, true);
|
||||
|
||||
if (this->store_baseline_ && this->pref_.load(&this->baselines_storage_)) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "sgp4x.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include <cinttypes>
|
||||
@@ -56,10 +57,10 @@ void SGP4xComponent::setup() {
|
||||
ESP_LOGD(TAG, "Version 0x%0X", featureset);
|
||||
|
||||
if (this->store_baseline_) {
|
||||
// Hash with compilation time and serial number
|
||||
// Hash with build time and serial number
|
||||
// This ensures the baseline storage is cleared after OTA
|
||||
// Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict
|
||||
uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(this->serial_number_));
|
||||
uint32_t hash = static_cast<uint32_t>(get_build_time()) ^ static_cast<uint32_t>(this->serial_number_);
|
||||
this->pref_ = global_preferences->make_preference<SGP4xBaselines>(hash, true);
|
||||
|
||||
if (this->pref_.load(&this->voc_baselines_storage_)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "version_text_sensor.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/version.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
@@ -13,7 +13,9 @@ void VersionTextSensor::setup() {
|
||||
if (this->hide_timestamp_) {
|
||||
this->publish_state(ESPHOME_VERSION);
|
||||
} else {
|
||||
this->publish_state(str_sprintf(ESPHOME_VERSION " %s", App.get_compilation_time_ref().c_str()));
|
||||
char build_time_str[BUILD_TIME_STR_SIZE];
|
||||
get_build_time_string(build_time_str);
|
||||
this->publish_state(str_sprintf(ESPHOME_VERSION " %s", build_time_str));
|
||||
}
|
||||
}
|
||||
float VersionTextSensor::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifdef USE_WIFI
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
#include "esphome/core/build_info.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#if (ESP_IDF_VERSION_MAJOR >= 5 && ESP_IDF_VERSION_MINOR >= 1)
|
||||
@@ -360,7 +361,7 @@ void WiFiComponent::start() {
|
||||
get_mac_address_pretty_into_buffer(mac_s));
|
||||
this->last_connected_ = millis();
|
||||
|
||||
uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time_ref().c_str()) : 88491487UL;
|
||||
uint32_t hash = this->has_sta() ? static_cast<uint32_t>(get_build_time()) : 88491487UL;
|
||||
|
||||
this->pref_ = global_preferences->make_preference<wifi::SavedWifiSettings>(hash, true);
|
||||
#ifdef USE_WIFI_FAST_CONNECT
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/build_info.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/version.h"
|
||||
#include "esphome/core/hal.h"
|
||||
@@ -191,7 +192,9 @@ void Application::loop() {
|
||||
|
||||
if (this->dump_config_at_ < this->components_.size()) {
|
||||
if (this->dump_config_at_ == 0) {
|
||||
ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_);
|
||||
char build_time_str[BUILD_TIME_STR_SIZE];
|
||||
get_build_time_string(build_time_str);
|
||||
ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", build_time_str);
|
||||
#ifdef ESPHOME_PROJECT_NAME
|
||||
ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ static const uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for quick
|
||||
class Application {
|
||||
public:
|
||||
void pre_setup(const std::string &name, const std::string &friendly_name, const char *comment,
|
||||
const char *compilation_time, bool name_add_mac_suffix) {
|
||||
bool name_add_mac_suffix) {
|
||||
arch_init();
|
||||
this->name_add_mac_suffix_ = name_add_mac_suffix;
|
||||
if (name_add_mac_suffix) {
|
||||
@@ -121,7 +121,6 @@ class Application {
|
||||
this->friendly_name_ = friendly_name;
|
||||
}
|
||||
this->comment_ = comment;
|
||||
this->compilation_time_ = compilation_time;
|
||||
}
|
||||
|
||||
#ifdef USE_DEVICES
|
||||
@@ -261,10 +260,6 @@ class Application {
|
||||
|
||||
bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; }
|
||||
|
||||
std::string get_compilation_time() const { return this->compilation_time_; }
|
||||
/// Get the compilation time as StringRef (for API usage)
|
||||
StringRef get_compilation_time_ref() const { return StringRef(this->compilation_time_); }
|
||||
|
||||
/// Get the cached time in milliseconds from when the current component started its loop execution
|
||||
inline uint32_t IRAM_ATTR HOT get_loop_component_start_time() const { return this->loop_component_start_time_; }
|
||||
|
||||
@@ -478,7 +473,6 @@ class Application {
|
||||
// Pointer-sized members first
|
||||
Component *current_component_{nullptr};
|
||||
const char *comment_{nullptr};
|
||||
const char *compilation_time_{nullptr};
|
||||
|
||||
// std::vector (3 pointers each: begin, end, capacity)
|
||||
// Partitioned vector design for looping components
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "build_info.h"
|
||||
#include "build_info_data.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
|
||||
uint32_t get_config_hash() { return ESPHOME_CONFIG_HASH; }
|
||||
|
||||
time_t get_build_time() { return ESPHOME_BUILD_TIME; }
|
||||
|
||||
void get_build_time_string(std::span<char, BUILD_TIME_STR_SIZE> buffer) {
|
||||
#ifdef USE_ESP8266
|
||||
strncpy_P(buffer.data(), ESPHOME_BUILD_TIME_STR, buffer.size());
|
||||
#else
|
||||
strncpy(buffer.data(), ESPHOME_BUILD_TIME_STR, buffer.size());
|
||||
#endif
|
||||
buffer[buffer.size() - 1] = '\0';
|
||||
}
|
||||
|
||||
} // namespace esphome
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <span>
|
||||
|
||||
namespace esphome {
|
||||
|
||||
/// Size of buffer required for build time string (including null terminator)
|
||||
static constexpr size_t BUILD_TIME_STR_SIZE = 24;
|
||||
|
||||
/// Get the config hash as a 32-bit integer
|
||||
uint32_t get_config_hash();
|
||||
|
||||
/// Get the build time as a Unix timestamp
|
||||
time_t get_build_time();
|
||||
|
||||
/// Copy the build time string into the provided buffer
|
||||
/// Buffer must be BUILD_TIME_STR_SIZE bytes (compile-time enforced)
|
||||
void get_build_time_string(std::span<char, BUILD_TIME_STR_SIZE> buffer);
|
||||
|
||||
} // namespace esphome
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
// This file is not used by the runtime, instead, a version is generated during
|
||||
// compilation with the actual build info values.
|
||||
//
|
||||
// This file is only used by static analyzers and IDEs.
|
||||
|
||||
#define ESPHOME_CONFIG_HASH 0x12345678U
|
||||
#define ESPHOME_BUILD_TIME 1700000000
|
||||
static const char ESPHOME_BUILD_TIME_STR[] = "Jan 01 2024, 00:00:00";
|
||||
@@ -1,82 +0,0 @@
|
||||
#include <cstdint>
|
||||
|
||||
// Build information is passed in via symbols defined in a linker script
|
||||
// as that is the simplest way to include build timestamps without the
|
||||
// changed timestamp itself causing a rebuild through dependencies, as
|
||||
// it would if it were in a header file like version.h.
|
||||
//
|
||||
// It's passed in in *string* form so that it can go directly into the
|
||||
// flash as .rodata instead of using precious RAM to build a date string
|
||||
// from a time_t at runtime.
|
||||
//
|
||||
// Determining the target endianness and word size from the generation
|
||||
// side is problematic, so it emits *four* sets of symbols into the
|
||||
// linker script, for each of little-endian and big-endiand, 32-bit and
|
||||
// 64-bit targets.
|
||||
//
|
||||
// The LINKERSYM macro gymnastics select the correct symbol for the
|
||||
// target, named e.g. 'ESPHOME_BUILD_TIME_STR_32LE_0'.
|
||||
|
||||
// Not all targets have <endian.h> (e.g. LibreTiny on BK72xx).
|
||||
// Use the compiler built-in macros but defensively default to
|
||||
// little-endian and 32-bit.
|
||||
#if !defined(__BYTE_ORDER__) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define BO LE
|
||||
#else
|
||||
#define BO BE
|
||||
#endif
|
||||
|
||||
#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8
|
||||
#define WS 64 // NOLINT
|
||||
#else
|
||||
#define WS 32 // NOLINT
|
||||
#define USE_32BIT
|
||||
#endif
|
||||
|
||||
// If you have to ask, you don't want to know...
|
||||
#define LINKERSYM2(name, ws, bo, us, num) ESPHOME_##name##_##ws##bo##us##num
|
||||
#define LINKERSYM1(name, ws, bo, us, num) LINKERSYM2(name, ws, bo, us, num)
|
||||
#define LINKERSYM(name, num) LINKERSYM1(name, WS, BO, _, num)
|
||||
|
||||
extern "C" {
|
||||
extern const char ESPHOME_BUILD_TIME[];
|
||||
extern const char LINKERSYM(CONFIG_HASH_STR, 0)[];
|
||||
extern const char LINKERSYM(CONFIG_HASH_STR, 1)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 0)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 1)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 2)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 3)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 4)[];
|
||||
extern const char LINKERSYM(BUILD_TIME_STR, 5)[];
|
||||
}
|
||||
|
||||
namespace esphome::buildinfo {
|
||||
|
||||
// An 8-byte string plus terminating NUL.
|
||||
struct ConfigHashStruct {
|
||||
uintptr_t data0;
|
||||
#ifdef USE_32BIT
|
||||
uintptr_t data1;
|
||||
#endif
|
||||
char nul;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern const ConfigHashStruct CONFIG_HASH_STR = {(uintptr_t) &LINKERSYM(CONFIG_HASH_STR, 0),
|
||||
#ifdef USE_32BIT
|
||||
(uintptr_t) &LINKERSYM(CONFIG_HASH_STR, 1),
|
||||
#endif
|
||||
0};
|
||||
|
||||
// A 21-byte string plus terminating NUL, in 24 bytes
|
||||
extern const uintptr_t BUILD_TIME_STR[] = {
|
||||
(uintptr_t) &LINKERSYM(BUILD_TIME_STR, 0), (uintptr_t) &LINKERSYM(BUILD_TIME_STR, 1),
|
||||
(uintptr_t) &LINKERSYM(BUILD_TIME_STR, 2),
|
||||
#ifdef USE_32BIT
|
||||
(uintptr_t) &LINKERSYM(BUILD_TIME_STR, 3), (uintptr_t) &LINKERSYM(BUILD_TIME_STR, 4),
|
||||
(uintptr_t) &LINKERSYM(BUILD_TIME_STR, 5),
|
||||
#endif
|
||||
};
|
||||
|
||||
extern const uintptr_t BUILD_TIME = (uintptr_t) &ESPHOME_BUILD_TIME;
|
||||
|
||||
} // namespace esphome::buildinfo
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
|
||||
// Build information functions that provide config hash and build time.
|
||||
// The actual values are provided by linker-defined symbols to avoid
|
||||
// unnecessary rebuilds when only the build time changes.
|
||||
// This is kept in its own file so that only files that need build-specific
|
||||
// information have to include it explicitly.
|
||||
|
||||
namespace esphome::buildinfo {
|
||||
|
||||
extern const char CONFIG_HASH_STR[];
|
||||
extern const char BUILD_TIME_STR[];
|
||||
extern const uintptr_t BUILD_TIME;
|
||||
|
||||
static inline const char *get_config_hash() { return CONFIG_HASH_STR; }
|
||||
|
||||
static inline time_t get_build_time() { return (time_t) BUILD_TIME; }
|
||||
|
||||
static inline const char *get_build_time_string() { return BUILD_TIME_STR; }
|
||||
|
||||
} // namespace esphome::buildinfo
|
||||
@@ -1,2 +0,0 @@
|
||||
Import("env") # noqa: F821
|
||||
env.Append(LINKFLAGS=["buildinfo.ld"]) # noqa: F821
|
||||
@@ -501,7 +501,6 @@ async def to_code(config: ConfigType) -> None:
|
||||
config[CONF_NAME],
|
||||
config[CONF_FRIENDLY_NAME],
|
||||
config.get(CONF_COMMENT, ""),
|
||||
cg.RawExpression("esphome::buildinfo::get_build_time_string()"),
|
||||
config[CONF_NAME_ADD_MAC_SUFFIX],
|
||||
)
|
||||
)
|
||||
|
||||
+20
-73
@@ -7,7 +7,6 @@ from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import stat
|
||||
import struct
|
||||
import time
|
||||
from types import TracebackType
|
||||
|
||||
@@ -250,21 +249,16 @@ def copy_src_tree():
|
||||
write_file_if_changed(
|
||||
CORE.relative_src_path("esphome", "core", "version.h"), generate_version_h()
|
||||
)
|
||||
# Write buildinfo linker script, JSON metadata, and copy the PlatformIO script
|
||||
config_hash, build_time, build_time_str = get_buildinfo()
|
||||
write_file(
|
||||
CORE.relative_build_path("buildinfo.ld"),
|
||||
generate_buildinfo_ld(config_hash, build_time, build_time_str),
|
||||
# Write build_info header and JSON metadata
|
||||
config_hash, build_time, build_time_str = get_build_info()
|
||||
write_file_if_changed(
|
||||
CORE.relative_src_path("esphome", "core", "build_info_data.h"),
|
||||
generate_build_info_data_h(config_hash, build_time, build_time_str),
|
||||
)
|
||||
write_file(
|
||||
CORE.relative_build_path("buildinfo.json"),
|
||||
CORE.relative_build_path("build_info.json"),
|
||||
json.dumps({"config_hash": config_hash, "build_time": build_time}),
|
||||
)
|
||||
copy_file_if_changed(
|
||||
Path(__file__).parent / "core" / "buildinfo.py.script",
|
||||
CORE.relative_build_path("buildinfo.py"),
|
||||
)
|
||||
CORE.add_platformio_option("extra_scripts", ["pre:buildinfo.py"])
|
||||
|
||||
platform = "esphome.components." + CORE.target_platform
|
||||
try:
|
||||
@@ -290,33 +284,8 @@ def generate_version_h():
|
||||
)
|
||||
|
||||
|
||||
def _encode_string_symbols(
|
||||
text: str, prefix: str, bits: int, bit_suffix: str, endian: str, endian_suffix: str
|
||||
) -> list[str]:
|
||||
"""Encode a string as linker symbols for given word size and endianness."""
|
||||
symbols: list[str] = []
|
||||
# Pad to word boundary with NUL (build time strings need trailing NUL)
|
||||
padded = text if prefix == "CONFIG_HASH_STR" else text + "\0"
|
||||
while len(padded) % bits != 0:
|
||||
padded += "\0"
|
||||
|
||||
for i in range(0, len(padded), bits):
|
||||
chunk = padded[i : i + bits].encode("utf-8")
|
||||
if bits == 8:
|
||||
value = struct.unpack(endian + "Q", chunk)[0]
|
||||
symbols.append(
|
||||
f"ESPHOME_{prefix}_{bit_suffix}{endian_suffix}_{i // bits} = 0x{value:016x};"
|
||||
)
|
||||
else:
|
||||
value = struct.unpack(endian + "I", chunk)[0]
|
||||
symbols.append(
|
||||
f"ESPHOME_{prefix}_{bit_suffix}{endian_suffix}_{i // bits} = 0x{value:08x};"
|
||||
)
|
||||
return symbols
|
||||
|
||||
|
||||
def get_buildinfo() -> tuple[int, int, str]:
|
||||
"""Calculate buildinfo values from current config.
|
||||
def get_build_info() -> tuple[int, int, str]:
|
||||
"""Calculate build_info values from current config.
|
||||
|
||||
Returns:
|
||||
Tuple of (config_hash, build_time, build_time_str)
|
||||
@@ -331,42 +300,20 @@ def get_buildinfo() -> tuple[int, int, str]:
|
||||
return config_hash, build_time, build_time_str
|
||||
|
||||
|
||||
def generate_buildinfo_ld(
|
||||
def generate_build_info_data_h(
|
||||
config_hash: int, build_time: int, build_time_str: str
|
||||
) -> str:
|
||||
"""Generate buildinfo linker script with config hash and build time."""
|
||||
config_hash_str = f"{config_hash:08x}"
|
||||
|
||||
# Generate symbols for all 4 variants: 32LE, 32BE, 64LE, 64BE
|
||||
all_variants: list[str] = []
|
||||
|
||||
for bits, bit_suffix in [(4, "32"), (8, "64")]:
|
||||
for endian, endian_suffix in [("<", "LE"), (">", "BE")]:
|
||||
all_variants.extend(
|
||||
_encode_string_symbols(
|
||||
config_hash_str,
|
||||
"CONFIG_HASH_STR",
|
||||
bits,
|
||||
bit_suffix,
|
||||
endian,
|
||||
endian_suffix,
|
||||
)
|
||||
)
|
||||
all_variants.extend(
|
||||
_encode_string_symbols(
|
||||
build_time_str,
|
||||
"BUILD_TIME_STR",
|
||||
bits,
|
||||
bit_suffix,
|
||||
endian,
|
||||
endian_suffix,
|
||||
)
|
||||
)
|
||||
|
||||
return f"""/* Auto-generated buildinfo symbols */
|
||||
ESPHOME_BUILD_TIME = {build_time};
|
||||
ESPHOME_CONFIG_HASH = 0x{config_hash:08x};
|
||||
{chr(10).join(all_variants)}
|
||||
"""Generate build_info_data.h header with config hash and build time."""
|
||||
return f"""#pragma once
|
||||
// Auto-generated build_info data
|
||||
#define ESPHOME_CONFIG_HASH 0x{config_hash:08x}U
|
||||
#define ESPHOME_BUILD_TIME {build_time}
|
||||
#ifdef USE_ESP8266
|
||||
#include <pgmspace.h>
|
||||
static const char ESPHOME_BUILD_TIME_STR[] PROGMEM = "{build_time_str}";
|
||||
#else
|
||||
static const char ESPHOME_BUILD_TIME_STR[] = "{build_time_str}";
|
||||
#endif
|
||||
"""
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user