Skip to content

an-dr/abcmake

Repository files navigation

logo

Simple, component‑first CMake helper for small & medium C/C++ projects

GitHub Release Build Test License: MIT CMake 3.15+

Quick Start β€’ Documentation β€’ Examples β€’ API Reference


Overview

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.

Why abcmake?

Traditional CMake

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...

With abcmake

include(ab.cmake)

add_component(mylib)

# Done! All components auto-discovered
# and linked, includes configured

Key Benefits

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

Features

  • ✨ 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.cmake packages just work
  • 🏷️ Automatic aliases - <name>::<name> for parent project compatibility
  • πŸ› οΈ IDE support - Generates compile_commands.json by default
  • πŸ“¦ Single-file distribution - Just download ab.cmake

Quick Start

1. Install

Option A: Project-Scoped (Recommended)

Download ab.cmake to your project root.

Option B: User/System-Wide

git clone https://github.com/an-dr/abcmake.git
cd abcmake
cmake -B build
cmake --install build --prefix ~/.local

πŸ“– Detailed Installation Guide

2. Create Your Project

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/MyApp

3. Add a Component

components/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.

πŸ“– Full Quick Start Guide

Documentation

Getting Started

References

  • πŸ“š API Reference - Complete function documentation
  • πŸ”§ Examples - Real-world usage patterns
  • πŸ“ Changelog - Version history and changes

Contributing

Project Structure

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
        └── ...

API at a Glance

# 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

Examples

Multiple Source Directories

add_component(core
    SOURCE_DIR src generated
    INCLUDE_DIR include public_api)

Component Registry

# 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)

Shared Library

add_component(myplugin SHARED)

Header-Only Library

add_component(templates INTERFACE)

πŸ“– More Examples

Requirements

  • CMake 3.15 or higher
  • C/C++ compiler (GCC, Clang, MSVC, etc.)
  • Platforms: Linux, macOS, Windows

FAQ

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.

Limitations

  • πŸ“‹ 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)

Contributing

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 -v

License

MIT License Β© Andrei Gramakov

See LICENSE for details.


⬆ Back to Top

Made with ❀️ by the abcmake community

About

Minimizes headache with CMake component packaging

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Languages