> For the complete documentation index, see [llms.txt](https://notes.davidfeng.us/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://notes.davidfeng.us/command-line-1/make.md).

# make

## What is Make?

Make is a build tool, which reads rules from a makefile.

A rule looks like this:

```bash
target: prerequisites
    recipe
```

If the prerequisite files are newer than the target, make will run the recipe to rebuild the target.

* There is a TAB before the recipe.
* The prerequisite files can be both data and code.
* If the target is a directory, the timestamp is **NOT** automatically updated when files are copied into it. Thus the last step is usually `touch $@`.
* Make prints actions as it executes them. Using `@` at the start of an action tells Make not to print this action. Therefore usually there is a `@` before `echo`.

### Automatic Variable

* `$@`: the target of the current rule.
* `$^`: the dependencies of the current rule.
* `$<`: the first dependency of the current rule.

## Common usages

* `make`: builds the first target in makefile.
* `make target1`: searches the rule for `target1` and builds it.
* `make clean`: usually `clean` is a phony target, which removes all temporary files.

### **Options**

* `-f`: read from other files than makefile, e.g. `make -f common.mk`.
* `-n`: dry run - show the commands it will execute without actually running them.
* `-C`: change the directory and then run make.

### [Phony Targets](https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html)

With the following rule, `make clean` will run the recipe regardless of whether there is a file named clean.

```bash
.PHONY: clean
clean:
    rm *.o temp
```

## A real example

With the following `makefile`, run `make` to remake all three programs, or specify as arguments the ones to remake (e.g. `make prog1 prog3`).

```bash
all : prog1 prog2 prog3
.PHONY : all

prog1 : prog1.o utils.o
    cc -o prog1 prog1.o utils.o

prog2 : prog2.o
    cc -o prog2 prog2.o

prog3 : prog3.o sort.o utils.o
    cc -o prog3 prog3.o sort.o utils.o
```

### Use phony target as subroutine

When one phony target is a prerequisite of another, it serves as a subroutine of the other. With the following `makefile`, `make cleanall` will delete the object files, the difference files, and the file `program`.

```bash
.PHONY: cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
    rm program

cleanobj :
    rm *.o

cleandiff :
    rm *.diff
```

### Pattern Rules

```bash
%.dat : books/%.txt countwords.py
    python countwords.py $< $*.dat # can also use $@ here
```

This rule can be interpreted as: “In order to build a file named \[something].dat (the target) find a file named books/\[that same something].txt (the dependency) and run countwords.py \[the dependency] \[the target].”

The Make `%` wildcard can only be used in a target and in its dependencies. It cannot be used in actions. In actions, you may however use `$*`, which will be replaced by the stem with which the rule matched.

## Advanced Topics

### Variables/Macros

Variables make the makefile more readable. For example:

```bash
CC = gcc # variable assignment
CCFLAGS = -Wall -Wextra -Werror -std=c99 -pedantic -g

main: main.o moreCode.o
    $(CC) $(CCFLAGS) -o main main.o moreCode.o # variable reference
```

We could also separate configuration from computation: use `include config.mk` at the top of the main makefile and put all configuration (LANGUAGE, SRC\_FILE\_NAME, etc) in `config.mk`.

Variables can be overridden on command line. e.g.

```bash
#Makefile
TEXT = default
target1:
	@ echo $(TEXT)

$ make
default

$ make TEXT=abc
abc
```

### Functions

Use `wildcard` function to get lists of files matching a pattern. Use `patsubst` function to rewrite file names.

```bash
TXT_FILES=$(wildcard books/*.txt)
DAT_FILES=$(patsubst books/%.txt, %.dat, $(TXT_FILES))

# output
TXT_FILES: books/abyss.txt books/isles.txt books/last.txt books/sierra.txt
DAT_FILES: abyss.dat isles.dat last.dat sierra.dat
```

### Self-Documenting Makefile

Add a comment that begins with `##` before each block and add a help block in the `makefile`. For example:

````
# makefile
## clean       : Remove auto-generated files.
.PHONY : clean
clean :
    rm -f $(DAT_FILES)
    rm -f results.txt

.PHONY : help
help : makefile
    @sed -n 's/^##//p' $<```
````

And in terminal we could run `make help`:

```
$ make help
 clean       : Remove auto-generated files.
```

## References

* [Automation and Make (Software Carpentry)](http://swcarpentry.github.io/make-novice/)
* [GNU Make manual](https://www.gnu.org/software/make/manual/make.html)
* [跟我一起写Makefile](https://github.com/seisman/how-to-write-makefile)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.davidfeng.us/command-line-1/make.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
