Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions lib/AppVersion/AppVersion.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
#pragma once

// Build identity. The version, commit and dirty flag change with every commit,
// so scripts/git_branch.py defines them only for src/util/BuildInfo.cpp, which
// implements these accessors. A global define would change every compile
// command and force a full rebuild after each commit.
namespace AppVersion {
const char* version(); // e.g. "1.6.0-x4-pro"
const char* versionLabel(); // "CrossInk <version>"
const char* userAgent(); // "CrossInk-ESP32-<version>"
const char* gitSha(); // short commit hash, or "unknown"
bool gitDirty(); // tracked files were modified when built
const char* gitDirtyFlag(); // "1", "0" or "unknown"
} // namespace AppVersion

// PlatformIO normally supplies these through build_flags/extra_scripts. Keep
// fallbacks here so editor indexers and simulator-like tools still parse files.
#ifndef CROSSINK_VERSION
#define CROSSINK_VERSION "dev"
#endif

#ifndef CROSSINK_GIT_SHA
#define CROSSINK_GIT_SHA "unknown"
#endif

#ifndef CROSSINK_GIT_DIRTY
#define CROSSINK_GIT_DIRTY "unknown"
#endif

#ifndef CROSSINK_PIOENV
#define CROSSINK_PIOENV "unknown"
#endif
Expand Down
3 changes: 2 additions & 1 deletion lib/hal/HalSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ std::string getPanicInfo(bool full) {
} else {
std::string info;

info += "CrossInk version: " CROSSINK_VERSION;
info += "CrossInk version: ";
info += AppVersion::version();
info += "\nCrossInk device type: " CROSSINK_FIRMWARE_DEVICE_TYPE;
char elfSha[65] = {};
esp_app_get_elf_sha256(elfSha, sizeof(elfSha));
Expand Down
42 changes: 22 additions & 20 deletions scripts/git_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ def short_branch_label(branch):
return branch.rsplit('/', 1)[-1] or 'unknown'


def register_build_info(env, project_dir):
# The build time changes on every build. Defining it globally would change
# every compile command and force a full rebuild, so scope these defines to
# the one small file that exposes them.
def register_build_info(env, project_dir, scoped_defines):
# The build time changes on every build, and the commit, dirty flag and
# (in test builds) the version change on every commit. Defining them
# globally would change every compile command and force a full rebuild,
# so scope them to the one small file that exposes them.
branch = run_git_value(
project_dir, ['rev-parse', '--abbrev-ref', 'HEAD'], 'branch'
)
Expand All @@ -139,6 +140,7 @@ def register_build_info(env, project_dir):
('CROSSINK_GIT_BRANCH_SHORT', f'\\"{short_branch_label(branch)}\\"'),
('CROSSINK_BUILD_NUMBER', f'\\"{get_build_number(project_dir)}\\"'),
('CROSSINK_BUILD_TIME', f'\\"{build_time}\\"'),
*scoped_defines,
]

def add_build_info_defines(node_env, node):
Expand Down Expand Up @@ -220,14 +222,13 @@ def inject_version(env):
# Keep build provenance separate from CROSSINK_VERSION: production versions
# intentionally omit the source revision, while diagnostics need the base
# commit and whether the compiled tree had tracked modifications.
env.Append(CPPDEFINES=[
# Values that change per commit go only to src/util/BuildInfo.cpp (see
# register_build_info); stable values stay global.
scoped = [
('CROSSINK_GIT_SHA', f'\\"{get_git_short_sha(project_dir)}\\"'),
('CROSSINK_GIT_DIRTY', f'\\"{get_git_dirty(project_dir)}\\"'),
('CROSSINK_PIOENV', f'\\"{pioenv}\\"'),
])

if hasattr(env, 'AddBuildMiddleware'):
register_build_info(env, project_dir)
]
env.Append(CPPDEFINES=[('CROSSINK_PIOENV', f'\\"{pioenv}\\"')])

