Skip to content

ChaseSunstrom/cforge

Repository files navigation

cforge

A modern C/C++ build tool with Cargo-like simplicity.

Version License

cforge simplifies C/C++ project management with a clean TOML configuration, automatic dependency resolution, and cross-platform builds. It generates CMake under the hood while providing a much simpler interface.

Quick Start

# Install cforge curl -fsSL https://raw.githubusercontent.com/ChaseSunstrom/cforge/master/scripts/install.sh | bash # Create a new project cforge init myapp cd myapp # Build and run cforge build cforge run

Features

  • Simple TOML configuration - No CMake syntax required
  • Portable compiler flags - Write once, works on MSVC, GCC, and Clang
  • Package registry - Search and install packages with cforge deps add <package>
  • Multiple dependency sources - Registry, Git, vcpkg, and system libraries
  • Workspaces - Manage multi-project repositories
  • Cross-compilation - Android, iOS, Raspberry Pi, WebAssembly, embedded bare-metal
  • Embedded development - Bare-metal targets with post-build commands, flash/upload
  • IDE integration - VS Code, CLion, Visual Studio, Xcode
  • Testing & benchmarks - Integrated test runner with Catch2, GTest, doctest
  • Developer tools - Formatting, linting, watch mode, documentation
  • Lock files - Reproducible builds with exact dependency versions
  • Shell completions - Bash, Zsh, PowerShell, Fish

Installation

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/ChaseSunstrom/cforge/master/scripts/install.sh | bash

Windows (PowerShell)

irm https://raw.githubusercontent.com/ChaseSunstrom/cforge/master/scripts/install.ps1 | iex

Prerequisites

  • CMake 3.15+
  • C/C++ compiler (GCC, Clang, or MSVC)

Building from Source

git clone https://github.com/ChaseSunstrom/cforge.git cd cforge cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build --config Release cmake --install build

Shell Completions

cforge completions bash >> ~/.bashrc cforge completions zsh >> ~/.zshrc cforge completions fish > ~/.config/fish/completions/cforge.fish cforge completions powershell >> $PROFILE

Configuration

Projects are configured with a cforge.toml file:

[project] name = "myapp" version = "1.0.0" cpp_standard = "17" binary_type = "executable" # languages = ["C", "CXX", "ASM"] # Override auto-detected languages # c_extensions = true # Enable C GNU extensions (gnu11 instead of c11) # cpp_extensions = true # Enable C++ GNU extensions (gnu++17 instead of c++17) [build] build_type = "Release" source_dirs = ["src"] # Source directories (default: ["src"]) include_dirs = ["include"] # Include directories (default: ["include"]) export_compile_commands = true [build.config.debug] optimize = "debug" debug_info = true warnings = "all" sanitizers = ["address"] [build.config.release] optimize = "speed" lto = true warnings = "all" [dependencies] fmt = "11.1.4" spdlog = "1.12.0"

Commands Reference

Project Management

Command Description
cforge init [name] Initialize a new project in current or new directory
cforge new <template> <name> Create files from templates (class, header, interface, test)
cforge build Build the project
cforge run Build and run the project
cforge clean Clean build artifacts
cforge install Install project to system
cforge flash Flash firmware to embedded target
cforge circular Check for circular dependencies

Dependencies

Command Description
cforge deps add <pkg> Add a dependency
cforge deps remove <pkg> Remove a dependency
cforge deps search <query> Search package registry
cforge deps info <pkg> Show package details
cforge deps list List current dependencies
cforge deps tree Visualize dependency tree
cforge deps lock Manage lock file for reproducible builds
cforge deps update Update package registry
cforge deps outdated Show dependencies with newer versions

Testing & Quality

Command Description
cforge test Run tests
cforge bench Run benchmarks
cforge fmt Format code with clang-format
cforge lint Static analysis with clang-tidy
cforge doc Generate documentation with Doxygen

Tools & IDE

Command Description
cforge ide Generate IDE project files
cforge watch Watch for changes and auto-rebuild
cforge package Create distributable packages
cforge cache Manage binary cache
cforge completions Generate shell completions

Other

