Rediscovering make: automatic variables
Tags: unix, tooling
Published: 2018-01-26 01:11:42

---
title: "Rediscovering make: automatic variables"
published: true
tags: unix, tooling
canonical_url: https://monades.roperzh.com/rediscovering-make-automatic-variables/
cover_image: https://user-images.githubusercontent.com/4419992/34566576-c93327a0-f13d-11e7-88de-e36ea159d189.jpg
---

Despite its simplicity, automatic variables are very convenient when writing non-trivial makefiles. This article covers what they are and how to use them.

_note: if you need a quick refresher on rules, check out [the previous post](https://dev.to/roperzh/rediscovering-make-the-power-behind-rules-3367-temp-slug-6534817) on the make series._

## Automatic variables

As [patterns](https://monades.roperzh.com/rediscovering-make-power-behind-rules/#patterns) can be really useful to define targets and prerequisites, they are also dynamic: every time the recipe is run the wildcard can be matching different files, which is a problem if you need to reference them in your recipe.

You can deal with this using automatic variables. As the name implies, `make` defines a set of variables for you _every time a rule is executed_, based on the target and the prerequisites of the rule.

While automatic variables are most useful with patterns, the following examples use static file names in order to simplify the concepts, but all of what’s described above works for patterns too.

Suppose you have the following rule:

```
targetdir/targetfile.o : pre.c predir/pre.h | order-only.c
	# recipe
```

When the recipe is run, the following variables are automatically assigned:

| Variable | Meaning | Example |
| --- | --- | --- |
| $@ | file name of the target | targetdir/targetfile.o |
| $\< | name of the first prerequisite | pre.c |
| $? | names of all prerequisites newer than the target | depends on context |
| $^ | names of all prerequisites | pre.c predir/pre.h |
| $| | names of all the order-only prerequisites | order-only.c |
| $\* | stem with which an implicit rule matches | targetdir/targetfile |
| $% | name of the archive member ([see archives](https://monades.roperzh.com/rediscovering-make-power-behind-rules/#archive-files)) | - |

#### Modifiers

Sometimes, you may only need only the directory or the filename of the variable, for this scenario `make` offers two modifiers you can add to your variables:

| Modifier | Meaning | Example |
| --- | --- | --- |
| D | the directory part | `dir` |
| F | the file-within-directory part | `simple.c` |

Modifiers are added right next to the variable and need to be wrapped in parenthesis, for example if `$@` is `targetdir/targetfile.o`:

- `$(@D)` is `targetdir`
- `$(@F)` is `targetfile.o`

### Helpers

As automatic variables can be difficult to remember, here are a couple of resources to help you:

#### Phony makefile

A good way to learn is by experimentation: create a directory, place mock files in there, and define your targets and prerequisites, then, instead of doing something useful in the recipe, just print the variables:

```
targetdir/targetfile.o : predir/pre.h | order-only.c
  @echo '@: $@'
  @echo '%: $%'
  @echo '<: $<'
  @echo '?: $?'
  @echo '^: $^'
  @echo '|: $|'
  @echo '*: $*'
```

#### Snippets

I published snippet packs for [Visual Studio Code](https://github.com/roperzh/vscode-make-auto-vars) and [Sublime Text](https://github.com/roperzh/sublime-make-auto-vars) that may come in handy: they give you a list of the available variables, followed by a short explanation of their purpouse:

![plugin-example](https://user-images.githubusercontent.com/4419992/35174851-a1af3c78-fd4f-11e7-9882-ff8f02523ffe.jpg)

_note: If you are using another editor there are tools to convert between snippets formats._