NEW: build scripts

This commit is contained in:
JohnE 2026-03-11 16:12:55 -07:00
parent 68836cfff4
commit 58389ad685
3 changed files with 794 additions and 0 deletions

370
README_DEV.rst Normal file
View File

@ -0,0 +1,370 @@
=============================================
CCC Rust — Developer Build Guide
=============================================
:Last Updated: 2026-03-11
This document covers everything needed to build, test, and cross-compile the
``ccc_rust`` workspace on a development machine.
----
Prerequisites
=============
The table below lists all required tools. Versions shown are known-good; newer
patch releases should work.
+------------------+---------------+--------------------------------------------------+
| Tool | Min Version | Purpose |
+==================+===============+==================================================+
| **Rust (rustup)**| stable 1.85+ | Compiler toolchain (pinned via ``rust-toolchain`` |
| | | ``.toml``) |
+------------------+---------------+--------------------------------------------------+
| **CMake** | 3.24+ | Builds vendored wolfSSL from source |
+------------------+---------------+--------------------------------------------------+
| **Clang / LLVM** | 14+ | Required by ``bindgen`` for FFI generation |
+------------------+---------------+--------------------------------------------------+
| **Git** | 2.30+ | Submodule management |
+------------------+---------------+--------------------------------------------------+
| **task** (opt) | 3.x | Local task runner (``Taskfile.yaml``) |
+------------------+---------------+--------------------------------------------------+
| **Android NDK** | r25+ | Cross-compile for Android (optional on macOS) |
| (optional) | | |
+------------------+---------------+--------------------------------------------------+
Installing Dependencies
-----------------------
macOS (Homebrew)
~~~~~~~~~~~~~~~~
.. code-block:: shell
# Rust (via rustup — manages toolchains automatically)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
# CMake and LLVM (clang for bindgen)
brew install cmake llvm
# Task runner (optional — for Taskfile.yaml)
brew install go-task
# Xcode Command Line Tools (required for iOS/macOS targets)
xcode-select --install
Linux (apt)
~~~~~~~~~~~
.. code-block:: shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
sudo apt update && sudo apt install -y cmake clang libclang-dev git
# Task runner (optional)
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
Windows
~~~~~~~
.. code-block:: shell
# Install rustup from https://rustup.rs
# Install CMake from https://cmake.org/download/ (add to PATH)
# Install LLVM/Clang from https://releases.llvm.org/ (add to PATH)
# Install Visual Studio Build Tools (C++ workload)
Android NDK (all platforms, optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Required only for ``aarch64-linux-android`` / ``x86_64-linux-android`` targets.
.. code-block:: shell
# Via Android Studio SDK Manager, or:
sdkmanager --install "ndk;28.2.13676358"
# Set environment variables (add to your shell profile):
export ANDROID_NDK_HOME="$HOME/Library/Android/sdk/ndk/27.0.12077973"
export PATH="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin:$PATH"
# On Linux, replace darwin-x86_64 with linux-x86_64.
----
First-Time Setup
================
.. code-block:: shell
# Clone the repository
git clone <repo-url> ccc_rust && cd ccc_rust
# Initialise the wolfSSL submodule (required — build fails without it)
git submodule update --init --recursive
# Verify the toolchain (rustup reads rust-toolchain.toml automatically)
rustc --version # should print stable ≥ 1.85
cmake --version # should print ≥ 3.24
----
Building
========
Native Build (Host Machine)
----------------------------
.. code-block:: shell
cargo build --workspace # debug
cargo build --workspace --release # release (optimised)
Cross-Compile Targets
---------------------
Cargo aliases are defined in ``.cargo/config.toml``:
.. code-block:: shell
# Apple
cargo build-ios # aarch64-apple-ios
cargo build-ios-sim # aarch64-apple-ios-sim
cargo build-macos-arm64 # aarch64-apple-darwin
cargo build-macos-x64 # x86_64-apple-darwin
cargo build-all-apple # all three Apple targets at once
# Android (requires NDK — see above)
cargo build-android-arm64 # aarch64-linux-android
cargo build-android-x64 # x86_64-linux-android
# Release variants: append --release
cargo build-ios --release
cargo build-macos-arm64 --release
wolfSSL Build Overrides
~~~~~~~~~~~~~~~~~~~~~~~~
The ``build.rs`` script accepts two environment variables:
``WOLFSSL_SOURCE_DIR``
Override the wolfSSL source path (default: ``vendors/wolfssl``).
Useful in CI when the submodule is at a non-standard location.
``WOLFSSL_INSTALL_DIR``
Point to a pre-installed wolfSSL (must contain ``include/wolfssl/``
and ``lib/libwolfssl.a``). Skips the CMake build entirely.
Stub FFI (no C build)
~~~~~~~~~~~~~~~~~~~~~~
For type-checking without building wolfSSL (CI lint jobs, docs):
.. code-block:: shell
cargo check -p ccc-crypto-wolfssl --features stub_ffi
----
Testing
=======
.. code-block:: shell
# Unit tests (all crates)
cargo test --workspace
# Conformance test binary (NIST / RFC vectors)
cargo run -p ccc-conformance-tests
# Run a single test by name
cargo test --workspace test_name
# Clippy (lint — treat warnings as errors)
cargo clippy --workspace -- -D warnings
# Format check
cargo fmt --check
----
Build Artifacts
===============
All output lands under ``target/``. The directory structure is:
::
target/
├── debug/ ← native host debug
│ ├── conformance ← conformance test binary
│ ├── libccc_crypto_core.rlib ← core crate (Rust lib)
│ ├── libccc_crypto_wolfssl.rlib ← wolfSSL provider (Rust lib)
│ └── build/ccc-crypto-wolfssl-*/out/
│ ├── lib/libwolfssl.a ← wolfSSL static library
│ └── include/wolfssl/ ← generated wolfSSL headers
├── release/ ← native host release
│ └── (same layout as debug/)
├── aarch64-apple-ios/
│ └── debug/ | release/ ← iOS artifacts
├── aarch64-apple-darwin/
│ └── debug/ | release/ ← macOS ARM64 artifacts
├── x86_64-apple-darwin/
│ └── debug/ | release/ ← macOS x86_64 artifacts
├── aarch64-linux-android/
│ └── debug/ | release/ ← Android ARM64 artifacts
└── x86_64-linux-android/
└── debug/ | release/ ← Android x86_64 artifacts
Key Artifacts per Target
~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------+--------------------------------------------------------------+
| Artifact | Path |
+=================================+==============================================================+
| Core Rust library | ``target/<triple>/<profile>/libccc_crypto_core.rlib`` |
+---------------------------------+--------------------------------------------------------------+
| wolfSSL provider library | ``target/<triple>/<profile>/libccc_crypto_wolfssl.rlib`` |
+---------------------------------+--------------------------------------------------------------+
| wolfSSL static C library | ``target/<triple>/<profile>/build/ccc-crypto-wolfssl-*/out/`` |
| | ``lib/libwolfssl.a`` |
+---------------------------------+--------------------------------------------------------------+
| Conformance test binary | ``target/<triple>/<profile>/conformance`` |
+---------------------------------+--------------------------------------------------------------+
Where ``<triple>`` is the Rust target triple (e.g. ``aarch64-apple-ios``)
and ``<profile>`` is ``debug`` or ``release``.
.. note::
These crates produce **rlib** (Rust library) output. The Milestone 2
bridge crate (in the separate ``ccc_cryptography`` repository) adds
``crate-type = ["cdylib", "staticlib"]`` to produce the ``.so`` /
``.dylib`` / ``.a`` artifacts consumed by Flutter.
----
Publish
=======
The Rust crypto library remains a pure Rust crate with no Flutter or FFI-specific code.
Option 1
--------
Option 1: Build from source via Cargokit (recommended for development)
* Cargokit compiles the Rust code at build time for each platform
* No precompiled binaries are needed
Option 2
--------
Option 2: Cargokit precompiled binaries via GitHub Releases (recommended for pub.dev)
* The Rust crate is compiled into platform-specific binaries (staticlib for iOS/macOS, cdylib for Android)
* Binaries are uploaded to GitHub Releases
* Cargokit fetches the correct binary at build time based on the target platform
* This allows pub.dev users to get native performance without needing Rust or a build environment
Workflow
~~~~~~~~
* CI builds the Rust crate for all 5 platform targets
* CI uploads the .so/.dylib/.dll/.framework to a GitHub Release tagged with the Cargo package hash
* When consumers run flutter build, Cargokit downloads the precompiled binary instead of compiling
* If no precompiled binary exists, it falls back to source build
* Pros: Fast builds for consumers, no Rust toolchain needed, no repo bloat, built into FRB, single repo
* Cons: Requires CI pipeline to build + upload binaries
* Best for: pub.dev releases, distributing to teams without Rust installed
----
Workspace Layout
================
::
ccc_rust/
├── Cargo.toml workspace manifest
├── rust-toolchain.toml pinned stable toolchain + targets
├── Taskfile.yaml local task runner (task CLI)
├── ci.sh CI/CD build script
├── .cargo/config.toml cross-compile aliases + linker config
├── vendors/
│ ├── README.md submodule pin rationale
│ └── wolfssl/ git submodule → wolfSSL v5.7.2-stable
├── crates/
│ ├── ccc-crypto-core/ shared traits, enums, registry
│ └── ccc-crypto-wolfssl/ wolfSSL/wolfCrypt provider
├── tests/
│ └── conformance/ NIST/RFC conformance test binary
└── docs/ architecture + design documents
----
Troubleshooting
===============
wolfSSL source not found
~~~~~~~~~~~~~~~~~~~~~~~~~
::
wolfSSL source not found at .../vendors/wolfssl.
Run `git submodule update --init --recursive` to fetch it.
The wolfSSL submodule was not initialised. Run the command shown in the error.
Linker errors on Apple (undefined symbols)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ensure the ``-lc++`` link arg is set for Apple targets. This is configured
in ``.cargo/config.toml`` and should work automatically. If you see linker
errors about C++ symbols, verify Xcode Command Line Tools are installed:
.. code-block:: shell
xcode-select --install
Android linker not found
~~~~~~~~~~~~~~~~~~~~~~~~~
::
linker `aarch64-linux-android21-clang` not found
The Android NDK toolchain is not in your PATH. See the "Android NDK" section
above.
bindgen fails / libclang not found
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``bindgen`` needs ``libclang``. On macOS, install LLVM via Homebrew:
.. code-block:: shell
brew install llvm
export LIBCLANG_PATH="$(brew --prefix llvm)/lib"
On Linux:
.. code-block:: shell
sudo apt install libclang-dev
----
Plugin Integration Notes
=========================
When building the Milestone 2 Flutter plugin (``ccc_cryptography``):
1. The bridge crate depends on these crates via git tag::
[dependencies]
ccc-crypto-core = { git = "...", tag = "v0.1.0" }
ccc-crypto-wolfssl = { git = "...", tag = "v0.1.0" }
2. The bridge crate sets ``crate-type = ["cdylib", "staticlib"]``.
3. Call ``ccc_crypto_wolfssl::init()`` from the bridge's ``ccc_init()``.
4. ``flutter_rust_bridge`` and all Dart/Flutter dependencies live exclusively
in the plugin repo — never in this one.

256
Taskfile.yaml Normal file
View File

@ -0,0 +1,256 @@
# https://taskfile.dev
version: "3"
vars:
APPLE_TARGETS: "aarch64-apple-ios aarch64-apple-darwin x86_64-apple-darwin"
tasks:
# ── Setup ────────────────────────────────────────────────────────────────
setup:
desc: Initialise submodules and verify toolchain
cmds:
- git submodule update --init --recursive
- rustc --version
- cmd: cmake --version | head -1
platforms: [darwin, linux]
- cmd: cmake --version
platforms: [windows]
status:
- test -f vendors/wolfssl/CMakeLists.txt
# ── Build ────────────────────────────────────────────────────────────────
build:
desc: Build all crates (debug)
deps: [setup]
cmds:
- cargo build --workspace
release:
desc: Build all crates (release)
deps: [setup]
cmds:
- cargo build --workspace --release
build:ios:
desc: Cross-compile for iOS (aarch64-apple-ios, release)
deps: [setup]
cmds:
- cargo build-ios --release
build:macos-arm64:
desc: Cross-compile for macOS ARM64 (release)
deps: [setup]
cmds:
- cargo build-macos-arm64 --release
build:macos-x64:
desc: Cross-compile for macOS x86_64 (release)
deps: [setup]
cmds:
- cargo build-macos-x64 --release
build:apple:
desc: Cross-compile all Apple targets (iOS + macOS, release)
deps: [setup]
cmds:
- cargo build-ios --release
- cargo build-macos-arm64 --release
- cargo build-macos-x64 --release
build:android-arm64:
desc: Cross-compile for Android ARM64 (release)
deps: [setup]
preconditions:
- sh: command -v aarch64-linux-android21-clang
msg: "Android NDK not in PATH. Set ANDROID_NDK_HOME and add toolchain bin/ to PATH."
cmds:
- cargo build-android-arm64 --release
build:android-x64:
desc: Cross-compile for Android x86_64 (release)
deps: [setup]
preconditions:
- sh: command -v x86_64-linux-android21-clang
msg: "Android NDK not in PATH. Set ANDROID_NDK_HOME and add toolchain bin/ to PATH."
cmds:
- cargo build-android-x64 --release
build:android:
desc: Cross-compile all Android targets (release)
cmds:
- task: build:android-arm64
- task: build:android-x64
# ── Windows (run on Windows only) ─────────────────────────────────────
build:windows-x64:
desc: Build for Windows x86_64 (release, run on Windows)
platforms: [windows]
deps: [setup]
cmds:
- cargo build --workspace --release --target x86_64-pc-windows-msvc
ci:windows:
desc: Full CI pipeline for Windows
platforms: [windows]
cmds:
- task: lint
- task: test
- task: conformance
- task: build:windows-x64
# ── Linux ────────────────────────────────────────────────────────────────
build:linux-x64:
desc: Build for Linux x86_64 (release, run on Linux)
platforms: [linux]
deps: [setup]
cmds:
- cargo build --workspace --release --target x86_64-unknown-linux-gnu
ci:linux:
desc: Full CI pipeline for Linux (lint + test + conformance + build + Android)
platforms: [linux]
cmds:
- task: lint
- task: test
- task: conformance
- task: build:linux-x64
- task: build:android
# ── Aggregate ────────────────────────────────────────────────────────────
build:all:
desc: Build for all targets (native + Apple + Android)
cmds:
- task: release
- task: build:apple
- task: build:android
# ── Test ─────────────────────────────────────────────────────────────────
test:
desc: Run all unit tests
deps: [setup]
cmds:
- cargo test --workspace
conformance:
desc: Run NIST/RFC conformance test vectors
deps: [setup]
cmds:
- cargo run -p ccc-conformance-tests
test:all:
desc: Run unit tests + conformance tests
cmds:
- task: test
- task: conformance
# ── Lint ─────────────────────────────────────────────────────────────────
fmt:
desc: Format code with rustfmt
cmds:
- cargo fmt
fmt:check:
desc: Check formatting (no changes)
cmds:
- cargo fmt --check
clippy:
desc: Run clippy with strict warnings
deps: [setup]
cmds:
- cargo clippy --workspace -- -D warnings
lint:
desc: Full lint (fmt check + clippy)
cmds:
- task: fmt:check
- task: clippy
# ── CI Pipeline ─────────────────────────────────────────────────────────
ci:
desc: Full CI pipeline (lint → test → conformance → release build)
cmds:
- task: lint
- task: test
- task: conformance
- task: release
ci:full:
desc: Full CI + all cross-compile targets (platform-aware)
cmds:
- task: ci
- task: build:apple
- task: build:android
ci:macos:
desc: Full CI pipeline for macOS (lint + test + conformance + Apple targets)
platforms: [darwin]
cmds:
- task: lint
- task: test
- task: conformance
- task: release
- task: build:apple
# ── Utility ─────────────────────────────────────────────────────────────
clean:
desc: Remove all build artifacts
cmds:
- cargo clean
check:
desc: Type-check without building (fast)
deps: [setup]
cmds:
- cargo check --workspace
check:stub:
desc: Type-check wolfSSL crate with stub_ffi (no C build)
cmds:
- cargo check -p ccc-crypto-wolfssl --features stub_ffi
artifacts:
desc: Show artifact locations for all built targets
platforms: [darwin, linux]
cmds:
- |
echo "=== Build artifacts ==="
for dir in target/debug target/release target/aarch64-apple-ios/release target/aarch64-apple-darwin/release target/x86_64-apple-darwin/release target/aarch64-linux-android/release target/x86_64-linux-android/release target/x86_64-unknown-linux-gnu/release; do
if [ -d "$dir" ]; then
echo ""
echo "── $dir ──"
find "$dir" -maxdepth 1 \( -name "*.rlib" -o -name "*.a" -o -name "*.dylib" -o -name "*.so" -o -name "conformance" \) 2>/dev/null | sort
find "$dir/build" -name "libwolfssl.a" 2>/dev/null | head -1
fi
done
artifacts:windows:
desc: Show artifact locations (Windows)
platforms: [windows]
cmds:
- cmd: |
echo === Build artifacts ===
for %%d in (target\debug target\release target\x86_64-pc-windows-msvc\release) do (
if exist "%%d" (
echo.
echo -- %%d --
dir /b "%%d\*.rlib" "%%d\*.lib" "%%d\*.dll" "%%d\*.exe" 2>nul
)
)
# ── Default ─────────────────────────────────────────────────────────────
default:
desc: Run the default CI pipeline
cmds:
- task: ci

168
ci.sh Executable file
View File

@ -0,0 +1,168 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────────
# ci.sh — CI/CD build script for ccc_rust
#
# Usage:
# ./ci.sh Run the full CI pipeline (lint + test + cross-build)
# ./ci.sh lint Lint only (fmt + clippy)
# ./ci.sh test Unit tests + conformance vectors
# ./ci.sh build Native debug build
# ./ci.sh release Native release build
# ./ci.sh apple Cross-compile all Apple targets (iOS + macOS)
# ./ci.sh android Cross-compile Android targets (requires NDK)
# ./ci.sh all Full pipeline + all cross targets
# ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail
# Source cargo env if not already in PATH.
if ! command -v cargo &>/dev/null; then
# shellcheck source=/dev/null
source "$HOME/.cargo/env"
fi
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
step() { echo -e "\n${CYAN}${BOLD}── $1 ──${RESET}"; }
pass() { echo -e "${GREEN}$1${RESET}"; }
fail() { echo -e "${RED}$1${RESET}"; exit 1; }
# ── Submodule check ──────────────────────────────────────────────────────────
check_submodule() {
if [ ! -f "vendors/wolfssl/CMakeLists.txt" ]; then
step "Initialising wolfSSL submodule"
git submodule update --init --recursive
fi
}
# ── Stages ───────────────────────────────────────────────────────────────────
do_lint() {
step "Format check"
cargo fmt --check || fail "cargo fmt --check failed"
pass "Format OK"
step "Clippy"
cargo clippy --workspace -- -D warnings || fail "clippy failed"
pass "Clippy OK"
}
do_test() {
step "Unit tests"
cargo test --workspace || fail "cargo test failed"
pass "Unit tests passed"
step "Conformance vectors"
cargo run -p ccc-conformance-tests || fail "conformance tests failed"
pass "Conformance tests passed"
}
do_build() {
step "Build (debug)"
cargo build --workspace || fail "debug build failed"
pass "Debug build OK"
}
do_release() {
step "Build (release)"
cargo build --workspace --release || fail "release build failed"
pass "Release build OK"
}
do_apple() {
step "Build iOS (aarch64-apple-ios)"
cargo build-ios --release || fail "iOS build failed"
pass "iOS build OK"
step "Build macOS ARM64 (aarch64-apple-darwin)"
cargo build-macos-arm64 --release || fail "macOS ARM64 build failed"
pass "macOS ARM64 build OK"
step "Build macOS x64 (x86_64-apple-darwin)"
cargo build-macos-x64 --release || fail "macOS x64 build failed"
pass "macOS x64 build OK"
}
do_android() {
if ! command -v aarch64-linux-android21-clang &>/dev/null; then
echo -e "${RED}Android NDK not in PATH — skipping Android targets.${RESET}"
echo "Set ANDROID_NDK_HOME and add the toolchain bin/ to PATH."
return 1
fi
step "Build Android ARM64 (aarch64-linux-android)"
cargo build-android-arm64 --release || fail "Android ARM64 build failed"
pass "Android ARM64 build OK"
step "Build Android x64 (x86_64-linux-android)"
cargo build-android-x64 --release || fail "Android x64 build failed"
pass "Android x64 build OK"
}
do_full() {
do_lint
do_test
do_release
}
do_linux() {
step "Build Linux x64 (x86_64-unknown-linux-gnu)"
cargo build --workspace --release --target x86_64-unknown-linux-gnu \
|| fail "Linux x64 build failed"
pass "Linux x64 build OK"
}
do_windows() {
step "Build Windows x64 (x86_64-pc-windows-msvc)"
cargo build --workspace --release --target x86_64-pc-windows-msvc \
|| fail "Windows x64 build failed"
pass "Windows x64 build OK"
}
do_all() {
do_full
do_apple
do_android || true # Don't fail the pipeline if NDK is absent.
}
# ── Summary ──────────────────────────────────────────────────────────────────
summary() {
echo ""
step "Artifact locations"
echo " Native (release): target/release/"
echo " iOS: target/aarch64-apple-ios/release/"
echo " macOS ARM64: target/aarch64-apple-darwin/release/"
echo " macOS x64: target/x86_64-apple-darwin/release/"
echo " Linux x64: target/x86_64-unknown-linux-gnu/release/"
echo " Windows x64: target/x86_64-pc-windows-msvc/release/"
echo " Android ARM64: target/aarch64-linux-android/release/"
echo " Android x64: target/x86_64-linux-android/release/"
echo ""
pass "CI pipeline complete"
}
# ── Main ─────────────────────────────────────────────────────────────────────
check_submodule
case "${1:-}" in
lint) do_lint ;;
test) do_test ;;
build) do_build ;;
release) do_release ;;
apple) do_apple && summary ;;
android) do_android && summary ;;
linux) do_linux && summary ;;
windows) do_windows && summary ;;
all) do_all && summary ;;
"") do_full && summary ;;
*)
echo "Usage: $0 {lint|test|build|release|apple|android|linux|windows|all}"
exit 1
;;
esac