Process metadata only in metadata.cpp

Improves cache utilization as fewer things are passed via CFLAGS to
all files.  In the event that no metadata is available, let the cpp
file handle warning about default usage.
This commit is contained in:
Will Miles
2025-10-05 23:36:16 -04:00
parent a073bf32e4
commit 5ca10f35d1
6 changed files with 74 additions and 40 deletions

View File

@@ -1,5 +1,6 @@
Import('env')
import subprocess
import json
import re
def get_github_repo():
@@ -42,7 +43,7 @@ def get_github_repo():
# Check if it's a GitHub URL
if 'github.com' not in remote_url.lower():
return 'unknown'
return None
# Parse GitHub URL patterns:
# https://github.com/owner/repo.git
@@ -63,17 +64,56 @@ def get_github_repo():
if ssh_match:
return ssh_match.group(1)
return 'unknown'
return None
except FileNotFoundError:
# Git CLI is not installed or not in PATH
return 'unknown'
return None
except subprocess.CalledProcessError:
# Git command failed (e.g., not a git repo, no remote, etc.)
return 'unknown'
return None
except Exception:
# Any other unexpected error
return 'unknown'
return None
repo = get_github_repo()
env.Append(BUILD_FLAGS=[f'-DWLED_REPO=\\"{repo}\\"'])
PACKAGE_FILE = "package.json"
def get_version():
with open(PACKAGE_FILE, "r") as package:
return json.load(package)["version"]
return None
def has_def(cppdefs, name):
""" Returns true if a given name is set in a CPPDEFINES collection """
for f in cppdefs:
if isinstance(f, tuple):
f = f[0]
if f == name:
return True
return False
def add_wled_metadata_flags(env, node):
cdefs = env["CPPDEFINES"].copy()
if not has_def(cdefs, "WLED_REPO"):
repo = get_github_repo()
if repo:
cdefs.append(("WLED_REPO", f"\\\"{repo}\\\""))
if not has_def(cdefs, "WLED_VERSION"):
version = get_version()
if version:
cdefs.append(("WLED_VERSION", get_version()))
# This transforms the node in to a Builder; it cannot be modified again
return env.Object(
node,
CPPDEFINES=cdefs
)
env.AddBuildMiddleware(
add_wled_metadata_flags,
"*/wled_metadata.cpp"
)

View File

@@ -1,8 +0,0 @@
Import('env')
import json
PACKAGE_FILE = "package.json"
with open(PACKAGE_FILE, "r") as package:
version = json.load(package)["version"]
env.Append(BUILD_FLAGS=[f"-DWLED_VERSION={version}"])

View File

@@ -110,8 +110,7 @@ ldscript_4m1m = eagle.flash.4m1m.ld
[scripts_defaults]
extra_scripts =
pre:pio-scripts/set_version.py
pre:pio-scripts/set_repo.py
pre:pio-scripts/set_metadata.py
post:pio-scripts/output_bins.py
post:pio-scripts/strip-floats.py
pre:pio-scripts/user_config_copy.py

View File

