Mule is a lightweight, convention-over-configuration build tool for C++ developers. Inspired by Rust's Cargo, Mule simplifies project scaffolding, handles incremental builds, and manages dependencies directly from Git repositories or local paths without the complexity of CMake.
- Zero Configuration: Start a project in seconds.
- Incremental Builds: Only recompiles files that have changed, saving you time.
- Advanced Dependency Management: Supports Git repositories (with commit/tag/branch locking) and local path dependencies.
- Integrated Testing Framework: Built-in
mule testcommand with a lightweight header-only assertion library. - Library & Executable Support: Easily create static libraries, shared libraries, or executables.
- Native TOML Configuration: Manage your project settings in a human-readable
mule.tomlfile. - Compiler Agnostic: Automatically detects and uses GCC, Clang, or MSVC on your system.
- Cross-Platform Ready: Works seamlessly on Linux, macOS, and Windows.
- A C++17 compatible compiler (
g++,clang++, orcl.exe). git(for dependency management).
If you don't want to build from source, download the latest pre-compiled binary:
- Download the
mulebinary from the Releases page. - Make it executable and move it to your path:
chmod +x mule
sudo mv mule /usr/local/bin/- Clone the repository:
git clone https://github.com/mahmudsudo/mule.git
cd mule- Compile the binary (choose your compiler):
Using GCC:
g++ -std=c++17 src/main.cpp src/core/*.cpp -o muleUsing Clang:
clang++ -std=c++17 src/main.cpp src/core/*.cpp -o muleUsing MSVC (Windows): Open a Developer Command Prompt for VS and run:
cl /std:c++17 /EHsc src/main.cpp src/core/*.cpp /Fe:mule.exe- Move the binary to your
PATH.
Check out the examples directory to see Mule in action with:
- Simple Hello World
- Static Libraries
- Qt Integration
- Custom Code Generators
Generate a standard executable project:
mule new my_projectOr a library project:
mule new my_lib --libConfigure your dependencies in mule.toml.
You can point to a Git repository and optionally specify a tag, commit, or branch.
[dependencies]
fmt = "https://github.com/fmtlib/fmt.git" # Latest master
json = { git = "https://github.com/nlohmann/json.git", commit = "bc889af" }
range-v3 = { git = "https://github.com/ericniebler/range-v3.git", tag = "0.12.0" }Useful for monorepos or local development.
[dependencies]
my_utils = { path = "../my_utils" }Run mule fetch to download dependencies. This generates a mule.lock file, pinning the exact commit hashes for reproducible builds.
Note
CMake Integration: Mule automatically detects CMakeLists.txt in your dependencies. It will run the CMake build process and automatically link the generated libraries, as well as discover include directories.
Control how your project is built with the [build] and [package] sections.
[package]
name = "my_app"
standard = "20"
type = "bin" # Options: "bin" (default), "static-lib", "shared-lib"
[build]
include_dirs = ["include", "third_party/include"]
lib_dirs = ["/usr/local/lib"]
libs = ["curl", "pthread", "m"]
flags = ["-O3", "-Wall"]
defines = ["ENABLE_LOGGING", "VERSION_MAJOR=1"]Mule supports generic code generation hooks. This is useful for tools like Protobuf, FlatBuffers, or custom codegen.
[[generator]]
name = "proto"
input_extension = ".proto"
output_extension = ".pb.cc"
command = "protoc {input} --cpp_out=build/generated"{input}: The source file path.{output}: The target file path inbuild/generated/.match_content(optional): Only run if file contains this string.
Mule has first-class support for Qt projects. It automatically handles MOC, UIC, and RCC.
[qt]
enabled = true
modules = ["Core", "Widgets", "Gui"]Enabling Qt automatically adds generators for:
- MOC: Runs on headers containing
Q_OBJECTorQ_GADGET. - UIC: Runs on
.uifiles. - RCC: Runs on
.qrcfiles.
Mule supports CUDA projects out of the box. It detects nvcc and handles .cu file compilation and linking.
[cuda]
enabled = true- Automatic Linking: When CUDA is enabled, Mule automatically links against the CUDA runtime (
cudart). - Source Discovery: Mule automatically finds and compiles
.cufiles in yoursrc/directory.
| Command | Description |
|---|---|
mule new <name> |
Create a new executable project. |
mule new <name> --lib |
Create a new library project. |
mule build |
Compile the project. |
mule run |
Build and execute the project (if it's a binary). |
mule test |
Discover and run tests (unit and integration). |
mule fetch |
Download and update dependencies. |
mule clean |
Remove the build/ directory and artifacts. |
Mule follows Rust's Cargo convention for a professional C++ testing experience.
Unit tests are co-located with your source code. Any file in src/ ending with _test.cpp is treated as a unit test and compiled with your library code.
src/utils_test.cpp:
#include "mule_test.h"
#include "utils.h"
MULE_TEST(addition) {
MULE_ASSERT(add(1, 1) == 2);
}Standalone tests reside in the tests/ directory. Each .cpp file here is compiled as its own separate executable, ensuring you only use the public interface of your library.
tests/api_test.cpp:
#include "mule_test.h"
#include "my_lib.h"
int main() {
// Integration tests can have their own main or use MULE_TEST with a generated runner
return 0;
}Run all tests with a single command:
mule testMule follows a standard convention:
src/: Core source files.include/: Public headers.tests/: Integration tests..mule/deps/: Managed dependencies (don't edit manually).mule.lock: Generated dependency lockfile.build/: Compilation artifacts and final binaries.
This is an experimental tool built to improve the C++ developer experience. Feel free to open issues or submit pull requests.