luban.cmake generated module

The cmake module luban generates and include()s into your project. Git-tracked — committed alongside source, so non-luban machines can build the project too.

Anatomy

# generated by luban — DO NOT EDIT BY HAND
# regenerate via: luban add / remove / sync / target add / target remove
# project deps come from vcpkg.json; flags come from luban.toml ([scaffold] section).

# ---- targets (LUBAN_TARGETS) ----
set(LUBAN_TARGETS calc mathlib)

# ---- find_package (auto from vcpkg.json dependencies) ----
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)

# ---- luban_apply: call once per target after add_executable / add_library ----
function(luban_apply target)
    target_compile_features(${target} PRIVATE cxx_std_23)
    if(NOT MSVC)
        target_compile_options(${target} PRIVATE -Wall -Wextra)
        # static-link toolchain runtime so the exe runs without toolchain DLLs on PATH.
        target_link_options(${target} PRIVATE -static -static-libgcc -static-libstdc++)
    endif()
    target_link_libraries(${target} PRIVATE
        fmt::fmt
        spdlog::spdlog
    )
endfunction()

# ---- luban_register_targets: call once from root CMakeLists.txt ----
function(luban_register_targets)
    foreach(t IN LISTS LUBAN_TARGETS)
        if(EXISTS ${CMAKE_SOURCE_DIR}/src/${t}/CMakeLists.txt)
            add_subdirectory(src/${t})
        else()
            message(WARNING "luban: target '${t}' has no src/${t}/CMakeLists.txt; skipping")
        endif()
    endforeach()
endfunction()

Three concerns, three sections

SectionSourceWhat it controls
LUBAN_TARGETSluban target add/removeWhich subdirs luban_register_targets() walks
find_package(...)vcpkg.json dependenciesWhich vcpkg libs are imported
luban_apply(target) bodyluban.toml [scaffold] + vcpkg.json depsFlags + library links applied per target

Inputs

vcpkg.json          → dependencies (drives find_package + target_link_libraries)
luban.toml          → cpp, warnings, sanitizers (drive compile_features + compile_options)
luban.cmake itself  → LUBAN_TARGETS list (read back via parse so target add/remove are atomic)

How users interact

The user's root CMakeLists.txt is just:

cmake_minimum_required(VERSION 3.25)
project(foo CXX)
include(${CMAKE_SOURCE_DIR}/luban.cmake)
luban_register_targets()

Each src/<target>/CMakeLists.txt does:

add_executable(foo main.cpp)
luban_apply(foo)
# user can add target_link_libraries / target_compile_options here

That's the full surface area. Two function calls per project.

When luban.cmake is regenerated

  • luban add <pkg> / luban remove <pkg> — find_package + link list updated
  • luban sync — full regen from vcpkg.json + luban.toml
  • luban target add / luban target remove — LUBAN_TARGETS updated, rest preserved if vcpkg.json/luban.toml unchanged

The whole file is rewritten each time (no diff/merge); user-edits to luban.cmake will be lost. Don't edit it by hand. The header comment says this; the user-facing contract is: write your custom cmake outside this file.

Why this shape

See Architecture → Why no IR for the full rationale.