Command Description
cforge version Show version information
cforge upgrade Upgrade cforge to the latest version
cforge doctor Diagnose environment and check for required tools
cforge help <cmd> Show help for a command

Project Initialization

Create a New Project

cforge init myapp # Create in new directory cforge init # Initialize in current directory cforge init --type=shared_lib # Create a shared library cforge init --std=c++20 # Use C++20 cforge init --with-tests # Include test infrastructure cforge init --template lib # Use library template cforge init blink --template embedded # Embedded bare-metal project

Create a Workspace

cforge init --workspace myws # Create empty workspace cforge init --workspace myws --projects app lib # Workspace with projects

Generate Code from Templates

cforge new class MyClass # Create MyClass.hpp and MyClass.cpp cforge new class MyClass -n myproj # With namespace cforge new header utils # Create utils.hpp cforge new interface IService # Create abstract interface cforge new test MyClass # Create test file cforge new struct Config # Create struct header

Building

cforge build # Debug build (default) cforge build -c Release # Release build cforge build -j8 # Parallel build with 8 jobs cforge build -v # Verbose output cforge build -t mytarget # Build specific target cforge build --force-regenerate # Clean rebuild with fresh CMake cforge build --skip-deps # Skip updating Git dependencies cforge build --profile android-arm64 # Cross-compile with profile cforge flash --profile avr # Flash firmware to embedded target

In Workspaces

cforge build # Build main project cforge build -p mylib # Build specific project cforge build --gen-workspace-cmake # Generate workspace CMakeLists.txt

Running

cforge run # Build and run cforge run -c Release # Run release build cforge run --no-build # Run without rebuilding cforge run -- arg1 arg2 # Pass arguments to executable cforge run -p myapp -- --config file # Run specific project with args

Dependencies

Registry Packages

[dependencies] fmt = "11.1.4" spdlog = "*" # Latest version json = "3.11.2"
cforge deps add fmt # Add from registry cforge deps add fmt@11.1.4 # Specific version cforge deps add spdlog --features async # With features cforge deps search json # Search packages cforge deps info nlohmann_json # Package details cforge deps outdated # Check for updates

Git Dependencies

[dependencies.git.imgui] url = "https://github.com/ocornut/imgui.git" tag = "v1.89.9"
cforge deps add mylib --git https://github.com/user/mylib --tag v1.0

vcpkg Dependencies

[dependencies.vcpkg] curl = { version = "7.80.0", features = ["ssl"] }
cforge deps add boost --vcpkg

System Dependencies

[dependencies.system.OpenGL] method = "find_package" components = ["GL", "GLU"] [dependencies.system.gtk3] method = "pkg_config" package = "gtk+-3.0"

Lock Files

cforge deps lock # Generate/update lock file cforge deps lock --verify # Verify deps match lock cforge deps lock --force # Force regeneration cforge deps lock --clean # Remove lock file

Commit cforge.lock to version control for reproducible builds.

Dependency Tree

cforge deps tree # Show dependency tree cforge deps tree -a # Include all details cforge deps tree -d 2 # Limit depth

Portable Compiler Flags

cforge provides portable build options that automatically translate to the correct flags for each compiler:

Option Values Description
optimize "none", "debug", "size", "speed", "aggressive" Optimization level
warnings "none", "default", "all", "strict", "pedantic" Warning level
debug_info true / false Include debug symbols
sanitizers ["address", "undefined", "thread", "leak"] Runtime sanitizers
lto true / false Link-time optimization
exceptions true / false C++ exceptions
rtti true / false Runtime type info
hardening "none", "basic", "full" Security hardening
stdlib "default", "libc++", "libstdc++" Standard library
visibility "default", "hidden" Symbol visibility

Flag Translation

Portable MSVC GCC/Clang
optimize = "speed" /O2 -O2
optimize = "size" /O1 /Os -Os
optimize = "aggressive" /Ox -O3
warnings = "all" /W4 -Wall -Wextra
warnings = "strict" /W4 /WX -Wall -Wextra -Werror
lto = true /GL + /LTCG -flto
debug_info = true /Zi -g
sanitizers = ["address"] /fsanitize=address -fsanitize=address

Platform & Compiler Configuration

