hachem.wtf
aboutsummaryrefslogtreecommitdiff

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.