if pioenv in {'default', 'sticky', 'x4-pro', 'x4-pro-light-sleep', 'x4-classic'}:
version_string = get_hardware_version(project_dir, pioenv)
Expand All @@ -237,15 +238,15 @@ def inject_version(env):
print(f'CrossInk production build version: {version_string}')
else:
print(f'CrossInk build version: {version_string}')
env.Append(CPPDEFINES=[('CROSSINK_VERSION', f'\\"{version_string}\\"')])
scoped.append(('CROSSINK_VERSION', f'\\"{version_string}\\"'))

elif pioenv == 'debug':
branch = get_git_branch(project_dir)
short_hash = get_git_short_hash(project_dir)
ci_version = get_crossink_version(project_dir)
suffix = f'-{branch}+{short_hash}'
scoped.append(('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'))
env.Append(CPPDEFINES=[
('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'),
('CROSSINK_BUILD_ENV', '\\"debug\\"'),
'CROSSINK_SHOW_SLEEP_BUILD_INFO',
])
Expand All @@ -256,8 +257,8 @@ def inject_version(env):
short_hash = get_git_short_hash(project_dir)
ci_version = get_crossink_version(project_dir)
suffix = f'-{branch}+{short_hash}'
scoped.append(('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'))
env.Append(CPPDEFINES=[
('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'),
('CROSSINK_BUILD_ENV', '\\"debug\\"'),
'CROSSINK_SHOW_SLEEP_BUILD_INFO',
])
Expand All @@ -268,8 +269,8 @@ def inject_version(env):
short_hash = get_git_short_hash(project_dir)
ci_version = get_crossink_version(project_dir)
suffix = f'-{branch}+{short_hash}'
scoped.append(('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'))
env.Append(CPPDEFINES=[
('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'),
('CROSSINK_BUILD_ENV', '\\"debug\\"'),
'CROSSINK_SHOW_SLEEP_BUILD_INFO',
])
Expand All @@ -280,19 +281,20 @@ def inject_version(env):
short_hash = get_git_short_hash(project_dir)
ci_version = get_crossink_version(project_dir)
suffix = f'-{branch}+{short_hash}'
env.Append(CPPDEFINES=[
('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'),
])
scoped.append(('CROSSINK_VERSION', f'\\"{ci_version}{suffix}\\"'))
print(f'CrossInk test build version: {ci_version}{suffix}')

elif pioenv == 'gh_release_rc':
# CI passes CROSSINK_RC_HASH as an env var; locally we derive it from git.
version_string = get_release_candidate_version(project_dir)
env.Append(CPPDEFINES=[
('CROSSINK_VERSION', f'\\"{version_string}\\"'),
])
scoped.append(('CROSSINK_VERSION', f'\\"{version_string}\\"'))
print(f'CrossInk RC build version: {version_string}')

if hasattr(env, 'AddBuildMiddleware'):
register_build_info(env, project_dir, scoped)
else:
env.Append(CPPDEFINES=scoped)


# PlatformIO/SCons entry point — Import and env are SCons builtins injected at runtime.
# When run directly with Python (e.g. for validation), a lightweight fake env is used
Expand Down
2 changes: 1 addition & 1 deletion src/activities/boot_sleep/BootActivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void drawDefaultBootLogo(const GfxRenderer& renderer) {
renderer.drawImage(Logo120, (pageWidth - 120) / 2, (pageHeight - 120) / 2, 120, 120);
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, tr(STR_CROSSINK), true, EpdFontFamily::BOLD);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, tr(STR_BOOTING));
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSINK_VERSION);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, AppVersion::version());
}

} // namespace
Expand Down
2 changes: 1 addition & 1 deletion src/activities/boot_sleep/SleepActivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ void SleepActivity::renderDefaultSleepScreen() const {
}

