DEV Community

RZM64
RZM64

Posted on

I was tired of writing CMake. So I built a simpler build system.

The frustration

I didn't start building HelpMake because I was bored. I started because CMake kept breaking on me.

It would not work for me, Cmake was bugging, crashing, complex to learn, annoying,...

At some point I realized I wasn't the only one. Every C++ Discord, every Reddit thread, every "what's wrong with my build" question, it's the same story. People don't hate CMake because it's bad. They hate it because it's a lot, and it breaks in ways that aren't obvious, and every project needs a slightly different incantation to make it work.

I don't build 100,000-file projects. I build 5–20 file projects. Sometimes 50. For that scope, CMake is a lot of machinery for a small job, and the failure modes are worse than the thing it's trying to solve.

So I built a build system where the whole config fits on one screen and you build with one command.

The CMakeLists.txt itself isn't really the problem. It's everything around it. The generator step. The out-of-source build requirement. The "why is it building in Debug when I didn't specify". The "why does this work on Linux but not Windows".

I don't build 100,000-file projects. I build 5–20 file projects. Sometimes 50. For that scope, CMake is a lot of ceremony for a small job.

What if it was one file?

I wanted a build system where the whole config fits on one screen and you build with one command. Not one command to configure another to build. Just one.

So I built one. It's called HelpMake. The entire config for a small C++ project:

Compiler: g++
Version: std=c++20
Output: build/app

InputFiles {
    src/**/*.cpp # built-in recursive glob
}

Includes {
    include
}

Flags {
    -Wall
    -O2
}
Enter fullscreen mode Exit fullscreen mode

hm -b and you get a binary. No configure step, no generator, no build directory you have to manage.

Wait, another build system?

I know. There are dozens. But every one I tried had the same problem:

  • Make - doable, but you can't see the whole build script on one screen, and it's not cross-platform by design
  • CMake - powerful, but a lot of ceremony for small projects
  • Meson - nice, but you still configure before you build
  • Bazel - for Google-scale monorepos, not side projects
  • Ninja - a backend, not something you write by hand

The gap I kept running into: there's a "too much" tier (CMake, Bazel, Meson) and a "too raw" tier (Make, Ninja), but no lightweight tier that's actually simple.

That's the tier I wanted.

What's actually interesting about it

The basic config isn't the interesting part. It's how a build system should work. These three things are why people actually use HelpMake:

1. Cross-platform without duplication

On Windows you want /W4 and /EHsc. On Linux you want -Wall -Wextra -pthread. In CMake that's if(WIN32) ... else() ... endif() blocks. In HelpMake:

Flags {
    -Wall
    win: /W4 /EHsc
    linux: -Wextra -pthread
    mac: -Wextra
    x64: -march=native
}
Enter fullscreen mode Exit fullscreen mode

The win: and linux: prefixes are platform conditionals. Any line can have one. One config for every OS.

2. hm test - a real test runner

Mark configs as tests:

Config: test-core {
    Test: true                  # Save as test
    Output: build/test-core
    InputFiles { tests/core.cpp }
}
Enter fullscreen mode Exit fullscreen mode

hm test builds and runs every marked config. Exit code 1 on failure. That's what CI needs, built in, no separate ctest step.

3. hm -b -w - watch mode

Save a file, rebuild. Save a file, rebuild. hm -b -w -r builds, runs, and rebuilds on save. That's the entire dev loop in one command.

Honest caveats

HelpMake isn't trying to replace CMake. It won't:

  • Generate Visual Studio solutions
  • Auto-detect hundreds of system libraries (you write Dependency: raylib { ... } for external libs)
  • Handle 100,000-file projects
  • Give you CMakeLists.txt compatibility if you need to hand the project to someone using CMake

If you need any of those, use CMake. Seriously.

HelpMake is for the projects where CMake feels like overkill - which, for a solo dev or a small team, is most of them.

What I learned building it

Three things I didn't expect:

  1. C++20 modules are still a mess in build systems. Every compiler handles them differently. Getting GCC and Clang working end-to-end took more time than the rest of the parser combined.

  2. "Just one more flag" is how build configs get to 200 lines. Every feature I added had to justify why the user can't just put it in Flags { }. That constraint kept the file format small.

  3. The hard part isn't the build system. It's the error messages. A build system that fails with "compilation failed" is useless. HelpMake tries to say HelpMake.txt:42: unknown field 'Compilr:' - did you mean 'Compiler:'? Getting those right is most of the work.

Try it

If you've read this far, you probably have a project in mind where CMake feels like too much. HelpMake might be for you.

hm --install    # or build from source, ~30 seconds
Enter fullscreen mode Exit fullscreen mode
Compiler: g++
Output: game.exe
InputFiles {
    src/*.cpp
}
Enter fullscreen mode Exit fullscreen mode
hm -b
Enter fullscreen mode Exit fullscreen mode

MIT licensed. Single binary, no runtime dependencies. If it's useful, a ⭐ on the repo helps other people find it.

If it's not useful - if CMake is the right tool for your project - that's completely fine, and I'd love to hear what your CMake setup looks like. That's the kind of feedback that makes the next version better.

  • Xavi

Top comments (0)