@@ -33,7 +33,7 @@ static bool validateOTA(const uint8_t* binaryData, size_t dataSize, char* errorM
}
// Try to extract WLED structure directly from binary data
wled_custom_desc_t extractedDesc;
wled_metadata_t extractedDesc;
bool hasDesc = findWledMetadata(binaryData, dataSize, &extractedDesc);
if (hasDesc) {

View File

@@ -1,6 +1,19 @@
#include "ota_update.h"
#include "wled.h"
#ifndef WLED_VERSION
#warning WLED_VERSION was not set - using default value of 'dev'
#define WLED_VERSION dev
#endif
#ifndef WLED_RELEASE_NAME
#warning WLED_RELEASE_NAME was not set - using default value of 'Custom'
#define WLED_RELEASE_NAME "Custom"
#endif
#ifndef WLED_REPO
// No warning for this one: integrators are not always on GitHub
#define WLED_REPO "unknown"
#endif
#define WLED_CUSTOM_DESC_MAGIC 0x57535453 // "WSTS" (WLED System Tag Structure)
#define WLED_CUSTOM_DESC_VERSION 1
#define WLED_RELEASE_NAME_MAX_LEN 48
@@ -40,7 +53,7 @@ inline uint32_t djb2_hash_runtime(const char* str) {
// GLOBAL VARIABLES
// ------------------------------------
// Structure instantiation for this build
const wled_custom_desc_t __attribute__((section(BUILD_METADATA_SECTION))) WLED_BUILD_DESCRIPTION = {
const wled_metadata_t __attribute__((section(BUILD_METADATA_SECTION))) WLED_BUILD_DESCRIPTION = {
WLED_CUSTOM_DESC_MAGIC, // magic
WLED_CUSTOM_DESC_VERSION, // version
TOSTRING(WLED_VERSION),
@@ -66,20 +79,20 @@ const __FlashStringHelper* brandString = FPSTR(brandString_s);
* @param extractedDesc Buffer to store extracted custom description structure
* @return true if structure was found and extracted, false otherwise
*/
bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_custom_desc_t* extractedDesc) {
if (!binaryData || !extractedDesc || dataSize < sizeof(wled_custom_desc_t)) {
bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_metadata_t* extractedDesc) {
if (!binaryData || !extractedDesc || dataSize < sizeof(wled_metadata_t)) {
return false;
}
for (size_t offset = 0; offset <= dataSize - sizeof(wled_custom_desc_t); offset++) {
const wled_custom_desc_t* custom_desc = (const wled_custom_desc_t*)(binaryData + offset);
for (size_t offset = 0; offset <= dataSize - sizeof(wled_metadata_t); offset++) {
const wled_metadata_t* custom_desc = (const wled_metadata_t*)(binaryData + offset);
// Check for magic number
if (custom_desc->magic == WLED_CUSTOM_DESC_MAGIC) {
// Found potential match, validate version
if (custom_desc->desc_version != WLED_CUSTOM_DESC_VERSION) {
DEBUG_PRINTF_P(PSTR("Found WLED structure at offset %u but version mismatch: %u\n"),
offset, custom_desc->version);
offset, custom_desc->desc_version);
continue;
}
@@ -91,7 +104,7 @@ bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_custom_de
}
// Valid structure found - copy entire structure
memcpy(extractedDesc, custom_desc, sizeof(wled_custom_desc_t));
memcpy(extractedDesc, custom_desc, sizeof(wled_metadata_t));
DEBUG_PRINTF_P(PSTR("Extracted WLED structure at offset %u: '%s'\n"),
offset, extractedDesc->release_name);
@@ -113,7 +126,7 @@ bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_custom_de
* @return true if OTA should proceed, false if it should be blocked
*/
bool shouldAllowOTA(const wled_custom_desc_t& firmwareDescription, char* errorMessage, size_t errorMessageLen) {
bool shouldAllowOTA(const wled_metadata_t& firmwareDescription, char* errorMessage, size_t errorMessageLen) {
// Clear error message
if (errorMessage && errorMessageLen > 0) {
errorMessage[0] = '\0';

View File

@@ -11,16 +11,6 @@
#include <string.h>
#include <WString.h>
#ifndef WLED_VERSION
#define WLED_VERSION dev
#endif
#ifndef WLED_RELEASE_NAME
#define WLED_RELEASE_NAME "Custom"
#endif
#ifndef WLED_REPO
#define WLED_REPO "unknown"
#endif
#define WLED_VERSION_MAX_LEN 48
#define WLED_RELEASE_NAME_MAX_LEN 48
@@ -36,11 +26,11 @@ typedef struct {
char wled_version[WLED_VERSION_MAX_LEN];
char release_name[WLED_RELEASE_NAME_MAX_LEN]; // Release name (null-terminated)
uint32_t hash; // Structure sanity check
} __attribute__((packed)) wled_custom_desc_t;
} __attribute__((packed)) wled_metadata_t;
// Global build description
extern const wled_custom_desc_t WLED_BUILD_DESCRIPTION;
extern const wled_metadata_t WLED_BUILD_DESCRIPTION;
// Convenient metdata pointers
#define versionString (WLED_BUILD_DESCRIPTION.wled_version) // Build version, WLED_VERSION
@@ -59,7 +49,7 @@ extern const __FlashStringHelper* brandString ; // Brand
* @param extractedDesc Buffer to store extracted custom description structure
* @return true if structure was found and extracted, false otherwise
*/
bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_custom_desc_t* extractedDesc);
bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_metadata_t* extractedDesc);
/**
* Check if OTA should be allowed based on release compatibility
@@ -68,4 +58,4 @@ bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_custom_de
* @param errorMessageLen Maximum length of error message buffer
* @return true if OTA should proceed, false if it should be blocked
*/
bool shouldAllowOTA(const wled_custom_desc_t& firmwareDescription, char* errorMessage, size_t errorMessageLen);
bool shouldAllowOTA(const wled_metadata_t& firmwareDescription, char* errorMessage, size_t errorMessageLen);