#ifdef CROSSINK_SHOW_SLEEP_BUILD_INFO
const std::string buildInfo = std::string(CROSSINK_BUILD_ENV) + " " + CROSSINK_VERSION;
const std::string buildInfo = std::string(CROSSINK_BUILD_ENV) + " " + AppVersion::version();
const std::string visibleBuildInfo =
renderer.truncatedText(SMALL_FONT_ID, buildInfo.c_str(), pageWidth - sleepBuildInfoSideMargin * 2);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 118, visibleBuildInfo.c_str(), lightSleepScreen);
Expand Down
2 changes: 1 addition & 1 deletion src/activities/settings/OtaUpdateActivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void OtaUpdateActivity::render(RenderLock&&) {
} else if (state == WAITING_CONFIRMATION) {
renderer.drawCenteredText(UI_10_FONT_ID, top, tr(STR_NEW_UPDATE), true, EpdFontFamily::BOLD);
renderer.drawText(UI_10_FONT_ID, metrics.contentSidePadding, top + height + metrics.verticalSpacing,
(std::string(tr(STR_CURRENT_VERSION)) + CROSSINK_VERSION).c_str());
(std::string(tr(STR_CURRENT_VERSION)) + AppVersion::version()).c_str());
renderer.drawText(UI_10_FONT_ID, metrics.contentSidePadding, top + height * 2 + metrics.verticalSpacing * 2,
(std::string(tr(STR_NEW_VERSION)) + updater.getLatestVersion()).c_str());

Expand Down
10 changes: 4 additions & 6 deletions src/activities/settings/SettingsActivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,18 @@ std::string formatCompactDuration(const uint32_t seconds) {
return buf;
}

constexpr const char* systemVersionLabel = "CrossInk " CROSSINK_VERSION;

// Space below the settings list for the System footer: the build details line
// plus the version on one line, or two when it has to wrap.
int systemVersionFooterReserve(const GfxRenderer& renderer, const int pageWidth, const ThemeMetrics& metrics) {
const int maxWidth = pageWidth - systemVersionFooterSideMargin * 2;
const int versionLines = renderer.getTextWidth(SMALL_FONT_ID, systemVersionLabel) <= maxWidth ? 1 : 2;
const int versionLines = renderer.getTextWidth(SMALL_FONT_ID, AppVersion::versionLabel()) <= maxWidth ? 1 : 2;
return metrics.verticalSpacing + systemVersionFooterBottomInset +
versionLines * renderer.getLineHeight(SMALL_FONT_ID);
}

