Skip to content
Snippets Groups Projects
Commit 0042425c authored by Mactavish's avatar Mactavish
Browse files

update

parent 0fd20dc9
No related branches found
No related tags found
No related merge requests found
---
title: Make
---
# Make: a build automation tool
### Intuition
- Yes, I can just type `gcc ...` to compile my tiny program.
- What about when you have tens, hundreds or even thousands of files?
- Even worse, these files can even be spread over different folders.
- We need a program to manage the compiling of all the files in our programs.
- **Make** is such a tool that can automate the build process.
<br/>
### What is Build Automation?
- Automating the process of compiling code into libraries and executables
- Recompile only the files that have changed
- There are many tools for this: [Apache Maven](https://maven.apache.org/), [Gradle](https://gradle.org/), [CMake](https://cmake.org/)
---
title: Make II
---
### What is Make?
- Make uses a **declarative language** as opposed to procedural languages.
- We tell Make what we want.
- We provide a set of rules showing dependencies between files.
- Make uses the rules to get the job done.
- Make is associated with the executable named `make`.
- There are different variants of Make, we focus on the [GNU Make](https://www.gnu.org/software/make/)
<br/>
### Makefile
Make uses a file called `Makefile` (or `makefile`).
We recommend `Makefile` because it appears prominently near the beginning of a directory listing, right near other important files such as README.
---
title: Makefile Overview
---
Here is an example of a Makefile:
```make
# Recursive variables
PROG = main
OBJS = main.o
CFLAG = -Wall -g
CC = gcc
INCLUDE = -I.
# Simple rules
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(OBJS) # Commands
# Pattern rules
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(INCLUDES)
# Phony targets
.PHONY: clean
# clean all the .o and executable files
clean:
rm -rf *.o core *.core $(PROG)
```
---
title: Makefile Syntax
---
### Makefile Syntax
When you are writing a Makefile, most of the time you are writing rules. A typical rule has the form:
```make
# This line contains a comment
target1 target2 ... : prerequisite1 prerequisite2 ...
command 1
command 2
command 3
...
```
- `target` list is a space separated list of files that needs to be "**made**" (created).
- `prerequisite` list is a space separated list of files that the target depends on in some way.
- The `command` list is one or more commands needed to accomplish the task of creating the target. The commands can be any shell command or any program available in your environment.
- **Each command must be indented with a tab.**
- The **#** symbol is used to start a comment in a Makefile.
- Long lines can be continued using the standard Unix escape character backslash (\\).
---
title: Makefile Rules
---
## Rules
There are a number of different kinds of rules:
- **Explicit rules**: specific target, mostly concrete filenames
- **Pattern rules**: wildcards instead of explicit filenames.
- **Implicit rules**: in the rules database built-in to Make
<br/>
### Explicit rules
A rule can have more than one target, and they share the same set of prerequisites:
```make
utils.o main.o: make.h config.h dep.h
```
This is equivalent to:
```make
utils.o: make.h config.h dep.h
main.o: make.h config.h dep.h
```
If any file in the prerequisite list is newer than the target, then `make` will update the target by executing the commands associated with the rule.
---
title: Makefile Rules II
---
### Pattern Rules
Pattern rules let you match the files that have a similar structure:
```c
# Define a pattern rule that compiles every .c file into a .o file
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
```
There is a special rule to generate a file with no suffix (always an executable) from a .c file:
```c
% : %.o
$(LD) $^ $(LDLIBS) -o $@
```
The percent character in a pattern rule is roughly equivalent to * in a Unix shell. It just represents any number of any characters. The percent character can be placed anywhere within the pattern but can occur only once.
```make
# valid uses of %
%,v
s%.o
wrapper_%
```
---
title: Makefile Rules III
---
### Static Pattern Rules
A static pattern rule is one that applies only to a specific list of targets.
```make
OBJECTS = main.o utils.o sort.o
$(OBJECTS): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
```
The only difference between this rule and an ordinary pattern rule is the initial `$(OBJECTS)`: specification.
This limits the rule to the files listed in the `$(OBJECTS)` variable.
Each object file in `$(OBJECTS)` is matched against the pattern `%.o` and its stem is extracted.
Use static pattern rules whenever it is easier to list the target files explicitly than to identify them by a suffix or other pattern.
---
title: Makefile Rules IV
---
### Implicit Rules
The built-in implicit rules are applied whenever a target is being considered and there is no explicit rule to update it.
```make
count_words: counter.o lexer.o
count_words.o: counter.h
counter.o: counter.h lexer.h
```
So using an implicit rule is easy: **simply do not specify a command script when adding your target to the makefile.**
You can use the `--print-data-base` flag to find out all rules that are defined in the internal database.
```bash
make --print-data-base
# or
make -p
```
---
title: Makefile Rules V
---
### Phony Targets
Targets that do not represent files are known as _phony targets_. The typical use case is for a target to be just a label representing a command script.
```make
.PHONY: clean
clean:
rm -f *.o
```
It is important to note that make cannot distinguish between a file target and phony target. So if you happen to have a file named `clean` and a target also named `clean`, then make will associate the file with the phony target.
So, just remember, always specify the phony target with `.PHONY`. (This is a special target in GNU Make).
---
title: Makefile Rules VI
---
### Variables
You can define variables with the following syntax:
```make
# recursively expanded variables
SRC = main.c utils.c
OBJECTS = main.o utils.o
# simply expanded variables
today := 2023-05-11
```
- simply expanded: right-hand side is expanded immediately upon reading the line from the makefile.
- recursively expanded: the right-hand side is expanded when the variable is used.
#### Variable Expansion
Expansion is just a fancy word for getting the value of the variable:
```make
# expansion syntax
$(variable-name)
${variable-name}
```
---
title: Makefile Rules VII
---
#### Automatic Variables
**Automatic variables are set by make after a rule is matched.**
There are several important automatic variables:
```make
$@ The filename representing the target
$? The names of all prerequisites that are newer than the target, separated by spaces
$< The filename of the first prerequisite
$^ The filenames of all the prerequisites, separated by spaces. (duplicates removed)
$+ Similar to $^ but includes duplicates
$* The stem of the target filename, typically a filename without its suffix
```
Here is an example:
```make
# count_words is a executable
count_words: count_words.o counter.o
gcc $^ -o $@
count_words.o: count_words.c
gcc -c $<
counter.o: counter.c
gcc -c $<
```
...@@ -34,6 +34,11 @@ transition: slide-left ...@@ -34,6 +34,11 @@ transition: slide-left
src: ./pages/recap.md src: ./pages/recap.md
--- ---
---
transition: slide-left
src: ./pages/makefile.md
---
--- ---
transition: slide-left transition: slide-left
src: ./pages/qa.md src: ./pages/qa.md
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment