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
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:
- Finds all
.htmlfiles undersrc/. - Minifies them (strips comments, collapses whitespace, preserves
<pre>,<code>,<textarea>,<script>,<style>blocks). - Generates
.generated.hfiles containingconstexpr char ...Html[] PROGMEM = R"rawliteral(...)rawliteral";strings.
Dependencies
SDK libraries (symlinked from open-x4-sdk submodule):
BatteryMonitorInputManagerEInkDisplaySDCardManager
External libraries (managed by PlatformIO):
bblanchon/ArduinoJson @ 7.4.2-- JSON parsingricmoo/QRCode @ 0.0.1-- QR code generationlinks2004/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
- Installs
clang-format-21from the LLVM apt repository. - Runs
bin/clang-format-fixon the full codebase. - Checks
git diff --exit-code-- fails if any file was reformatted.
2. cppcheck -- Static Analysis
- Installs PlatformIO.
- Runs
pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high. - Fails on any low, medium, or high severity defect.
3. build -- Compilation
- Installs PlatformIO.
- Runs
pio run(default environment). - Extracts RAM and Flash usage stats into the GitHub step summary.
- Uploads
firmware.binas 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.
- Builds using the
gh_releaseenvironment. - Uploads release artifacts named
CrossPoint-{tag}:bootloader.binfirmware.binfirmware.elffirmware.mappartitions.bin
release_candidate.yml -- RC Build
Trigger: Manual workflow_dispatch, restricted to branches matching release/*.
- Extracts the 7-character short SHA and branch suffix (e.g.,
v1.0.0fromrelease/v1.0.0). - Sets
CROSSPOINT_RC_HASHenv var. - Builds using the
gh_release_rcenvironment. - Uploads artifacts named
CrossPoint-RC-{suffix}.
Release Process
Official Release
- Create and push a git tag (e.g.,
v1.0.0). - The
release.ymlworkflow triggers automatically. - Artifacts are uploaded to the GitHub Actions run.
Release Candidate
- Create a branch named
release/{identifier}(e.g.,release/v1.0.0). - Navigate to Actions in GitHub and manually trigger
Compile Release Candidateon that branch. - 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:
- Priority 1: System headers with
.hextension (<foo.h>) - Priority 2: Other system headers (
<foo>) and extension headers (<ext/foo.h>) - 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=allenables all checks.- Suppressed: missing system includes, unused functions (common in library code), PlatformIO build directory.
--inline-supprallows// cppcheck-suppresscomments in source.- CI fails on any defect severity (low, medium, or high).
Run locally:
pio check
Contribution Guidelines
PR Requirements
-
Semantic PR title -- enforced by CI. Must follow conventional format:
feat: ...,fix: ...,refactor: ...,docs: ...,chore: ..., etc.
-
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, orNO.
-
Code formatting -- run
bin/clang-format-fixbefore pushing. CI will reject unformatted code. -
Static analysis -- ensure
pio checkpasses without low/medium/high defects. -
Build -- confirm
pio runcompiles 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)