# Note about Makefile
###### tags: `C` `C++` `Linux`
## Makefile?
Makefiles are used to help decide which parts of a large program need to be recompiled.
## make command:
On Unix-like operating systems, make is a utility for building and maintaining groups of programs (and other types of files) from source code. In fact, make is not limited to programs. **You can use it to describe any task where some files must be updated automatically from others whenever the others change.** Prepare to use make, you should write a file named GNUmakefile, makefile, or Makefile(Make command will search these target in order.).
* make command syntex
```
make [ -f makefile ] [ options ] ... [ targets ] ...
```
* Options
https://www.computerhope.com/unix/umake.htm#syntax
* Examples
## Makefile Syntax
A makefile consists of a set of rules:
::: success
targets: prerequisites
<\tab>command #not space!!!
<\tab>command
<\tab>command
:::
* The targets are file names, separated by spaces. Typically, there is only one per rule.
* The commands are a series of steps typically used to make the target(s). These need to **start with a tab** character, **not spaces**.
* The **prerequisites** are also **file names** which should be **separated by spaces**. These files need to exist before the commands for the target are run. These are also called **dependencies**.
:::info
Useful tip: cat -e -t -v makefile_name
This command can check if each command starts with a tab
if the command starts with ^I, this means there is a tab.
Ex:
```shell=1
#command
cat -e -t -v makefile_name
```
```shell=1
#output
test: test.o$
^Icc test.o -o test$ #this is ok
```
:::
#### Example
```she
test: test.o # Third rule. if test not exists, run this when test.o exists
cc test.o -o test
test.o: test.c # Second rule. if test.o not exists, run this when test.c exists
cc -c test.c -o test.o
test.c: # First rule. If test.c not exist, run command.
echo "int main() { return 0; }" > test.c
clean:
rm *.o *.c
rm -f test
```
#### Variables:
* variables can only be **string**
* reference variable: ${} or $()
* Example:
```she
files = file1 file2
x = dude
test_files: $(files)
echo "Look at this variable: " $(files)
echo "Look at this variable again: " ${files}
echo "Look at this variable again in bad practice: " $files
echo "Look at x in bad practice: " $x
touch some_file
file1:
touch file1
file2:
touch file2
clean:
rm -f file1 file2 some_file
```
Output:
```shell
echo "Look at this variable: " file1 file2
Look at this variable: file1 file2
echo "Look at this variable again: " file1 file2
Look at this variable again: file1 file2
echo "Look at this variable again in bad practice: " iles
Look at this variable again in bad practice: iles
echo "Look at x in bad practice: " dude
Look at x in bad practice: dude
touch some_file
```
:::danger
Danger: reference variable by $var is a bad idea. The previous example show that the output is expected in "x=dude" but is wrong in "files= file1 file2".
:::
* Automatic variables(not finished: https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html)
* Wildcard: * and %
(star)* means searching in filesystem for matching filenames.
% means differently in three seperated situation:
1. When used in "matching" mode, it matches one or more characters in a string. This match is called the stem.
2. When used in "replacing" mode, it takes the stem that was matched and replaces that in a string.
3. % is most often used in rule definitions and in some specific functions.
4. The usage example will be exposed in the rules below.(please add url)
Example:
## reference
Learn Makefiles With the tastiest examples: https://makefiletutorial.com/#makefile-cookbook
Makefile 語法和示範 : https://hackmd.io/@sysprog/SySTMXPvl