main gen
 1#!/bin/sh
 2# gen is a small generator for ninja build files. before i was hand writing them, but this makes it 
 3# pretty easy. it takes a list of files from stdin and a target as an argument, soyou can do something
 4# like:
 5#
 6#      find. -name '*.c' | gen binary
 7#
 8# and that will generate ninja to build the binary. you can edit the variables at the top of the file 
 9# to add any libraries you link, or edit cflags, etc. its's quite simplistic, so it only really works 
10# for simple projects with a few C files and a single target. the ninja files are simple enough for 
11# users to edit to their liking, so you can just generate them once and ship the generated files.
12#
13# it only works for C sources, and dependency tracking is handled by the compiler. cleaning is handled
14# by ninja, eg 'ninja -t clean'
15
16set -eu
17
18if [ "$#" -ne 1 ]; then
19	printf 'usage: %s target\n' "${0##*/}" >&2
20	exit 2
21fi
22
23target=$1
24objs=
25first=1
26printf "# i know this is a ninja file, but you're allowed to edit it.\n"
27printf "# you can also pass things on the command line if you like, eg\n"
28printf "#\n"
29printf "#     CC=clang ninja\n"
30printf "\n"
31printf 'cc = $${CC:-cc}\n'
32printf 'cflags = $${CFLAGS:--O2 -std=c99}\n'
33printf 'ldflags = $${LDFLAGS:-}\n'
34printf 'libs = $${LIBS:-}\n'
35printf 'prefix = $${PREFIX:-/usr/local}\n'
36printf 'destdir = $${DESTDIR:-}\n'
37printf 'bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}\n'
38printf '\n'
39printf 'rule cc\n'
40printf '  command = $cc $cflags -MMD -MF $out.d -c -o $out $in\n'
41printf '  deps = gcc\n'
42printf '  depfile = $out.d\n'
43printf '  description = cc $out\n'
44printf '\n'
45printf 'rule link\n'
46printf '  command = $cc $ldflags -o $out $in $libs\n'
47printf '  description = link $out\n'
48printf '\n'
49printf 'rule install\n'
50printf '  command = mkdir -p $bindir && cp %s $bindir/\n' "$target"
51printf '  description = install %s\n' "$target"
52printf '\n'
53
54while IFS= read -r src; do
55	[ -n "$src" ] || continue
56	case $src in
57	*.c) ;;
58	*) continue ;;
59	esac
60	obj=${src%.c}.o
61	printf 'build %s: cc %s\n' "$obj" "$src"
62	if [ $first -eq 1 ]; then
63		objs=$obj
64		first=0
65	else
66		objs="$objs $obj"
67	fi
68done
69
70if [ $first -eq 1 ]; then
71	printf '%s: no .c files on stdin\n' "${0##*/}" >&2
72	exit 1
73fi
74
75printf '\n'
76printf 'build %s: link %s\n' "$target" "$objs"
77printf 'build all: phony %s\n' "$target"
78printf 'build install: install %s\n' "$target"
79printf '\n'
80printf 'default all\n'