Using the make command (with examples)
Calling the first target specified in the Makefile
make
Motivation: This use case is helpful when you want to compile the entire project or perform all the tasks specified in the Makefile.
Explanation: By executing make
without specifying a target, the make command will execute the first target mentioned in the Makefile, which is usually named “all”. The “all” target typically includes instructions for compiling the entire project.
Example output:
$ make
gcc -o main main.c
gcc -o utils utils.c
In this example, the make command executes the “all” target, which compiles two files main.c
and utils.c
and generates two executables main
and utils
.
Calling a specific target
make target
Motivation: This use case allows you to compile or perform specific tasks defined in the Makefile, instead of executing all the tasks. It helps in cases where you only need to compile or perform a specific task without executing the entire Makefile.
Explanation: By specifying a target name after the make command, you instruct the make command to execute the specific target defined in the Makefile.
Example output:
$ make clean
rm -f main utils
In this example, the make command executes the “clean” target, which removes the compiled executables main
and utils
from the project directory.
Calling a specific target, executing jobs in parallel
make -j4 target
Motivation: Parallel execution can speed up the build process for large projects where tasks can be executed independently.
Explanation: By using the -j
flag followed by a number, you can specify the maximum number of jobs to be run in parallel. The make command will automatically determine the dependencies between tasks and execute them concurrently, up to the specified number of jobs.
Example output:
$ make -j4 build
gcc -o utils utils.c
gcc -o main main.c
In this example, the make command executes the “build” target while running up to 4 jobs in parallel. It compiles two files main.c
and utils.c
concurrently and generates two executables main
and utils
.
Using a specific Makefile
make --file path/to/file
Motivation: In some cases, you may have multiple Makefiles in a project directory, or the Makefile may not be named “Makefile”. In such situations, specifying a specific Makefile is useful.
Explanation: The --file
(or -f
) flag followed by the path to the desired Makefile allows you to specify a different Makefile for the make command to execute. This is helpful when you want to use a custom Makefile or when you have multiple Makefiles in a project.
Example output:
$ make --file src/Makefile build
gcc -o src/utils src/utils.c
gcc -o src/main src/main.c
In this example, the make command executes the “build” target specified in the Makefile located in the src
directory.
Executing make from another directory
make --directory path/to/directory
Motivation: Sometimes, it is necessary to run the make command from a different directory than where the Makefile is located. This is useful when you want to build targets for a component in a separate directory without navigating to that directory.
Explanation: The --directory
(or -C
) flag followed by the path to the desired directory allows you to change the current directory and execute the make command from that directory. This is helpful when you want to build targets from a specific directory without changing the current working directory.
Example output:
$ make --directory libs/math/ build
gcc -o libs/math/add libs/math/add.c
gcc -o libs/math/subtract libs/math/subtract.c
In this example, the make command executes the “build” target specified in the Makefile located in the libs/math
directory.
Force making of a target, even if source files are unchanged
make --always-make target
Motivation: By default, the make command intelligently determines whether a target needs to be rebuilt by comparing the modification timestamps of source files and target files. In some cases, you may want to force the make command to rebuild a target even if the source files are unchanged.
Explanation: The --always-make
flag forces the make command to execute the specified target, regardless of timestamp comparisons. This ensures that the target is rebuilt every time the make command is run, even if the source files are unchanged.
Example output:
$ make --always-make build
gcc -o main main.c
gcc -o utils utils.c
In this example, the make command executes the “build” target, and it rebuilds the targets main
and utils
even if the source files are unchanged.
Override a variable defined in the Makefile
make target variable=new_value
Motivation: Makefiles often contain variables that control the compilation process. Sometimes, you may want to override the default value of a variable defined in the Makefile to customize the build process.
Explanation: By specifying the target and the variable followed by =
and a new value, you can override the default value of a variable defined in the Makefile. The make command will use the new value instead of the default value.
Example output:
$ make build OPTIMIZATION_LEVEL=2
gcc -o main main.c -O2
gcc -o utils utils.c -O2
In this example, the make command executes the “build” target and sets the OPTIMIZATION_LEVEL
variable to 2
. This overrides the default value defined in the Makefile and applies the optimization level -O2
to the compilation process.
Override variables defined in the Makefile by the environment
make --environment-overrides target
Motivation: The make command allows you to override variables defined in the Makefile by using environment variables. This provides a flexible way to customize the build process without modifying the Makefile directly.
Explanation: The --environment-overrides
flag instructs the make command to prioritize environment variables over the variables defined in the Makefile. When a variable is set both in the environment and the Makefile, the value from the environment will be used.
Example output:
$ export CC=gcc-9
$ make --environment-overrides build
gcc-9 -o main main.c
gcc-9 -o utils utils.c
In this example, the make command executes the “build” target, and the environment variable CC
is set to gcc-9
. This overrides the default value of CC
defined in the Makefile and uses gcc-9
as the compiler for both main.c
and utils.c
.