Download
259 lines 5.2 KiBMarkdownModified 2025-03-20executable raw

#!/bin/env slides

Makefiles Are Cool

By Bruce Hill


First Experiences with Makefiles Suck

sxiv -sf -f

  • Some college course gave you this thing that magically makes your code compile.
  • Some open source project has an autogenerate script that makes a 20,000 line makefile.
  • Configuration options are often poorly documented.
  • Just run make and pray it works.

Actually Make Is Good

  • Really useful for small projects
  • Not just compiling C code
  • Anything where files are used to make other files

What Even Is Make?

make is a command you run to compile stuff.


What Even Is Make?

make is a bunch of similar programs (most commonly GNU) that look at files and determines which files need to be rebuilt and how.


What Even Is Make?

make is a domain specific programming language and interpreter for expressing dependency trees and production rule systems.


What Even Is Make?

make is a lightweight way to have files turn into other files lazily using simple rules.


Makefiles

When you run make, it looks for a file called Makefile or makefile with a set of rules.

Each rule has the format:

output: input1 input2 input3...
    how to build...

The body of the rule is a shell script

The rule will only run if any of the input files has been modified more recently than the output file!


Simple Example

sorted_names.txt: names.txt
    sort names.txt > sorted_names.txt

If you ever modify names.txt, you can run make sorted_names.txt to create the sorted names file.

If you don't want to retype the filename, you can use the variables $< (input files), $@ (output file), and $^ (first input file):

sorted_names.txt: names.txt
    sort $< > $@

Another Example

Run a python script to draw an image:

graph.png: plot_graph.py graph_module.py
    python3 $^

This will re-run if either plot_graph.py or graph_module.py is edited.


Dependency Trees

Rules can form dependency trees:

graph.png: plot_graph.py data.csv
    python3 plot_graph.py data.csv

data.csv: raw_data.bin
    convert_bin_to_csv raw_data.bin

Running make graph.png will first make sure that plot_graph.py and data.csv are up-to-date, then make sure that graph.png is up-to-date.

Rules are lazy, so if you edit plot_graph.py, but don't touch raw_data.bin, then running make graph.png won't run convert_bin_to_csv because it's not necessary.


Phony Rules

Sometimes you have a rule that doesn't actually have a file ouput.

You can use .PHONY to tell make to not bother looking for a file with that name.

Most commonly used for all, clean, and install:

.PHONY all clean install

all: sorted_names.txt graph.png

clean:
    rm sorted_names.txt graph.png

install: sorted_names.txt graph.png
    cp $< /etc/cool-files/

Note 1: a rule with no body just means "I need these files to be built using their rules, but I don't do anything in particular"

Note 2: when you run just make with no arguments, it runs the first rule in the file, which is usually all


Pattern Rules

If you put a % in the name, you can do reusable pattern rules that work for different filenames.

Turn Markdown Files into PDFs

%.pdf: %.md
    pandoc $< -o $@

Compile C Code

%.o: %.c %.h
    cc -c $^ -o $@

Defining Variables

You can define variables that are reused in different rules like this:

O=-O2
CFLAGS=-Wall -Werror $O

all: program

program: main.c foo.o baz.o
    cc $CFLAGS $< -o $@

%.o: %.c %.h
    cc $CFLAGS -c $^ -o $@

When running make you can override these variables if you want to:

make O=-O1 CFLAGS='-Weverything -Werror' all

Warning: changing the variables does not change file modification times, so make won't know stuff needs to be rebuilt with different flags.


My Website

I use a makefile to build my website and blog:

  • pandoc to make HTML files from markdown files.
  • A janky bash script to make an RSS feed from my blogposts.
  • gzip to compress my CSS files.
  • rsync PHONY rule to send files to my server.


Not Covered

There's a bunch of stuff not covered in the talk:

  • Platform-dependent variables
  • Pattern matching variables (get all the files of a type)
  • Built-in rules (you can run make even without a makefile)
  • Silent commands with @
  • Read the docs
  • You can use pandoc to make a website
  • You can use pandoc to make manpages for programs
  • You can use pandoc for anything
  • Please don't make scripts to autogenerate 10K+ line makefiles

The End

Thanks! Hope you try using simple Makefiles for your own projects!

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
#!/bin/env slides

# Makefiles Are Cool

_By Bruce Hill_


--------------------------

# First Experiences with Makefiles Suck

![sxiv -sf -f](bosch.jpg)

- Some college course gave you this thing that magically
  makes your code compile.
- Some open source project has an autogenerate script that
  makes a 20,000 line makefile.
- Configuration options are often poorly documented.
- Just run `make` and pray it works.

--------------------------

