Skip to content

ChaseSunstrom/cforge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚠️ WARNING: BETA VERSION ⚠️

🚨 This software is currently in BETA. Features may be incomplete, contain bugs, or change without notice, and being frequently updated. Use at your own risk.

  • Not recommended for production environments
  • Data loss or corruption may occur
  • APIs are subject to change without warning
  • Limited support available

Please report any bugs or issues in the Issues section.

CForge

Version License

A TOML-based build system for C/C++ projects with seamless CMake and vcpkg integration.

CForge is a modern build system designed to simplify C/C++ project management. It provides a clean TOML-based configuration approach while leveraging the power of CMake and vcpkg under the hood.


πŸ“– Table of Contents

  1. Features
  2. Installation
  3. Quick Start
  4. Command Reference
  5. Project Configuration
  6. Working with Dependencies
  7. Workspaces
  8. Build Variants
  9. Cross-Compilation
  10. IDE Integration
  11. Scripts & Hooks
  12. Testing
  13. Advanced Topics
  14. Examples
  15. Troubleshooting
  16. Goals & Roadmap
  17. Contributing
  18. License

πŸš€ Features

  • Simple TOML Configuration: Easy project setup without complex CMake syntax
  • Multi-platform: Supports Windows, macOS, Linux
  • Dependency Management: Integrated support for vcpkg, Conan, Git, and custom dependencies
  • Workspaces: Manage multiple projects together with dependency resolution
  • Cross-compilation: Support for Android, iOS, Raspberry Pi, WebAssembly
  • IDE Integration: VS Code, CLion, Xcode, Visual Studio
  • Testing: Integrated with CTest
  • Custom Scripts & Hooks: Run project-specific tasks at various stages
  • Automatic Tool Setup: Installs missing tools automatically
  • Enhanced Diagnostics: Clear, informative compiler errors
  • Build Variants: Easily switch between different build configurations
  • Package Management: Create distributable packages for your software

πŸ“₯ Installation

From Cargo

cargo install cforge@version-beta
# For example cforge@1.4.2-beta

From Source

git clone https://github.com/ChaseSunstrom/cforge.git
cd cforge
cargo build --release
cargo install --path .

Prerequisites

  • Rust
  • CMake (β‰₯3.15)
  • C/C++ Compiler (GCC, Clang, MSVC)
  • Optional: Ninja, Make, or Visual Studio Build Tools

⚑ Quick Start

Creating a New Project

# Create a new project in the current directory
cforge init

# Create a specific project type
cforge init --template lib     # Create a library project
cforge init --template header-only  # Create a header-only library

# Build the project
cforge build

# Run the executable (for application projects)
cforge run

Example Project Structure

After initializing a project with cforge init, you'll have a structure like this:

myproject/
β”œβ”€β”€ cforge.toml         # Project configuration
β”œβ”€β”€ src/
β”‚   └── main.cpp        # Main source file
β”œβ”€β”€ include/            # Header files
β”œβ”€β”€ scripts/            # Custom scripts
└── build/              # Build artifacts (generated)

Example C++ Code

src/main.cpp (generated automatically):

#include <iostream>

int main(int argc, char* argv[]) {
    std::cout << "Hello, cforge!" << std::endl;
    return 0;
}

Build and Run

$ cforge build
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           cforge - C/C++ Build System            β”‚
β”‚                    v1.2.0                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Building: myproject
[1/4] Checking build tools
Checking for required build tools...
CMake: βœ“
Compiler 'clang': βœ“
Build generator 'Ninja': βœ“
vcpkg: βœ“ (will be configured during build)
All required build tools are available.

[2/4] Configuring project
Project configured with generator: Ninja (Debug)

[3/4] Running pre-build hooks
Running pre-build hooks
Running hook: echo Starting build process...
Starting build process...

[4/4] Building project
Building myproject in Debug configuration
βœ“ Compiling 1 source files (completed in 1.2s)

βœ“ Build completed successfully

