LinuxCommandLibrary

make

Automate software build processes

TLDR

Call the first target specified in the Makefile (usually named "all")

$ make
copy

Call a specific target
$ make [target]
copy

Call a specific target, executing 4 jobs at a time in parallel
$ make [[-j|--jobs]] 4 [target]
copy

Use a specific Makefile
$ make [[-f|--file]] [path/to/file]
copy

Execute make from another directory
$ make [[-C|--directory]] [path/to/directory]
copy

Force making of a target, even if source files are unchanged
$ make [[-B|--always-make]] [target]
copy

Override a variable defined in the Makefile
$ make [target] [variable]=[new_value]
copy

Override variables defined in the Makefile by the environment
$ make [[-e|--environment-overrides]] [target]
copy

SYNOPSIS

make [options] [targets]
make -f FILE [targets]

PARAMETERS

-f FILE, --file=FILE, --makefile=FILE
    Specifies an alternative Makefile to use instead of the default Makefile or makefile.

-j [N], --jobs[=N]
    Allows N jobs (commands) to run simultaneously. If N is omitted, make runs as many jobs as possible, typically limited by CPU cores.

-k, --keep-going
    Continues building as much as possible even after a command fails.

-n, --just-print, --dry-run, --recon
    Prints the commands that would be executed, but does not actually execute them. Useful for debugging Makefiles.

-s, --silent, --quiet
    Suppresses the echoing of commands as they are executed, showing only the output of the commands themselves.

-C DIR, --directory=DIR
    Changes the current working directory to DIR before reading Makefiles or doing anything else.

-B, --always-make
    Unconditionally makes all targets, even if their prerequisites are up to date.

DESCRIPTION

make is a powerful command-line utility used for automating the compilation of software projects and managing dependencies. Its primary function is to read a Makefile (or makefile) which contains a set of rules defining how to build a project's components. Each rule specifies a target (what to build), its prerequisites (files it depends on), and a recipe (the commands to execute to build the target).

When make is invoked, it intelligently determines which parts of a project need to be recompiled by comparing the timestamps of target files and their prerequisites. If a prerequisite is newer than its target, or if the target doesn't exist, make executes the associated recipe. This approach ensures efficient, incremental builds, saving significant time by only rebuilding what has changed. make is indispensable for large, complex software projects written in languages like C, C++, and for managing general build processes where dependencies need to be tracked precisely.

CAVEATS

While powerful, make can have a steep learning curve due to its unique syntax and implicit rules. Debugging complex Makefiles can be challenging, especially when dealing with variable expansions and shell interactions. Its dependency on file timestamps can sometimes be problematic in distributed or network file system environments. For highly dynamic build processes or complex package management, newer build systems might offer more flexibility or abstraction.

MAKEFILE STRUCTURE

A Makefile consists of rules, variables, and comments. A basic rule is defined as: target: prerequisites
recipe

where `\t` represents a tab character. Targets are typically files to be created (e.g., executable, object file) or actions to perform (e.g., clean). Prerequisites are files or other targets the target depends on. The recipe is a sequence of shell commands to execute if the target is out of date or does not exist.

IMPLICIT RULES

make provides a set of built-in, or implicit, rules that simplify common tasks. For example, it knows how to compile a .c file into a .o object file using cc -c $< without explicit definition in the Makefile. These rules save time and effort, but can sometimes lead to unexpected behavior if not understood.

VARIABLES

Makefiles extensively use variables to store lists of files, compiler options, or paths, making them more organized and reusable. Variables are defined using VAR = value and referenced with $(VAR) or ${VAR}. They significantly enhance the flexibility and maintainability of build configurations.

HISTORY

The make utility was originally developed by Stuart Feldman at Bell Labs in April 1976. It emerged from the need to manage dependencies in large software projects, specifically to avoid recompiling an entire system when only a few files had changed. Before make, developers had to manually track file changes and issue compilation commands, a tedious and error-prone process. make quickly became a standard and essential tool in Unix-like operating systems. The most widely used version today is GNU Make, which has significantly extended the original functionality with features like conditional execution, functions, and powerful string manipulation, solidifying its role as a cornerstone of software development on Linux and other Unix-like platforms.

SEE ALSO

gcc(1), cmake(1), ninja(1), autoconf(1), Makefile(5)

Copied to clipboard