Skip to content
Merged
20 changes: 1 addition & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ include(cmake/third_party/CPM.cmake)
include(cmake/compile/CompilerFlag.cmake)

# ── Dependencies ──────────────────────────────────────────────
CPMAddPackage(
NAME zlib
GITHUB_REPOSITORY madler/zlib
GIT_TAG v1.3.1
OPTIONS "CMAKE_POSITION_INDEPENDENT_CODE ON"
)
# (zlib removed — using built-in deflate/inflate implementation)

# ── Applet configuration ─────────────────────────────────────
include(cmake/Config.cmake)
Expand Down Expand Up @@ -60,13 +55,6 @@ add_executable(cfbox src/main.cpp ${CFBOX_APPLET_SOURCES})
target_include_directories(cfbox PUBLIC include)
target_include_directories(cfbox PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include)
target_link_libraries(cfbox PRIVATE cfbox_compiler_flags)
if(zlib_ADDED)
target_link_libraries(cfbox PRIVATE zlibstatic)
target_include_directories(cfbox SYSTEM PRIVATE ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
else()
find_package(ZLIB REQUIRED)
target_link_libraries(cfbox PRIVATE ZLIB::ZLIB)
endif()

# ── GTest via CPM (FetchContent) ──────────────────────────────
if(NOT CMAKE_CROSSCOMPILING)
Expand All @@ -89,12 +77,6 @@ if(GTest_ADDED)
cfbox_compiler_flags
GTest::gtest_main
)
if(zlib_ADDED)
target_link_libraries(cfbox_tests PRIVATE zlibstatic)
target_include_directories(cfbox_tests SYSTEM PRIVATE ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
else()
target_link_libraries(cfbox_tests PRIVATE ZLIB::ZLIB)
endif()

include(GoogleTest)
gtest_discover_tests(cfbox_tests)
Expand Down
121 changes: 71 additions & 50 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,40 @@ A minimalist BusyBox alternative written in modern C++23.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![C++23](https://img.shields.io/badge/C++23-00599C?logo=cplusplus)](https://en.cppreference.com/w/cpp/23)
[![CMake](https://img.shields.io/badge/CMake-3.26+-064F8C?logo=cmake)](https://cmake.org/)
[![Tests](https://img.shields.io/badge/Tests-149_passing-brightgreen)](tests/)
[![Applets](https://img.shields.io/badge/Applets-17-brightgreen)](src/applets/)
[![Tests](https://img.shields.io/badge/Tests-331_passing-brightgreen)](tests/)
[![Applets](https://img.shields.io/badge/Applets-109-brightgreen)](src/applets/)

## Overview

CFBox is a single-executable Unix utility collection distributed via symbolic links. 17 applets implemented and tested, with a CI pipeline covering native builds, cross-compilation, and QEMU user/system-mode testing across 5 stages. Features configurable CMake builds (per-applet toggles), GNU-style long options, and colored help output.
CFBox is a single-executable Unix utility collection distributed via symbolic links. 109 applets implemented and tested, with a CI pipeline covering native builds, cross-compilation, and QEMU user/system-mode testing. Features configurable CMake builds (per-applet toggles), GNU-style long options, and colored help output.

**Design philosophy:** Simplicity first — Modern C++ (`std::expected`) — Embedded-friendly (cross-compilation, static linking)

## Size Comparison

| Project | Language | Size | Applets | Size/Applet |
|---------|----------|------|---------|-------------|
| **CFBox (size-opt)** | **C++23** | **446 KB** | **109** | **~4.1 KB** |
| Toybox | C | ~500 KB | 238 | ~2.1 KB |
| BusyBox (full) | C | ~1.7 MB | 274 | ~9 KB |
| uutils/coreutils | Rust | ~11 MB | ~100 | ~110 KB |

> CFBox is **3-4x smaller** than BusyBox while providing a complete AWK interpreter, archive suite (tar/cpio/ar/unzip/gzip), diff/patch (Myers O(ND) algorithm), process tools (ps/top/pstree/pgrep/pmap), and a built-in TUI framework.

## Performance

| Operation | Data Size | Time |
|-----------|-----------|------|
| grep -c | 10 MB | 54 ms |
| cat | 10 MB | 63 ms |
| wc | 10 MB | 17 ms |
| sort | 100K lines | 32 ms |
| diff | 100K lines (similar) | 79 ms |

- grep/cat/wc use streaming I/O — reading `/dev/urandom` won't exhaust memory
- diff uses Myers O(ND) algorithm; sort precomputes keys to avoid repeated allocation
- Zero external dependencies: hand-written lightweight deflate/inflate replaces zlib

## Quick Start

```bash
Expand All @@ -25,8 +50,8 @@ cmake -B build
cmake --build build

# Test
ctest --test-dir build --output-on-failure # 149 GTest unit tests
bash tests/integration/run_all.sh # 17 integration test scripts
ctest --test-dir build --output-on-failure # 331 GTest unit tests
bash tests/integration/run_all.sh # 54 integration test scripts

# Run via subcommand
./build/cfbox echo "Hello, World!"
Expand All @@ -36,44 +61,37 @@ bash tests/integration/run_all.sh # 17 integration test scripts
echo "Hello, World!" # now calls cfbox via symlink
```

## Supported Commands
## Supported Commands (109)

### Text Processing (28)

`echo`, `printf`, `cat`, `head`, `tail`, `wc`, `sort`, `uniq`, `grep`, `sed`, `fold`, `expand`, `cut`, `paste`, `nl`, `comm`, `tr`, `tac`, `rev`, `shuf`, `factor`, `od`, `split`, `seq`, `tsort`, `expr`, `awk`, `diff` + `patch` + `cmp` + `ed`

### File Operations (20)

`mkdir`, `rm`, `cp`, `mv`, `ls`, `find`, `ln`, `touch`, `stat`, `install`, `mktemp`, `truncate`, `du`, `df`, `readlink`, `realpath`, `rmdir`, `link`, `unlink`, `chmod`

### Archive & Compression (6)

`tar` (ustar format), `cpio` (newc format), `ar` (static library), `unzip`, `gzip`, `gunzip`

### Shell & Scripting (2)

### Text Processing
`sh` (POSIX shell: pipes, redirections, variable expansion, command substitution, if/while/for, 15 builtins), `xargs`

| Applet | Supported Flags / Features |
|--------|----------------------------|
| `echo` | `-n` (no trailing newline), `-e` (interpret escape sequences), all applets support `--help` / `--version` |
| `printf` | Format strings (`%s` `%d` `%f` `%c` `%%`), format reuse |
| `cat` | `-n` (number lines), `-b` (number non-blank), `-A` (show non-printing), stdin passthrough |
| `head` | `-n N` (first N lines), `-c N` (first N bytes), multi-file headers |
| `tail` | `-n N` (last N lines), `-c N` (last N bytes), multi-file footers |
| `wc` | `-l` (lines), `-w` (words), `-c` (bytes), `-m` (chars), multi-file totals |
| `sort` | `-r` (reverse), `-n` (numeric), `-u` (unique), `-k N` (key field), multi-file merge |
| `uniq` | `-c` (count), `-d` (duplicates only), `-u` (unique only), stdin support |
| `grep` | `-E` (extended regex), `-i` (ignore case), `-v` (invert), `-n` (line numbers), `-r` (recursive), `-c` (count), `-l` (files with matches), `-q` (quiet) |
| `sed` | `-n` (suppress auto-print), `-e SCRIPT`; substitution `s/pat/repl/[g\|p\|d]`, line addresses, ranges, `$` |
### System Info (20)

### File Operations
`pwd`, `basename`, `dirname`, `uname`, `hostname`, `whoami`, `id`, `tty`, `date`, `nproc`, `logname`, `hostid`, `printenv`, `env`, `uptime`, `free`, `cal`, `dmesg`, `who`, `test`

| Applet | Supported Flags / Features |
|--------|----------------------------|
| `mkdir` | `-p`/`--parents` (create parents), `-m`/`--mode MODE` (permissions) |
| `rm` | `-r`/`--recursive` (recursive), `-f`/`--force` (force), `-i` (interactive), `/` safety check |
| `cp` | `-r`/`--recursive` (recursive), `-p`/`--preserve` (preserve permissions), multi-file to directory |
| `mv` | `-f` (force overwrite), cross-filesystem fallback (copy + remove) |
### Process Management (15)

### Directory & Search
`ps`, `top`, `kill`, `pgrep`/`pkill`, `pidof`, `pstree`, `pmap`, `fuser`, `pwdx`, `sysctl`, `iostat`, `watch`, `nice`, `renice`, `timeout`

| Applet | Supported Flags / Features |
|--------|----------------------------|
| `ls` | `-a`/`--all` (show hidden), `-l`/`--long` (long format), `-h`/`--human-readable` (human-readable sizes) |
| `find` | `-name PATTERN` (glob), `-type [f\|d\|l]`, `-maxdepth N`, `-exec CMD {} ;` |
### Other (18)

### System
`true`, `false`, `yes`, `sleep`, `usleep`, `sync`, `nohup`, `cksum`, `md5sum`, `sum`, `hexdump`, `more`, `tee`, `init` (PID 1 initramfs init system), `mkfifo`, `mknod`, `sleep`, `sh`

| Applet | Description |
|--------|-------------|
| `init` | System initialization — auto-mounts proc/sysfs/devtmpfs when PID 1, runs smoke tests, then powers off |
> All applets support `--help` / `--version`

## Requirements

Expand All @@ -86,9 +104,10 @@ echo "Hello, World!" # now calls cfbox via symlink
| Document | Description |
|----------|-------------|
| [Architecture & Design](document/architecture.md) | Dispatch mechanism, core infrastructure, error handling, testing |
| [Roadmap](Roadmap.md) | 7-phase development plan, current progress, architecture decisions |
| [Cross-Compilation & Embedded](document/cross-compilation.md) | Toolchains, CMake options, build examples, binary sizes |
| [QEMU Testing](document/qemu-testing.md) | User-mode / system-mode testing, init applet, kernel config |
| [Continuous Integration](document/ci.md) | CI pipeline 5-stage overview |
| [Continuous Integration](document/ci.md) | CI pipeline overview |
| [Contributing Guide](CONTRIBUTING.md) | Build, test, code style, submission |

## Project Structure
Expand All @@ -99,28 +118,30 @@ cfbox/
├── cmake/
│ ├── Config.cmake # Per-applet configuration (CFBOX_ENABLE_xxx options)
│ ├── compile/CompilerFlag.cmake # Compiler warnings & optimization flags
│ ├── third_party/CPM.cmake # CPM dependency manager
│ ├── third_party/CPM.cmake # CPM dependency manager (GTest only)
│ └── toolchain/ # Cross-compilation toolchains
├── configs/
│ └── qemu-virt-aarch64.config # Minimal QEMU aarch64 kernel config
├── document/ # Detailed documentation
├── include/cfbox/
│ ├── applet_config.hpp.in # CMake-generated config (version + enable flags)
│ ├── applet.hpp / applets.hpp # Registry & dispatch
│ ├── args.hpp # Short + long option argument parser
│ ├── help.hpp # --help / --version help system
│ ├── error.hpp # std::expected error handling + CFBOX_TRY
│ ├── io.hpp # Streaming I/O (for_each_line, read_all, write_all)
│ ├── stream.hpp # Line-by-line pipeline, LineProcessor
│ ├── deflate.hpp / inflate.hpp # Hand-written lightweight DEFLATE (zero deps)
│ ├── compress.hpp # gzip wrapper
│ ├── utf8.hpp # Unicode width/count (constexpr + static_assert)
│ ├── term.hpp # ANSI colored output (NO_COLOR support)
│ ├── utf8.hpp # Unicode-aware width/count utilities
│ └── ... # error.hpp, io.hpp, fs_util.hpp, escape.hpp
│ ├── terminal.hpp # Terminal control (RawMode RAII, cursor, double buffer)
│ ├── tui.hpp # TUI framework (ScreenBuffer, Key, TuiApp)
│ ├── proc.hpp # /proc parser (processes, memory, CPU, disks)
│ ├── regex.hpp # POSIX regex RAII (scoped_regex)
│ └── ... # help.hpp, fs_util.hpp, escape.hpp, checksum.hpp
├── src/
│ ├── main.cpp # Dispatch entry
│ └── applets/ # 17 command implementations
│ └── applets/ # 109 command implementations
├── tests/
│ ├── unit/ # GTest unit tests (149 cases)
│ └── integration/ # Shell integration tests (17 scripts)
├── scripts/ # Build, test, install scripts
├── .github/workflows/ci.yml # CI pipeline
└── CONTRIBUTING.md # Contributing guide
│ ├── unit/ # GTest unit tests (331 cases)
│ └── integration/ # Shell integration tests (54 scripts)
└── scripts/ # Build, test, install scripts
```

## Contributing
Expand Down
Loading
Loading