$ cforge run
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           cforge - C/C++ Build System            β”‚
β”‚                    v1.2.0                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Running: myproject
Found executable: build/bin/myproject
Running: build/bin/myproject

Program Output
────────────
Hello, cforge!

βœ“ Program executed successfully

πŸ› οΈ Command Reference

Command Description Example
init Create new project/workspace cforge init --template lib
build Build the project cforge build --config Release
clean Clean build artifacts cforge clean
run Run built executable cforge run -- arg1 arg2
test Execute tests (CTest integration) cforge test --filter MyTest
install Install project binaries cforge install --prefix /usr/local
deps Manage dependencies cforge deps --update
script Execute custom scripts cforge script format
startup Manage workspace startup project cforge startup my_app
ide Generate IDE project files cforge ide vscode
package Package project binaries cforge package --type zip
list List variants, configs, or targets cforge list variants

Command Options

All commands accept the following global options:

  • --verbosity: Set verbosity level (quiet, normal, verbose)

Many commands support these options:

  • --config: Build/run with specific configuration (e.g., Debug, Release)
  • --variant: Use a specific build variant
  • --target: Specify a cross-compilation target

πŸ“‹ Project Configuration

Basic Configuration

The cforge.toml file is the heart of your project configuration:

[project]
name = "my_project"
version = "0.1.0"
description = "My C/C++ project"
type = "executable"  # executable, library, static-library, header-only
language = "c++"
standard = "c++17"   # c++11, c++14, c++17, c++20, c++23

[build]
build_dir = "build"
default_config = "Debug"
generator = "Ninja"  # Ninja, "Visual Studio 17 2022", NMake Makefiles, etc.

[build.configs.Debug]
defines = ["DEBUG", "_DEBUG"]
flags = ["NO_OPT", "DEBUG_INFO"]

[build.configs.Release]
defines = ["NDEBUG"]
flags = ["OPTIMIZE", "OB2", "DNDEBUG"]

[targets.default]
sources = ["src/**/*.cpp", "src/**/*.c"]
include_dirs = ["include"]
links = []

Target Configuration

A project can have multiple targets (executables or libraries):

[targets.main_app]
sources = ["src/app/**/*.cpp"]
include_dirs = ["include"]
links = ["fmt", "boost_system"]

[targets.utils_lib]
sources = ["src/utils/**/*.cpp"]
include_dirs = ["include/utils"]
links = []

Platform-specific Configuration

[platforms.windows]
defines = ["WINDOWS", "WIN32"]
flags = ["UNICODE"]

[platforms.darwin]
defines = ["OSX"]
flags = []

[platforms.linux]
defines = ["LINUX"]
flags = []

πŸ“¦ Working with Dependencies

CForge supports multiple dependency management systems:

vcpkg Integration

[dependencies.vcpkg]
enabled = true
path = "~/.vcpkg"  # Optional, defaults to ~/.vcpkg
packages = ["fmt", "boost", "nlohmann-json"]

Example C++ code using vcpkg dependencies:

#include <fmt/core.h>
#include <nlohmann/json.hpp>

int main() {
    // Using fmt library from vcpkg
    fmt::print("Hello, {}!\n", "world");
    
    // Using nlohmann/json library from vcpkg
    nlohmann::json j = {
        {"name", "CForge"},
        {"version", "1.2.0"}
    };
    
    fmt::print("JSON: {}\n", j.dump(2));
    return 0;
}

Conan Integration

[dependencies.conan]
enabled = true
packages = ["fmt/9.1.0", "spdlog/1.10.0"]
options = { "fmt:shared": "False", "spdlog:shared": "False" }
generators = ["cmake", "cmake_find_package"]

Git Dependencies

[[dependencies.git]]
name = "nlohmann_json"
url = "https://github.com/nlohmann/json.git"
tag = "v3.11.3"
# Optional settings
shallow = true  # Faster clone with reduced history
update = false  # Whether to update the repo on builds