void drawSystemVersionFooter(const GfxRenderer& renderer, const int pageWidth, const int pageHeight,
const ThemeMetrics& metrics) {
const std::string label = systemVersionLabel;
const std::string label = AppVersion::versionLabel();
const int maxWidth = pageWidth - systemVersionFooterSideMargin * 2;
const int lineHeight = renderer.getLineHeight(SMALL_FONT_ID);
const int detailsLineY =
Expand All @@ -171,8 +169,8 @@ void drawSystemVersionFooter(const GfxRenderer& renderer, const int pageWidth, c

// Short branch and commit; "*" marks uncommitted changes.
char details[64];
snprintf(details, sizeof(details), "%s %s%s", BuildInfo::shortBranch(), CROSSINK_GIT_SHA,
strcmp(CROSSINK_GIT_DIRTY, "1") == 0 ? "*" : "");
snprintf(details, sizeof(details), "%s %s%s", BuildInfo::shortBranch(), AppVersion::gitSha(),
AppVersion::gitDirty() ? "*" : "");
drawCenteredTextLine(renderer, pageWidth, detailsLineY, renderer.truncatedText(SMALL_FONT_ID, details, maxWidth));

if (renderer.getTextWidth(SMALL_FONT_ID, label.c_str()) <= maxWidth) {
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1366,7 +1366,7 @@ void setup() {
(BoardConfig::isX4Pro() || CROSSINK_APP_DEVICE_X4CLASSIC) ? "DOWN" : "UP");
}

LOG_DBG("MAIN", "Starting CrossInk version " CROSSINK_VERSION);
LOG_DBG("MAIN", "Starting CrossInk version %s", AppVersion::version());
logMemoryStats("Boot");

// Resolve the single boot-presentation decision. Skipping the splash also
Expand Down
6 changes: 3 additions & 3 deletions src/network/CrossPointWebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ void CrossPointWebServer::handleStatus() const {
const String ipAddr = apMode ? WiFi.softAPIP().toString() : WiFi.localIP().toString();

JsonDocument doc;
doc["version"] = CROSSINK_VERSION;
doc["version"] = AppVersion::version();
doc["ip"] = ipAddr;
doc["mode"] = apMode ? "AP" : "STA";
doc["rssi"] = apMode ? 0 : WiFi.RSSI();
Expand Down Expand Up @@ -784,8 +784,8 @@ void CrossPointWebServer::handleStatus() const {
// touches the SD card beyond the capacity cached at mount.
JsonObject build = doc["build"].to<JsonObject>();
build["env"] = CROSSINK_PIOENV;
build["gitSha"] = CROSSINK_GIT_SHA;
build["gitDirty"] = CROSSINK_GIT_DIRTY;
build["gitSha"] = AppVersion::gitSha();
build["gitDirty"] = AppVersion::gitDirtyFlag();
build["gitBranch"] = BuildInfo::gitBranch();
build["buildNumber"] = BuildInfo::buildNumber();
build["buildTime"] = BuildInfo::buildTime();
Expand Down
4 changes: 2 additions & 2 deletions src/network/HttpDownloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct Sink {

void setRequestHeaders(esp_http_client_handle_t client, const std::string& username, const std::string& password,
size_t resumeOffset, bool sendAuthorization) {
esp_http_client_set_header(client, "User-Agent", "CrossInk-ESP32-" CROSSINK_VERSION);
esp_http_client_set_header(client, "User-Agent", AppVersion::userAgent());
esp_http_client_set_header(client, "Connection", "close");
if (resumeOffset > 0) {
char rangeHeader[40];
Expand Down Expand Up @@ -159,7 +159,7 @@ HttpDownloader::DownloadError runGetWolfSsl(const std::string& url, const std::s
}
// Replace SecureHttpClient's built-in User-Agent so strict servers receive
// exactly one header while retaining CrossInk's device/version identity.
http.setUserAgent("CrossInk-ESP32-" CROSSINK_VERSION);
http.setUserAgent(AppVersion::userAgent());
if (sink.resumeOffset > 0) {
char rangeHeader[40];
snprintf(rangeHeader, sizeof(rangeHeader), "bytes=%zu-", sink.resumeOffset);
Expand Down
10 changes: 5 additions & 5 deletions src/network/OtaUpdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,15 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
};

totalBytesReceived = 0;
LOG_DBG("OTA", "Checking for update (current: %s)", CROSSINK_VERSION);
LOG_DBG("OTA", "Checking for update (current: %s)", AppVersion::version());

esp_http_client_handle_t client_handle = esp_http_client_init(&client_config);
if (!client_handle) {
LOG_ERR("OTA", "HTTP Client Handle Failed");
return INTERNAL_UPDATE_ERROR;
}

esp_err = esp_http_client_set_header(client_handle, "User-Agent", "CrossInk-ESP32-" CROSSINK_VERSION);
esp_err = esp_http_client_set_header(client_handle, "User-Agent", AppVersion::userAgent());
if (esp_err != ESP_OK) {
LOG_ERR("OTA", "esp_http_client_set_header Failed : %s", esp_err_to_name(esp_err));
esp_http_client_cleanup(client_handle);
Expand Down Expand Up @@ -356,12 +356,12 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
}

bool OtaUpdater::isUpdateNewer() const {
if (!updateAvailable || latestVersion.empty() || latestVersion == CROSSINK_VERSION) {
if (!updateAvailable || latestVersion.empty() || latestVersion == AppVersion::version()) {
return false;
}

const int comparison = compareVersions(latestVersion.c_str(), CROSSINK_VERSION);
LOG_DBG("OTA", "Version comparison latest=%s current=%s result=%d", latestVersion.c_str(), CROSSINK_VERSION,
const int comparison = compareVersions(latestVersion.c_str(), AppVersion::version());
LOG_DBG("OTA", "Version comparison latest=%s current=%s result=%d", latestVersion.c_str(), AppVersion::version(),
comparison);
return comparison > 0;
}
Expand Down
6 changes: 2 additions & 4 deletions src/network/UsbSerialFileTransfer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "UsbSerialFileTransfer.h"

#include <AppVersion.h>
#include <Arduino.h>
#include <FsHelpers.h>
#include <HalStorage.h>
Expand Down Expand Up @@ -45,9 +46,6 @@ constexpr const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
#ifndef CROSSINK_FIRMWARE_DEVICE_TYPE
#define CROSSINK_FIRMWARE_DEVICE_TYPE "unknown"
#endif
#ifndef CROSSINK_VERSION
#define CROSSINK_VERSION "unknown"
#endif

uint8_t commandMatchPos = 0;
char lineBuffer[LINE_BUFFER_SIZE] = {};
Expand Down Expand Up @@ -308,7 +306,7 @@ bool removeRecursive(const char* path, size_t depth = 0) {
void handleStatus() {
char response[160];
snprintf(response, sizeof(response), "STATUS:protocol=1,device=%s,firmware=%s,free=%u,largest=%u\n",
CROSSINK_FIRMWARE_DEVICE_TYPE, CROSSINK_VERSION, ESP.getFreeHeap(), ESP.getMaxAllocHeap());
CROSSINK_FIRMWARE_DEVICE_TYPE, AppVersion::version(), ESP.getFreeHeap(), ESP.getMaxAllocHeap());
writeLine(response);
}

Expand Down
4 changes: 2 additions & 2 deletions src/util/BatteryDiagnosticLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,12 @@ void record(const Event event, const char* const deviceName, const char* const w
formatOptional(soc, sizeof(soc), battery.socKnown, battery.soc);
formatOptional(millivolts, sizeof(millivolts), battery.millivoltsKnown, battery.millivolts);
formatOptional(charging, sizeof(charging), battery.chargingKnown, battery.charging ? 1u : 0u);
formatText(version, sizeof(version), CROSSINK_VERSION);
formatText(version, sizeof(version), AppVersion::version());

char row[ROW_LEN];
const int rowLen =
snprintf(row, sizeof(row), "%s,%lu,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", timestamp, static_cast<unsigned long>(millis()),
soc, millivolts, charging, eventName(event), version, CROSSINK_GIT_SHA, CROSSINK_GIT_DIRTY,
soc, millivolts, charging, eventName(event), version, AppVersion::gitSha(), AppVersion::gitDirtyFlag(),
deviceName ? deviceName : "", wakeRoute ? wakeRoute : "");
if (rowLen <= 0 || static_cast<size_t>(rowLen) >= sizeof(row)) {
file.close();
Expand Down
25 changes: 25 additions & 0 deletions src/util/BuildInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
#include "BuildInfo.h"

#include <AppVersion.h>

#include <cstring>

#ifndef CROSSINK_VERSION
#define CROSSINK_VERSION "dev"
#endif

#ifndef CROSSINK_GIT_SHA
#define CROSSINK_GIT_SHA "unknown"
#endif

#ifndef CROSSINK_GIT_DIRTY
#define CROSSINK_GIT_DIRTY "unknown"
#endif

#ifndef CROSSINK_GIT_BRANCH
#define CROSSINK_GIT_BRANCH "unknown"
#endif
Expand All @@ -22,3 +38,12 @@ const char* shortBranch() { return CROSSINK_GIT_BRANCH_SHORT; }
const char* buildNumber() { return CROSSINK_BUILD_NUMBER; }
const char* buildTime() { return CROSSINK_BUILD_TIME; }
} // namespace BuildInfo

namespace AppVersion {
const char* version() { return CROSSINK_VERSION; }
const char* versionLabel() { return "CrossInk " CROSSINK_VERSION; }
const char* userAgent() { return "CrossInk-ESP32-" CROSSINK_VERSION; }
const char* gitSha() { return CROSSINK_GIT_SHA; }
bool gitDirty() { return std::strcmp(CROSSINK_GIT_DIRTY, "1") == 0; }
const char* gitDirtyFlag() { return CROSSINK_GIT_DIRTY; }
} // namespace AppVersion
Loading