Files
crosspoint-reader-mod/mod/docs/ci-build-and-code-style.md
cottongin dfbc931c14 mod: Phase 1 - bring forward mod-exclusive files with ActivityManager migration
Brings ~55 mod-exclusive files to the upstream-based mod/master-resync branch:

Activities (migrated to new ActivityManager pattern):
- Clock/Time: SetTimeActivity, SetTimezoneOffsetActivity, NtpSyncActivity
- Dictionary: DictionaryDefinitionActivity, DictionarySuggestionsActivity,
  DictionaryWordSelectActivity, LookedUpWordsActivity
- Bookmark: EpubReaderBookmarkSelectionActivity
- Book management: BookManageMenuActivity, EndOfBookMenuActivity
- OPDS: OpdsServerListActivity, OpdsSettingsActivity
- Utility: DirectoryPickerActivity, NumericStepperActivity

Utilities (unchanged):
- BookManager, BookSettings, BookmarkStore, BootNtpSync
- Dictionary, LookupHistory, TimeSync, OpdsServerStore

Libraries: PlaceholderCover, TableData, ChapterXPathIndexer
Scripts: inject_mod_version, generate_book_icon, preview_placeholder_cover
Docs: KOReader sync XPath mapping

Migration changes:
- ActivityWithSubactivity -> Activity base class
- Callback constructors -> finish()/setResult() pattern
- enterNewActivity() -> startActivityForResult()
- Activity::RenderLock&& -> RenderLock&&

These files won't compile yet - they reference mod settings and I18n
strings that will be added in subsequent phases.

Made-with: Cursor
2026-03-07 15:10:00 -05:00

9.5 KiB

CI, Build, Release & Code Style

This document covers the CrossPoint Reader build system, CI pipeline, release process, code formatting rules, static analysis, and contribution guidelines.

Build System

The project uses PlatformIO with the Arduino framework targeting the ESP32-C3.

Build Environments

Defined in platformio.ini:

Environment Purpose Version String
default Local development builds 1.0.0-dev
gh_release Official tagged releases 1.0.0
gh_release_rc Release candidates 1.0.0-rc+{7-char SHA}

Build Command

# Development build
pio run

# Release build
pio run -e gh_release

# Release candidate build (requires CROSSPOINT_RC_HASH env var)
CROSSPOINT_RC_HASH=abc1234 pio run -e gh_release_rc

Build Flags

All environments share a common set of flags ([base] section):

Flag Purpose
-std=c++2a C++20 standard
-DARDUINO_USB_MODE=1 USB mode selection
-DARDUINO_USB_CDC_ON_BOOT=1 Enable USB CDC serial on boot
-DMINIZ_NO_ZLIB_COMPATIBLE_NAMES=1 Avoid miniz/zlib symbol conflicts
-DEINK_DISPLAY_SINGLE_BUFFER_MODE=1 Single frame buffer (saves RAM)
-DDISABLE_FS_H_WARNING=1 Suppress Arduino FS.h warning
-DXML_GE=0 Disable expat general entity expansion
-DXML_CONTEXT_BYTES=1024 Expat context buffer size
-DUSE_UTF8_LONG_NAMES=1 Enable UTF-8 long filenames in SdFat

Pre-Build Step

scripts/build_html.py runs before compilation (configured via extra_scripts = pre:scripts/build_html.py). It:

  1. Finds all .html files under src/.
  2. Minifies them (strips comments, collapses whitespace, preserves <pre>, <code>, <textarea>, <script>, <style> blocks).
  3. Generates .generated.h files containing constexpr char ...Html[] PROGMEM = R"rawliteral(...)rawliteral"; strings.

Dependencies

SDK libraries (symlinked from open-x4-sdk submodule):

  • BatteryMonitor
  • InputManager
  • EInkDisplay
  • SDCardManager

External libraries (managed by PlatformIO):

  • bblanchon/ArduinoJson @ 7.4.2 -- JSON parsing
  • ricmoo/QRCode @ 0.0.1 -- QR code generation
  • links2004/WebSockets @ 2.7.3 -- WebSocket server

Tool Versions

Tool Version Notes
PlatformIO Latest (via pip) espressif32 @ 6.12.0 platform
Python 3.14 Used in CI and build scripts
clang-format 21 From LLVM apt repository
cppcheck Latest (via PlatformIO) Static analysis

CI Pipeline

All CI workflows are in .github/workflows/.

ci.yml -- Main CI

Triggers: Push to master, all pull requests.

Runs 4 jobs in parallel (the first 3 are independent; the 4th aggregates results):

1. clang-format -- Code Formatting Check

  1. Installs clang-format-21 from the LLVM apt repository.
  2. Runs bin/clang-format-fix on the full codebase.
  3. Checks git diff --exit-code -- fails if any file was reformatted.

2. cppcheck -- Static Analysis

  1. Installs PlatformIO.
  2. Runs pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high.
  3. Fails on any low, medium, or high severity defect.

3. build -- Compilation

  1. Installs PlatformIO.
  2. Runs pio run (default environment).
  3. Extracts RAM and Flash usage stats into the GitHub step summary.
  4. Uploads firmware.bin as a build artifact.

4. test-status -- PR Gate

  • Depends on all three jobs above.
  • Fails if any dependency failed or was cancelled.
  • This is the required status check for pull requests, decoupling CI steps from PR merge requirements.

pr-formatting-check.yml -- PR Title Validation

Triggers: Pull request opened, reopened, edited events.