# Platform-specific settings [platform.windows] hardening = "full" defines = ["WIN32"] links = ["ws2_32"] [platform.linux] hardening = "basic" links = ["pthread"] [platform.macos] stdlib = "libc++" frameworks = ["Cocoa"] # Compiler-specific settings [compiler.msvc] warnings = "strict" defines = ["_CRT_SECURE_NO_WARNINGS"] [compiler.gcc] warnings = "pedantic" [compiler.clang] flags = ["-fcolor-diagnostics"]

Workspaces

For multi-project repositories:

# workspace.toml or cforge.toml [workspace] name = "my-workspace" projects = ["app", "lib", "tests"] main_project = "app"
cforge build # Build main project cforge build -p lib # Build specific project cforge build --gen-workspace-cmake # Generate workspace CMake

Testing

[test] enabled = true framework = "catch2" # or "gtest", "doctest", "boost"
cforge test # Run all tests cforge test -c Release # Test release build cforge test Math # Run tests in Math category cforge test -c Release -- Math Add # Specific tests cforge test -v # Verbose output

Benchmarks

[benchmark] directory = "bench" framework = "google" # google, nanobench, catch2 auto_link_project = true # Link project library
cforge bench # Run all benchmarks cforge bench --filter 'BM_Sort' # Run matching benchmarks cforge bench --no-build # Skip rebuild cforge bench --json > results.json # JSON output cforge bench --csv # CSV output cforge bench -c Release # Build configuration

Supported frameworks:

  • Google Benchmark - Industry-standard microbenchmarking
  • nanobench - Header-only, easy to integrate
  • Catch2 BENCHMARK - Use Catch2's built-in benchmarking

Benchmarks run in Release mode by default for accurate timing. Files with 'bench' or 'perf' in the name are auto-discovered.


Developer Tools

Code Formatting

cforge fmt # Format all source files cforge fmt --check # Check without modifying cforge fmt --diff # Show what would change cforge fmt --style=google # Use specific style

Uses .clang-format if present. Requires clang-format.

Static Analysis

cforge lint # Run clang-tidy checks cforge lint --fix # Apply automatic fixes cforge lint --checks='modernize-*' # Run specific checks

Uses .clang-tidy if present. Requires clang-tidy.

Documentation

cforge doc # Generate Doxygen docs cforge doc --init # Create Doxyfile only cforge doc --open # Generate and open in browser cforge doc -o api-docs # Custom output directory

Requires Doxygen.

Watch Mode

cforge watch # Watch and rebuild cforge watch --run # Also run after build cforge watch -c Release # Watch with Release config cforge watch --interval 1000 # Custom poll interval (ms)

Watches .cpp, .cc, .cxx, .c, .hpp, .hxx, .h, .toml files.


Cross-Compilation

[cross.profile.android-arm64] system = "Android" processor = "aarch64" toolchain = "${ANDROID_NDK}/build/cmake/android.toolchain.cmake" variables = { ANDROID_ABI = "arm64-v8a" } [cross.profile.raspberry-pi] system = "Linux" processor = "arm" compilers = { c = "arm-linux-gnueabihf-gcc", cxx = "arm-linux-gnueabihf-g++" }
cforge build --profile android-arm64 cforge build --profile raspberry-pi

Embedded / Bare-Metal Development

Cross-compilation profiles support embedded-specific options for bare-metal targets:

[project] name = "blink" version = "0.1.0" c_standard = "99" c_extensions = true # GNU extensions (gnu99) languages = ["C", "ASM"] # Enable C and assembly binary_type = "executable" [build] source_dirs = ["src"] include_dirs = ["include"] defines = ["F_CPU=16000000UL"] [build.config.release] optimize = "size" [compiler.gcc] flags = ["-mmcu=atmega328p", "-funsigned-char", "-ffunction-sections", "-fdata-sections"] [linker] scripts = ["link/linker.ld"] flags = ["-mmcu=atmega328p"] dead_code_strip = true map_file = true [cross.profile.avr] system = "Generic" processor = "avr" compilers = { c = "avr-gcc", cxx = "avr-g++" } variables = { CMAKE_ASM_COMPILER = "avr-gcc" } nostdlib = true nostartfiles = true nodefaultlibs = true post_build = [ "avr-objcopy -R .eeprom -O ihex $<TARGET_FILE:${PROJECT_NAME}> $<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.hex", "avr-size --mcu=atmega328p -C $<TARGET_FILE:${PROJECT_NAME}>" ] flash = "avrdude -c arduino -p atmega328p -P /dev/ttyUSB0 -b 115200 -D -U flash:w:$<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.hex"
# Create an embedded project from template cforge init blink --template embedded # Build for target cforge build --profile avr # Flash firmware cforge flash --profile avr

