make and makefile
I am a C/C++ newbie, but occassionally I have to compile or build projects. Since make (and Makefiles) are quite prevalent and sometimes they have to be adjusted due to potential errors, I had to learn more about them and want to share my learning publicly here.
Building Blocks
First of all, what are the involved building blocks of make and Makefiles?
- make:
- The GNU make utility. This is the executable that you actually run in order to execute a series of commands in order to modify files, typically compiling programs.
- If you run the program without specifying an explicit input file with the -f option, make will look for the makefiles GNUmakefile, makefile, and Makefile, in that order.
- make updates a target if it depends on prerequisite files that have been modified since the target was last modified, or if the target does not exist.
- makefile:
- This is the input file for the make utility and consists of a series of instructions how to modify files.
- A makefile can contain one or more rules.
- rule:
- A rule consists of one or more targets, prerequisites and commands.
- target:
- A target is a file name and typically, there is only one per rule.
- prerequisite:
- The prerequisites are file names, separated by spaces. These files need to exist before the commands for the target are run. These are also called dependencies.
- command:
- The commands are a series of steps typically to make the target. They need to start with a tab character, not spaces.
The general format of a Makefile
is as follows:
|
|
Example 1: Starting Simple
A more specific Makefile
would be the following file:
|
|
This file has one target named myfirsttarget
, no prerequisites and only one command, which will execute the echo command:
|
|
Typically, when a target is run (i.e., when the commands of a target are run), the commands will create a file with the same name as the target.
If we create a file named myfirsttarget
in the same folder as the Makefile
, the commands will no longer be executed:
|
|
Example 2: Multiple Rules
Let us consider another example Makefile
with two rules:
|
|
The desired rule and target can be specified with make <targetname>
.
If no target is specified, the first target of the Makefile is chosen automatically:
|
|
Furthermore, multiple targets can be specified at once:
|
|
The target execution can also be carried out in parallel with the -j
option:
|
|
Example 3: Variables
Variables can be used for dynamic input and they are limited to string values.
Single or double quotes have no meaning in make
:
Variables can be declared either with =
or :=
, as shown below:
|
|
They can be referenced either with ${var}
, $(var)
, or $var
:
|
|
Example 4: Security Issues
Furthermore, a Makefile
may be used for injection attacks, when a user is able to introduce malicious input in a variable.
Any variables are expanded before execution, regardless of any used quotes. Therefore, you should never allow unsanitized user input in the files:
Example Makefile
:
|
|
If an attacker is able to call make
with the aforementioned Makefile
and control the contents of the var
variable, they can inject arbitrary commands, as demonstrated below:
|
|
Similarly, the following Makefile
will exhibit the same behaviour with single quotes:
|
|
|
|