Uses amannn/action-semantic-pull-request@v6 to enforce semantic PR title format (e.g., feat: add dark mode, fix: correct page numbering).

release.yml -- Official Release

Trigger: Push of any git tag.

  1. Builds using the gh_release environment.
  2. Uploads release artifacts named CrossPoint-{tag}:
    • bootloader.bin
    • firmware.bin
    • firmware.elf
    • firmware.map
    • partitions.bin

release_candidate.yml -- RC Build

Trigger: Manual workflow_dispatch, restricted to branches matching release/*.

  1. Extracts the 7-character short SHA and branch suffix (e.g., v1.0.0 from release/v1.0.0).
  2. Sets CROSSPOINT_RC_HASH env var.
  3. Builds using the gh_release_rc environment.
  4. Uploads artifacts named CrossPoint-RC-{suffix}.

Release Process

Official Release

  1. Create and push a git tag (e.g., v1.0.0).
  2. The release.yml workflow triggers automatically.
  3. Artifacts are uploaded to the GitHub Actions run.

Release Candidate

  1. Create a branch named release/{identifier} (e.g., release/v1.0.0).
  2. Navigate to Actions in GitHub and manually trigger Compile Release Candidate on that branch.
  3. The RC version string includes the commit SHA for traceability.

Version Scheme

1.0.0-dev           # Local development (default env)
1.0.0               # Official release (gh_release env)
1.0.0-rc+a1b2c3d    # Release candidate (gh_release_rc env)

The version base is set in platformio.ini under [crosspoint] version = 1.0.0.

Code Style

Formatting: clang-format

The project uses clang-format 21 with a .clang-format config at the repository root. Key rules:

Setting Value Meaning
IndentWidth 2 2-space indentation
TabWidth / UseTab 8 / Never Spaces only (no tabs)
ColumnLimit 120 Maximum line width
BreakBeforeBraces Attach K&R brace style (opening brace on same line)
PointerAlignment Left int* ptr not int *ptr
ReferenceAlignment Pointer References follow pointer style
ContinuationIndentWidth 4 4-space continuation indent
AllowShortFunctionsOnASingleLine All Short functions may be single-line
AllowShortIfStatementsOnASingleLine WithoutElse if (x) return; allowed
AllowShortLoopsOnASingleLine true Short loops may be single-line
BreakBeforeTernaryOperators true ? and : start new lines
BreakBeforeBinaryOperators None Binary operators stay at end of line
SortIncludes Enabled Includes sorted lexicographically
IncludeBlocks Regroup Includes grouped by category
ReflowComments Always Long comments are rewrapped
SpacesBeforeTrailingComments 2 Two spaces before // comment
LineEnding DeriveLF Unix-style line endings

Include Order

Includes are regrouped into priority categories:

  1. Priority 1: System headers with .h extension (<foo.h>)
  2. Priority 2: Other system headers (<foo>) and extension headers (<ext/foo.h>)
  3. Priority 3: Project-local headers ("foo.h")

Running the Formatter

# Format all tracked source files
./bin/clang-format-fix

# Format only modified (staged or unstaged) files
./bin/clang-format-fix -g

The script formats .c, .cpp, .h, .hpp files tracked by git, excluding lib/EpdFont/builtinFonts/ (script-generated font headers).

Static Analysis: cppcheck

Configuration in platformio.ini:

check_tool = cppcheck
check_flags = --enable=all
               --suppress=missingIncludeSystem
               --suppress=unusedFunction
               --suppress=unmatchedSuppression
               --suppress=*:*/.pio/*
               --inline-suppr
  • --enable=all enables all checks.
  • Suppressed: missing system includes, unused functions (common in library code), PlatformIO build directory.
  • --inline-suppr allows // cppcheck-suppress comments in source.
  • CI fails on any defect severity (low, medium, or high).

Run locally:

pio check

Contribution Guidelines

PR Requirements

  1. Semantic PR title -- enforced by CI. Must follow conventional format:

    • feat: ..., fix: ..., refactor: ..., docs: ..., chore: ..., etc.
  2. PR template (.github/PULL_REQUEST_TEMPLATE.md) must be filled out:

    • Summary: Goal and changes included.
    • Additional Context: Performance implications, risks, focus areas.
    • AI Usage: Transparent disclosure -- YES, PARTIALLY, or NO.
  3. Code formatting -- run bin/clang-format-fix before pushing. CI will reject unformatted code.

  4. Static analysis -- ensure pio check passes without low/medium/high defects.

  5. Build -- confirm pio run compiles without errors.

Project Scope

All contributions must align with the project's core mission: focused reading on the Xteink X4. See SCOPE.md for full details.

In scope: UX improvements, document rendering (EPUB), typography, e-ink driver refinement, library management, local file transfer, language support.

Out of scope: Interactive apps, active connectivity (RSS/news/browsers), media playback, complex reader features (highlighting, notes, dictionary).

When unsure, open a Discussion before coding.

Governance

From GOVERNANCE.md:

  • Assume good intent in technical discussions.
  • Critique code, not people.
  • Public by default -- decisions happen in Issues, PRs, and Discussions.
  • Maintainers guide technical direction for ESP32-C3 hardware constraints.
  • Report harassment privately to @daveallie.

Checklist Before Submitting

  • Code compiles: pio run
  • Code is formatted: bin/clang-format-fix
  • Static analysis passes: pio check
  • PR title follows semantic format
  • PR template filled out (summary, context, AI disclosure)
  • Changes align with project scope (SCOPE.md)