menuconfig++

A standalone configuration tool derived from the Linux kernel's kconfig / mconf. Configure your project's macros through the familiar menu UI and generate an sdkconfig that CMake can read directly as compile definitions.

The main menu of menuconfig++: a title bar reading .config - Main Menu, a navigable list of configuration entries, and Select / Exit / Help buttons at the bottom
mconf .config - Main Menu

# Features

# Install

Option 1: prebuilt binary

Grab menuconfig-plusplus-<version>-linux-x86_64.tar.gz from Releases. It unpacks to mconf (menu UI) and conf (command line):

$ tar -xzf menuconfig-plusplus-*-linux-x86_64.tar.gz
$ cd menuconfig-plusplus-*
$ ./mconf test/rootconf

Option 2: build from source

The only dependencies are a C compiler and the ncurses development library (it provides the wide-character library used below):

# Debian / Ubuntu
$ sudo apt install -y libncurses-dev cmake ninja-build

$ git clone https://github.com/luskyle/menuconfig-plusplus.git
$ cd menuconfig-plusplus
$ cmake -S . -B build -G Ninja
$ cmake --build build
The build type is controlled by -DDEBUG and -DCMAKE_BUILD_TYPE: DEBUG=ON (the default) yields a Debug build with debug info, while -DDEBUG=OFF yields Release; an explicit -DCMAKE_BUILD_TYPE=... always wins.

# Usage

Menu UI

$ ./mconf test/rootconf

Point it at your own kconfig entry file instead of test/rootconf. On exit, choosing to save writes the configuration to sdkconfig.

A compact main menu: the title bar reads sdkconfig - Main Menu and lists HEX parameter, Three states, Subconfmenu, Subconfmenu2 and Save as
mconf sdkconfig - Main Menu

Command line (non-interactive)

conf shares the same parser as the menu UI, so it fits scripts and CI pipelines:

OptionDescription
--listnewconfigList new options
--oldaskconfigStart a new configuration using a line-oriented program
--oldconfigUpdate a configuration using a provided .config as base
--silentoldconfig <file>Same as oldconfig, but quietly; write header to <file>
--olddefconfigSame as silentoldconfig but sets new symbols to their default value
--oldnoconfigAn alias of olddefconfig
--defconfig <file>New config with default defined in <file>
--savedefconfig <file>Save the minimal current configuration to <file>
--allnoconfigNew config where all options are answered with no
--allyesconfigNew config where all options are answered with yes
--allmodconfigNew config where all options are answered with mod
--alldefconfigNew config with all symbols set to default
--randconfigNew config with random answer to all options
$ ./conf --alldefconfig test/rootconf
configuration written to sdkconfig

The generated sdkconfig

#
# Automatically generated file; DO NOT EDIT.
# Main Menu
#
CONFIG_GEN_CHOICE1=y
# CONFIG_GEN_CHOICE2 is not set
CONFIG_STRING_PARAM=""
CONFIG_NUM_PARAM=0

# Wiring it into CMake

Read sdkconfig and turn each CONFIG_* into a compile definition (excerpt; the full version is in the README):

file(STRINGS sdkconfig lines NEWLINE_CONSUME)
string(REGEX MATCHALL "(CONFIG[a-zA-Z_0-9]+)=([a-zA-Z0-9\"]+)" result ${lines})

foreach(line ${result})
    string(REPLACE "=" ";" pv ${line})
    list(GET pv 0 p)
    list(GET pv 1 v)

    if(v STREQUAL "y")
        add_compile_definitions(${p})
    else()
        add_compile_definitions(${line})
    endif()
endforeach()

# Known issues