Embedded Profile Options

Option Type Description
nostdlib bool Link with -nostdlib (no standard library)
nostartfiles bool Link with -nostartfiles (no default startup code)
nodefaultlibs bool Link with -nodefaultlibs (no default libraries)
post_build [string] Commands to run after build (e.g., ELF to HEX conversion)
flash string Command to flash/upload firmware to device

Post-build commands run automatically after cforge build --profile <name>. Flash commands are invoked with cforge flash --profile <name>.


IDE Integration

cforge ide vscode # Generate VS Code config cforge ide clion # Generate CLion project cforge ide vs # Open in Visual Studio cforge ide xcode # Generate Xcode project (macOS)

Packaging

[package] enabled = true generators = ["ZIP", "TGZ", "DEB"] vendor = "Your Name" contact = "you@example.com"
cforge package # Create packages cforge package -c Release # Package release build cforge package -t ZIP # Specific generator cforge package --no-build # Skip rebuild

Installation

Install a project to the system:

cforge install # Install to default location cforge install --to /opt/myapp # Custom install path cforge install --add-to-path # Add to PATH cforge install --from https://github.com/user/repo.git # From URL

CMake Options

[build] export_compile_commands = true # CMAKE_EXPORT_COMPILE_COMMANDS position_independent_code = true # CMAKE_POSITION_INDEPENDENT_CODE [build.cmake_variables] MY_OPTION = "ON" CUSTOM_VAR = "value"

Advanced CMake

[cmake] includes = ["cmake/custom.cmake"] module_paths = ["cmake/modules"] inject_before_target = "find_package(Boost REQUIRED)" inject_after_target = "target_precompile_headers(${PROJECT_NAME} PRIVATE pch.h)"

Project Structure

myproject/ ├── cforge.toml # Project configuration ├── cforge.lock # Dependency lock file ├── src/ │ └── main.cpp ├── include/ │ └── myproject/ ├── tests/ │ └── test_main.cpp ├── bench/ │ └── benchmark.cpp └── build/ # Build output (generated) 

Cleaning

cforge clean # Clean current config cforge clean --all # Clean all configurations cforge clean -c Release # Clean specific config cforge clean --cmake-files # Also clean CMake files cforge clean --regenerate # Regenerate after clean cforge clean --deep # Remove dependencies too

Upgrading cforge

cforge upgrade # Upgrade cforge to latest version cforge upgrade --path /opt/cforge # Upgrade to custom location cforge deps update # Refresh package registry

Data Locations

cforge stores all data in a single location per platform:

Windows: %LOCALAPPDATA%\cforge\

%LOCALAPPDATA%\cforge\ ├── installed\cforge\bin\cforge.exe # Binary installation ├── cache\ # Binary cache for dependencies ├── registry\ # Package registry index └── config.toml # Global configuration 

Linux/macOS: ~/.local/share/cforge\ (XDG compliant)

~/.local/share/cforge/ ├── installed/cforge/bin/cforge # Binary installation ├── cache/ # Binary cache └── registry/ # Package registry ~/.config/cforge/ └── config.toml # Global configuration 

Troubleshooting

Build fails with missing dependencies

cforge deps list # List current dependencies cforge deps tree # Visualize dependency tree cforge deps lock --verify # Check lock file cforge deps outdated # Check for newer versions

Clean rebuild

cforge clean --all cforge build

Force regenerate CMake

cforge build --force-regenerate

Verbose output

cforge build -v cforge test -v

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

cforge is licensed under the PolyForm Noncommercial License.

Packages

 
 
 

Contributors