Simple, componentβfirst CMake helper for small & medium C/C++ projects
Quick Start β’ Documentation β’ Examples β’ API Reference
abcmake (Andrei's Build CMake subsystem) lets you structure codebases as independent components with minimal boilerplate. Drop folders under components/, call one function, and get automatic target creation, include paths, and linking.
file(GLOB_RECURSE SOURCES "src/*.cpp")
add_library(mylib ${SOURCES})
target_include_directories(mylib PUBLIC include)
add_subdirectory(components/comp_a)
target_link_libraries(mylib PUBLIC comp_a)
add_subdirectory(components/comp_b)
target_link_libraries(mylib PUBLIC comp_b)
# Repeat for every component... |
include(ab.cmake)
add_component(mylib)
# Done! All components auto-discovered
# and linked, includes configured |
| Problem | abcmake Solution |
|---|---|
π Repeating add_library + globbing everywhere |
Single add_component() with auto-discovery |
| π¦ Hard to reuse internal modules | Component folders become portable units |
| π Tedious dependency wiring | Automatic linking + optional registry |
| π Vendored CMake packages cumbersome | Auto-detect & link *Config.cmake packages |
| π Monolithic CMakeLists.txt growth | Natural split by component directory |
- β¨ Zero dependencies - Pure CMake 3.15+, no Python or external tools
- π― Convention over configuration - Sensible defaults, override when needed
- π Automatic discovery - Recursive component detection and linking
- π Component registry - Link by name instead of path
- π§© Component sets - Bulk registration without building
- π Package auto-detection - Vendored
*Config.cmakepackages just work - π·οΈ Automatic aliases -
<name>::<name>for parent project compatibility - π οΈ IDE support - Generates
compile_commands.jsonby default - π¦ Single-file distribution - Just download
ab.cmake
Download ab.cmake to your project root.
git clone https://github.com/an-dr/abcmake.git
cd abcmake
cmake -B build
cmake --install build --prefix ~/.localπ Detailed Installation Guide
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(MyApp)
include(ab.cmake)
add_main_component(${PROJECT_NAME})src/main.cpp:
#include <iostream>
int main() {
std::cout << "Hello, abcmake!" << std::endl;
return 0;
}Build:
cmake -B build
cmake --build build
./build/MyAppcomponents/greeter/CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(greeter)
include(../../ab.cmake)
add_component(${PROJECT_NAME})components/greeter/include/greeter/greeter.hpp:
#pragma once
#include <string>
std::string greet(const std::string& name);components/greeter/src/greeter.cpp:
#include "greeter/greeter.hpp"
std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}That's it! The component is automatically discovered, built, and linked.
- π Quick Start Guide - Get up and running in 5 minutes
- π¦ Installation Guide - Detailed installation options
- π‘ Core Concepts - Understand the component model
- π API Reference - Complete function documentation
- π§ Examples - Real-world usage patterns
- π Changelog - Version history and changes
- π€ Contributing Guide - How to contribute
- π Issue Tracker - Report bugs or request features
my_project/
βββ CMakeLists.txt # include(ab.cmake) + add_main_component()
βββ ab.cmake # Single-file abcmake distribution
βββ src/ # Main application sources
β βββ main.cpp
βββ include/ # (Optional) Public headers
β βββ myapp/
β βββ config.hpp
βββ components/ # Auto-discovered components
βββ component_a/
β βββ CMakeLists.txt # add_component(component_a)
β βββ include/component_a/
β β βββ api.hpp
β βββ src/
β βββ impl.cpp
βββ component_b/
βββ CMakeLists.txt
βββ ...
# Create main executable with auto-discovery
add_main_component(<name> [SOURCE_DIR ...] [INCLUDE_DIR ...])
# Create library component (static by default)
add_component(<name> [SHARED|INTERFACE] [SOURCE_DIR ...] [INCLUDE_DIR ...])
# Register components for name-based linking
register_components(<path>...)
# Link components by path or name
target_link_components(<target> [PATH <path>...] [NAME <name>...])
# Bulk register components without building
add_component_set([PATH <path>] [COMPONENTS ...] [REGISTER_ALL])π Complete API Documentation
add_component(core
SOURCE_DIR src generated
INCLUDE_DIR include public_api)# Register once
register_components(
${CMAKE_CURRENT_LIST_DIR}/components/logger
${CMAKE_CURRENT_LIST_DIR}/components/config)
# Link by name anywhere
target_link_components(app NAME logger config)add_component(myplugin SHARED)add_component(templates INTERFACE)π More Examples
- CMake 3.15 or higher
- C/C++ compiler (GCC, Clang, MSVC, etc.)
- Platforms: Linux, macOS, Windows
Can I use abcmake with existing CMake projects?
Yes! abcmake components create standard CMake targets with <name>::<name> aliases. Parent projects can use them with add_subdirectory() whether or not they use abcmake.
Does abcmake support header-only libraries?
Absolutely! Use add_component(<name> INTERFACE) for header-only components.
How do I integrate third-party libraries?
Drop vendored libraries with *Config.cmake into components/ - they're auto-detected and linked. Or use standard CMake find_package() and target_link_libraries().
Can components have sub-components?
Yes! Components can have their own components/ directory with nested components. Discovery is recursive.
Is abcmake suitable for large projects?
abcmake is optimized for small to medium projects. Very large monorepos may prefer native CMake patterns for fine-grained control.
- π One logical component per
CMakeLists.txt(keeps components focused) - π― Best suited for small/medium projects (large monorepos may need more control)
- π§ Convention-based (less flexibility than raw CMake for complex scenarios)
We welcome contributions! Please see our Contributing Guide for:
- π Reporting bugs
- π‘ Suggesting features
- π§ Development setup
- β Running tests
- π Documentation improvements
Testing:
cd tests
python -m unittest discover -vMIT License Β© Andrei Gramakov
See LICENSE for details.
Made with β€οΈ by the abcmake community