# Actually Make Is Good

- Really useful for small projects
- Not just compiling C code
- Anything where files are used to make other files

--------------------------

# What Even Is Make?

![](tinybrain.png)

`make` is a command you run to compile stuff.

--------------------------

# What Even Is Make?

![](brain.png)

`make` is a bunch of similar programs (most commonly GNU)
that look at files and determines which files need to be
rebuilt and how.

--------------------------

# What Even Is Make?

![](bigbrain.png)

`make` is a domain specific programming language
and interpreter for expressing dependency trees
and production rule systems.

--------------------------

# What Even Is Make?

![](galaxybrain.png)

`make` is a lightweight way to have files turn
into other files lazily using simple rules.

--------------------------

# Makefiles

When you run `make`, it looks for a file called
`Makefile` or `makefile` with a set of rules.

Each rule has the format:

```make
output: input1 input2 input3...
    how to build...
```

The body of the rule is a _shell script_

**The rule will only run if any of the input files has
been modified more recently than the output file!**

----------------------------

# Simple Example

```make
sorted_names.txt: names.txt
    sort names.txt > sorted_names.txt
```

If you ever modify `names.txt`, you can run
`make sorted_names.txt` to create the sorted names file.

If you don't want to retype the filename, you can use
the variables `$<` (input files), `$@` (output file),
and `$^` (first input file):

```make
sorted_names.txt: names.txt
    sort $< > $@
```

-----------------------------

# Another Example

Run a python script to draw an image:

```make
graph.png: plot_graph.py graph_module.py
    python3 $^
```

This will re-run if either `plot_graph.py` or
`graph_module.py` is edited.

----------------------------

# Dependency Trees

Rules can form dependency trees:

```make
graph.png: plot_graph.py data.csv
    python3 plot_graph.py data.csv

data.csv: raw_data.bin
    convert_bin_to_csv raw_data.bin
```

Running `make graph.png` will first make sure that
`plot_graph.py` and `data.csv` are up-to-date,
then make sure that `graph.png` is up-to-date.

Rules are **lazy**, so if you edit `plot_graph.py`, but
don't touch `raw_data.bin`, then running `make graph.png`
won't run `convert_bin_to_csv` because it's not necessary.

----------------------------

# Phony Rules

Sometimes you have a rule that doesn't actually have
a file ouput.

You can use `.PHONY` to tell `make` to not bother looking
for a file with that name.

Most commonly used for `all`, `clean`, and `install`:

```make
.PHONY all clean install

all: sorted_names.txt graph.png

clean:
    rm sorted_names.txt graph.png

install: sorted_names.txt graph.png
    cp $< /etc/cool-files/
```

**Note 1:** a rule with no body just means "I need these
files to be built using their rules, but I don't do anything
in particular"

**Note 2:** when you run just `make` with no arguments, it
runs the _first_ rule in the file, which is usually `all`

----------------------------

# Pattern Rules

If you put a `%` in the name, you can do reusable pattern
rules that work for different filenames.

## Turn Markdown Files into PDFs

```make
%.pdf: %.md
    pandoc $< -o $@
```

## Compile C Code

```make
%.o: %.c %.h
    cc -c $^ -o $@
```

-----------------------------

# Defining Variables

You can define variables that are reused in different
rules like this:

```make
O=-O2
CFLAGS=-Wall -Werror $O

all: program

program: main.c foo.o baz.o
    cc $CFLAGS $< -o $@

%.o: %.c %.h
    cc $CFLAGS -c $^ -o $@
```

When running `make` you can override these variables if you
want to:

```bash
make O=-O1 CFLAGS='-Weverything -Werror' all
```

**Warning:** changing the variables does not change file
modification times, so `make` won't know stuff needs to
be rebuilt with different flags.

--------------------------------

# My Website

I use a makefile to build my website and blog:

- `pandoc` to make HTML files from markdown files.
- A janky bash script to make an RSS feed from my blogposts.
- `gzip` to compress my CSS files.
- `rsync` PHONY rule to send files to my server.

![](website_makefile.make)

--------------------------------

# Not Covered

There's a bunch of stuff not covered in the talk:

- Platform-dependent variables
- Pattern matching variables (get all the files of a type)
- Built-in rules (you can run `make` even without a makefile)
- Silent commands with `@`
- [Read the docs](https://www.gnu.org/software/make/manual/html_node/index.html)
- You can use pandoc to make a website
- You can use pandoc to make manpages for programs
- You can use pandoc for anything
- Please don't make scripts to autogenerate 10K+ line makefiles

-------------------------------

# The End

Thanks! Hope you try using simple
Makefiles for your own projects!