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
}
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
}
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 }
}
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.txtcompatibility 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:
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.
"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.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
Compiler: g++
Output: game.exe
InputFiles {
src/*.cpp
}
hm -b
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)