mkproj
just a dumb bullshit utility that generates build system boilerplate and gets the fuck out of your way.
like, imagine you want to start a new project. maybe it's something scalable, maybe it's just some stupid scratch program to test an idea. either way, before you've written a single line of the thing you actually want to make, you have to pick a build system, because project management in c is fucking cancer. then you have to go out of your way to write a Makefile, or a CMakeLists.txt, or whatever other configuration file your build system decided it needed, instead of just actually writing whatever the fuck it is you wanted to write.
mkproj fixes that. it makes a directory (or uses the one you're in, with mkproj .), generates the boilerplate for the build system you picked — currently make, cmake, meson, premake, and xmake — and that's it. you get a project you can immediately build, and you never use mkproj again.
by default you get a flat c project built with make: the source sits at the root, the binary builds to the root, the object files go under bin/, and it uses the newest language standard. there are a couple of things you can customize: whether it initializes a git repository, the language (c, cpp, objc, nasm, swift, or crust — rust through rustc, no cargo), the language standard, where your sources live, where your build output goes, and whether you want the object files in their own directory. but most of the time, you shouldn't have to think about any of that.
$ mkproj hello
that's a c project using make. cd hello && make run and you're off — the generated makefiles have a run target that builds and runs the thing.
usage
$ mkproj --help
mkproj 0.4.0 - dumb project generator
generates boilerplate for make, cmake, meson or premake so you can stop
writing the same fucking build files every time you start a project.
usage: mkproj [-l lang] [-s std] [-b system] [-k kind] [--cc cc] [--license name]
[--git] [--no-root] [--single] [--no-validation] [--docker]
[--style] [--ci] [--src dir] [--bin dir] [--bin-int dir] <name>
mkproj --completions bash|zsh|fish
mkproj [-v | -h]
<name> is the project directory to create, or . to generate into the
current directory (the project name is taken from its basename).
defaults: a flat C project built with make, binary at the project root,
the latest language standard, and objects under bin/.
options:
-l, --lang LANG language: c, cpp, objc, nasm, swift, crust (default c)
-s, --std STD language standard (default: latest for the language)
-b, --build SYSTEM build system: make, cmake, meson, premake, xmake (default make)
-k, --kind KIND exe, lib (static) or shared (default exe)
--cc CC compiler (default clang/clang++); make, premake, xmake
--license NAME add a LICENSE: mit, isc, bsd-2, bsd-3, unlicense
--git initialize a git repository and write a .gitignore
--src DIR put sources in DIR/ instead of at the project root
--no-root put the binary in the build dir, not the project root
--single single-file project: compile directly, no object dir (make, c family)
--no-validation drop the make check target and the sanitizer flags
--docker add a Dockerfile to build in a container (c, cpp, nasm)
--style add .clang-format + .editorconfig from the style guide
--ci add a GitHub Actions workflow that builds the project
--bin DIR build directory (default per build system)
--bin-int DIR put objects in a separate dir (make/premake)
-v, --version print version and bail
-h, --help print this and bail
by hachem <im@hachem.wtf>
$ mkproj hello # C + make, the default
$ mkproj . # generate into the current directory
$ mkproj -l cpp -s c++20 -b cmake app # C++20 + cmake
$ mkproj -l objc -b meson gui # Objective-C + meson
$ mkproj -l crust hello # Rust through rustc, no cargo
$ mkproj -k shared -b cmake libbar # a shared library
$ mkproj --src source tool # sources under source/
$ mkproj -b make --bin-int obj tool # objects in obj/, binary at the root
$ mkproj --git tool # also init a git repo + .gitignore
build
needs a c compiler. nothing else.
$ sudo make install # -> /usr/local/bin + man page
$ make install PREFIX=~/.local # or somewhere without sudo
it really is one file, so if you don't want the makefile:
$ cc -O2 mkproj.c -o mkproj
completions
make install already drops bash, zsh, and fish completions into the standard
directories under $PREFIX/share, so a normal sudo make install just works.
if you installed somewhere non-standard (e.g. PREFIX=~/.local), zsh may need that dir on its fpath — add fpath=(~/.local/share/zsh/site-functions $fpath) to your .zshrc before compinit. you can also generate a script by hand anytime:
$ mkproj --completions bash > /etc/bash_completion.d/mkproj
$ mkproj --completions zsh > ~/.zsh/completions/_mkproj
$ mkproj --completions fish > ~/.config/fish/completions/mkproj.fish
license
mkproj is licensed under the mit license. see license for more.