[[dependencies.git]]
name = "fmt"
url = "https://github.com/fmtlib/fmt.git"
tag = "9.1.0"
cmake_options = ["-DFMT_TEST=OFF", "-DFMT_DOC=OFF"]  # Pass CMake options when building

[[dependencies.git]]
name = "imgui"
url = "https://github.com/ocornut/imgui.git"
branch = "master"  # Use a specific branch instead of tag
shallow = true

[[dependencies.git]]
name = "custom_repo"
url = "https://example.com/repo.git"
commit = "abc123def456"  # Use a specific commit hash

Git dependencies are automatically cloned into a deps directory. The libraries can be included in your project by adding their include paths to your target configuration:

[targets.default]
include_dirs = ["include", "deps/nlohmann_json/single_include", "deps/fmt/include"]
defines = ["FMT_HEADER_ONLY"]  # Optionally add defines for your dependencies

You can also use the libraries in your code immediately:

#include <nlohmann/json.hpp>
#include <fmt/core.h>

int main() {
    // Using nlohmann/json
    nlohmann::json obj = {{"name", "cforge"}, {"version", "1.4.0"}};
    
    // Using fmt
    fmt::print("Project: {}\n", obj["name"].get<std::string>());
    return 0;
}

Custom Dependencies

[[dependencies.custom]]
name = "my_library"
url = "https://example.com/my_library-1.0.0.zip"
include_path = "include"
library_path = "lib"

System Dependencies

[dependencies]
system = ["X11", "pthread", "dl"]

πŸ—‚οΈ Workspaces

Workspaces allow you to manage multiple related projects together:

# Initialize a workspace
cforge init --workspace

# Initialize a project within the workspace
cd projects
cforge init --template lib

# Build all projects
cd ..
cforge build

# Build a specific project
cforge build my_lib

# Run a specific project
cforge run my_app

Workspace Configuration

# cforge-workspace.toml
[workspace]
name = "my_workspace"
projects = ["projects/app", "projects/lib"]
default_startup_project = "projects/app"

Project Dependencies within Workspace

# projects/app/cforge.toml
[dependencies.workspace]
name = "lib"
link_type = "static"  # static, shared, interface

🚩 Build Variants

Build variants allow for different build configurations beyond just Debug/Release:

[variants]
default = "standard"

[variants.variants.standard]
description = "Standard build"

[variants.variants.performance]
description = "Optimized build"
defines = ["HIGH_PERF=1"]
flags = ["OPTIMIZE_MAX", "LTO"]

[variants.variants.memory_safety]
description = "Build with memory safety checks"
defines = ["ENABLE_MEMORY_SAFETY=1"]
flags = ["MEMSAFE"]

Building with variants:

cforge build --variant performance

🌐 Cross-Compilation

CForge supports cross-compilation for various platforms:

[cross_compile]
enabled = true
target = "android-arm64"
sysroot = "$ANDROID_NDK/platforms/android-24/arch-arm64"
cmake_toolchain_file = "$ANDROID_NDK/build/cmake/android.toolchain.cmake"
flags = ["-DANDROID_ABI=arm64-v8a", "-DANDROID_PLATFORM=android-24"]

Cross-compilation targets:

  • android-arm64: Android ARM64 platform
  • android-arm: Android ARM platform
  • ios: iOS ARM64 platform
  • raspberry-pi: Raspberry Pi ARM platform
  • wasm: WebAssembly via Emscripten

Example:

cforge build --target android-arm64

πŸ–₯️ IDE Integration

Generate IDE-specific project files:

# VS Code
cforge ide vscode

# CLion
cforge ide clion

# Xcode (macOS only)
cforge ide xcode

# Visual Studio (Windows only)
cforge ide vs2022
cforge ide vs:x64  # With architecture specification

Example VS Code launch configuration (generated automatically):

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug",
      "type": "cppdbg",
      "request": "launch",
      "program": "${workspaceFolder}/build/bin/${workspaceFolderBasename}",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "build"
    }
  ]
}

πŸ“ Scripts & Hooks

