automaker is designed to automatically generate Makefiles for C projects. The idea is that you declare dependencies explicitly in your source files, then run automaker, and your Makefile will be created.

For example, given a source file greeter.c, to produce a Makefile that will produce the greeter executable along with any dependencies, run:

$ automaker greeter.c > Makefile

Here’s how it works: automaker opens greeter.c and looks for a comment section of the following format:

%use io_getline;
%use io_put;
%use io_putline;

The above would mean greeter needs to be linked with io_getline.o, io_put.o, io_putline and any dependencies that come along with them (as defined in io_getline.c, io_put.c, and io_putline.c). (A completely flat file structure is expected: automaker is meant for small(ish) C projects.) Each file (with a .o suffix) would be added to greeter’s Makefile entry, along with any more dependencies generated after checking the file (with a .c suffix) for any of its dependencies, recursively. It then outputs a fully functioning Makefile capable of building greeter.

You may supply more than one main source file. For example:

$ automaker myprog1.c myprog2.c myprog3.c > Makefile

The above constructs a Makefile that creates executables myprog1, myprog2, and myprog3, linking them with all necessary dependencies.

To give a more complete example, the source code for greeter.c might look like:

%use io_getline;
%use io_put;
%use io_putline;
#include "io.h"
#include "str.h"
static str name = {0};
int main()
    io_putline(io_stdout, "Type your name: "); 
    io_getline(io_stdin, &name); 
    io_put(io_stdout, "Hello, "); io_putline(io_stdout, &name);
    return 0;

Then, to produce the Makefile necessary to build test, run:

$ automaker greeter.c > Makefile

This will produce the following Makefile:

default: it
    echo '#!/bin/sh' > load
    echo 'main="$$1"; shift' >> load
    echo 'exec cc -o "$$main" "$$main".o $${1+"$$@"}' >> load
    chmod +x load
    echo '#!/bin/sh' > compile
    echo 'exec cc -c $${1+"$$@"}' >> compile
    chmod +x compile
greeter: load greeter.o io_getline.o io_put.o io_putline.o
    ./load myprog io_getline.o io_put.o io_putline.o
io_getline.o: compile io_getline.c
    ./compile io_getline.c
io_put.o: compile io_put.c
    ./compile io_put.c
io_putline.o: compile io_putline.c
    ./compile io_putline.c
it: greeter
    rm -f *.o greeting

The code is on GitHub and, like most of my work, is public domain.