Define custom scripts and build hooks:

[scripts]
scripts = {
  "format" = "clang-format -i src/*.cpp include/*.h",
  "count_lines" = "find src include -name '*.cpp' -o -name '*.h' | xargs wc -l",
  "clean_all" = "rm -rf build bin"
}

[hooks]
pre_build = ["echo Building...", "python scripts/version_gen.py"]
post_build = ["echo Done!", "cp build/bin/myapp /tmp/"]
pre_run = ["echo Starting application..."]
post_run = ["echo Application closed."]

Running scripts:

cforge script format

πŸ§ͺ Testing

CForge integrates with CTest for testing:

[tests]
directory = "tests"
enabled = true
timeout = 30  # seconds

[[tests.executables]]
name = "math_tests"
sources = ["tests/math_test.cpp"]
includes = ["include", "tests/common"]
links = ["my_project"]
labels = ["unit", "math"]

Example test file (tests/math_test.cpp):

#include <iostream>
#include <cassert>
#include "my_project.h"

void test_addition() {
    assert(my_project::add(2, 3) == 5);
    std::cout << "Addition test passed!" << std::endl;
}

void test_multiplication() {
    assert(my_project::multiply(2, 3) == 6);
    std::cout << "Multiplication test passed!" << std::endl;
}

int main() {
    test_addition();
    test_multiplication();
    std::cout << "All tests passed!" << std::endl;
    return 0;
}

Running tests:

# Run all tests
cforge test

# Run tests with a specific label
cforge test --label unit

# Run tests matching a pattern
cforge test --filter math

# Initialize test directory with sample test
cforge test --init

# Discover tests and update config
cforge test --discover

# Generate test reports
cforge test --report xml

🧩 Advanced Topics

Precompiled Headers

[pch]
enabled = true
header = "include/pch.h"
source = "src/pch.cpp"  # Optional
exclude_sources = ["src/no_pch.cpp"]

Package Generation

# Create a package (defaults to zip/tar.gz)
cforge package

# Specify package type
cforge package --type deb  # Linux Debian package
cforge package --type rpm  # Linux RPM package
cforge package --type zip  # Zip archive

Installing Projects

# Install to default location
cforge install

# Install to specific directory
cforge install --prefix /usr/local

πŸ“š Examples

Simple Application

# cforge.toml
[project]
name = "hello_app"
version = "1.0.0"
description = "Hello World Application"
type = "executable"
language = "c++"
standard = "c++17"

[build]
default_config = "Debug"

[targets.default]
sources = ["src/**/*.cpp"]
include_dirs = ["include"]
// src/main.cpp
#include <iostream>

int main() {
    std::cout << "Hello, CForge!" << std::endl;
    return 0;
}

Library with vcpkg Dependencies

# cforge.toml
[project]
name = "math_lib"
version = "0.1.0"
description = "Mathematics Library"
type = "library"
language = "c++"
standard = "c++17"

[dependencies.vcpkg]
enabled = true
packages = ["fmt", "doctest"]

[targets.default]
sources = ["src/**/*.cpp"]
include_dirs = ["include"]
// include/math_lib.h
#pragma once

namespace math_lib {
    int add(int a, int b);
    int subtract(int a, int b);
    int multiply(int a, int b);
    int divide(int a, int b);
}
// src/math_lib.cpp
#include "math_lib.h"
#include <fmt/core.h>

namespace math_lib {
    int add(int a, int b) {
        fmt::print("Adding {} and {}\n", a, b);
        return a + b;
    }
    
    int subtract(int a, int b) {
        fmt::print("Subtracting {} from {}\n", b, a);
        return a - b;
    }
    
    int multiply(int a, int b) {
        fmt::print("Multiplying {} by {}\n", a, b);
        return a * b;
    }
    
    int divide(int a, int b) {
        fmt::print("Dividing {} by {}\n", a, b);
        return a / b;
    }
}

Multi-project Workspace

# cforge-workspace.toml
[workspace]
name = "calculator"
projects = ["projects/core", "projects/gui", "projects/cli"]
default_startup_project = "projects/gui"
# projects/core/cforge.toml
[project]
name = "calc_core"
version = "0.1.0"
description = "Calculator Core Library"
type = "library"
language = "c++"
standard = "c++17"

[targets.default]
sources = ["src/**/*.cpp"]
include_dirs = ["include"]
# projects/gui/cforge.toml
[project]
name = "calc_gui"
version = "0.1.0"
description = "Calculator GUI Application"
type = "executable"
language = "c++"
standard = "c++17"

[dependencies.workspace]
name = "calc_core"
link_type = "static"

[dependencies.vcpkg]
enabled = true
packages = ["imgui", "glfw3", "opengl"]

[targets.default]
sources = ["src/**/*.cpp"]
include_dirs = ["include"]

πŸ”§ Troubleshooting

Common Issues

  • CMake not found: Ensure it's installed and in PATH.
  • Dependency failures: Run cforge deps --update.
  • Cross-compilation: Check environment variables (e.g., $ANDROID_NDK).
  • Compiler errors: Use cforge build --verbosity verbose.

CForge provides enhanced error diagnostics:

Build error details:
ERROR[E0001]: undefined reference to 'math_lib::divide(int, int)'
 --> src/main.cpp:12:5
  12| math_lib::divide(10, 0);
     ^~~~~~~~~~~~~~~~

help: The function 'divide' is used but not defined. Check if the library is properly linked.

Useful Commands

# List available configurations
cforge list configs

# List available build variants
cforge list variants

# List cross-compilation targets
cforge list targets

# List custom scripts
cforge list scripts

πŸš€ Goals & Roadmap

CForge is continuously evolving to simplify C/C++ project management while providing powerful features. Here's what we've accomplished and where we're headed next:

βœ… Completed Features

  • Simple TOML Configuration: Easy project setup without complex CMake syntax
  • Multi-platform Support: Windows, macOS, Linux compatibility
  • Core Dependency Management: Integrated vcpkg and git dependencies
  • Workspace Support: Basic multi-project management
  • Cross-compilation: Support for Android, iOS, Raspberry Pi, WebAssembly
  • IDE Integration: VS Code, CLion support
  • Testing: CTest integration
  • Custom Scripts & Hooks: Run tasks at various build stages
  • Build Variants: Multiple configuration support
  • Package Generation: Create distributable packages

🚧 In Progress

  • Enhanced Workspace Dependencies: Improving library detection and linking
  • Precompiled Header Optimization: Better build performance
  • Diagnostic Improvements: Clearer error messages and suggestions
  • Documentation Expansion: More examples and quick-start guides

πŸ“ Planned Features

  • Enhanced IDE Support

    • Better Visual Studio project generation
    • QtCreator integration
    • Eclipse CDT support
    • Xcode project improvements
  • Plugin System

    • Custom build steps via plugins
    • Language server integration
    • Code generation tools
  • Documentation Features

    • Automatic API documentation generation
    • Doxygen integration
  • Advanced Testing

    • Code coverage reports
    • Benchmark framework integration
    • Sanitizer integrations
  • CI/CD Pipeline Integration

    • GitHub Actions templates
    • GitLab CI templates
    • Azure DevOps integration
  • Mobile Development

    • Improved Android/iOS workflows
    • Mobile-specific templates
  • Cloud Development

    • Remote build capabilities
    • Container-based builds
    • Package registry integration
  • Package Manager Enhancements

    • Complete Conan 2.0 support
    • Lock file management
    • Recipe generation

We welcome contributions to help achieve these goals! If you're interested in working on a specific feature or have suggestions, please open an issue or submit a pull request.

🀝 Contributing

Contributions welcome!

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/new-feature)
  3. Commit your changes (git commit -m 'Add new feature')
  4. Push to your branch (git push origin feature/new-feature)
  5. Open a Pull Request

πŸ“„ License

MIT License β€” see LICENSE.