Make (software)


In software development, Make is a command-line interface software tool that performs actions ordered by configured dependencies as defined in a configuration file called a makefile. It is commonly used for build automation to build executable code from source code. Make is also not limited to building and can perform any operation available via the operating system shell.
Make is widely used, especially in Unix and Unix-like operating systems, even though many competing technologies and tools are available, including similar tools that perform actions based on dependencies, some compilers and interactively via an integrated development environment.
In addition to referring to the original Unix tool, Make is also a technology since multiple tools have been implemented with roughly the same functionality including similar makefile syntax and semantics.

Origin

created Make while at Bell Labs. An early version was completed in April 1976. Feldman received the 2003 ACM Software System Award for authoring Make.
Feldman describes the inspiration to write Make as arising from a coworker's frustration with the available tooling of the time:
Before Make, building on Unix mostly consisted of shell scripts written for each program's codebase. Make's dependency ordering and out-of-date checking makes the build process more robust and more efficient. The makefile allowed for better organization of build logic and often fewer build files.
Make is widely used in part due to its early inclusion in Unix, starting with PWB/UNIX 1.0, which featured a variety of software development tools.

Variants

Make has been implemented numerous times, generally using the same makefile format and providing the same features, but some providing enhancements from the original. Examples:
  • Sun DevPro Make appeared in 1986 with SunOS-3.2. With SunOS-3.2. It was delivered as an optional program; with SunOS-4.0, SunPro Make was made the default Make program. In December 2006, Sun DevPro Make was made open source as part of the efforts to open-source Solaris.
  • dmake or Distributed Make that came with Sun Solaris Studio as its default Make, but not the default one on the Solaris Operating System. It was originally required to build OpenOffice, but in 2009 the build system was rewritten to use GNU Make. While Apache OpenOffice still contains a mixture of both build systems, the much more actively developed LibreOffice only uses the modernized "gbuild" now.
  • BSD Make, which is derived from Adam de Boor's work on a version of Make capable of building targets in parallel, and survives with varying degrees of modification in FreeBSD, NetBSD and OpenBSD. Distinctively, it has conditionals and iterative loops which are applied at the parsing stage and may be used to conditionally and programmatically construct the makefile, including generation of targets at runtime.
  • GNU Make is the standard implementation of Make for Linux and macOS. It provides several extensions over the original Make, such as conditionals. It also provides many built-in functions which can be used to eliminate the need for shell-scripting in the makefile rules as well as to manipulate the variables set and used in the makefile. For example, the foreach function can be used to iterate over a list of values, such as the names of files in a given directory. GNU Make is required for building many software systems, including GNU Compiler Collection , the Linux kernel, Apache OpenOffice, LibreOffice, and Mozilla Firefox.
  • Rocky Bernstein's Remake is a fork of GNU Make and provides several extensions over GNU Make, such as better location and error-location reporting, execution tracing, execution profiling, and it contains a debugger.
  • Glenn Fowler's nmake is incompatible with the UNIX variant, but provides features which, according to some, reduce the size of makefiles by a factor of 10.
  • Microsoft nmake is normally installed with Visual Studio. It supports preprocessor directives such as includes and conditional expressions which use variables set on the command-line or within the makefiles. Inference rules differ from Make; for example they can include search paths.
  • Embarcadero make has a command-line option that "Causes MAKE to mimic Microsoft's NMAKE.".
  • Qt Project's Jom tool is a clone of nmake.
  • Mk replaced Make in Research Unix, starting from version 9. A redesign of the original tool by Bell Labs programmer Andrew G. Hume, it features a different syntax. Mk became the standard build tool in Plan 9, Bell Labs' intended successor to Unix.
  • Kati is Google's replacement of GNU Make, as of 2020 used in Android OS builds. It translates the makefile into ninja for faster incremental builds.
  • Snakemake is a Python-driven implementation for compiling and running bioinformatics workflows.
POSIX includes standardization of the basic features and operation of the Make utility, and is implemented with varying degrees of compatibility with Unix-based versions of Make. In general, simple makefiles may be used between various versions of Make with reasonable success. GNU Make, Makepp and some versions of BSD Make default to looking first for files named "GNUmakefile", "Makeppfile" and "BSDmakefile" respectively, which allows one to put makefiles which use implementation-defined behavior in separate locations.

Use

In general, based on a makefile, Make updates target files from source files if any source file has a newer timestamp than the target file or the target file does not exist. For example, this could include compiling C files into object files, then linking the object files into an executable program. Or this could include compiling TypeScript files to JavaScript for use in a browser. Other examples include: convert a source image file to another format, copy a file to a content management system, and send e-mail about build status.
A makefile defines targets where each is either a file to generate or is a user-defined concept, called a phony target.
Make updates the targets passed as arguments:

make

If no target is specified, Make updates the first target in the makefile which is often a phony target to perform the most commonly used action.
Make skips build actions if the target file timestamp is after that of the source files. Doing so optimizes the build process by skipping actions when the target file is up-to-date, but sometimes updates are skipped erroneously due to file timestamp issues including restoring an older version of a source file, or when a network filesystem is a source of files and its clock or time zone is not synchronized with the machine running Make. Also, if a source file's timestamp is in the future, make repeatedly triggers unnecessary actions, causing longer build time.
When Make starts, it uses the makefile specified on the command-line or if not specified, then uses the one found by via specific search rules. Generally, Make defaults to using the file in the working directory named. GNU Make searches for the first file matching:,, or.
Make processes the options of the command-line based on the loaded makefile.

Makefile

The makefile language is partially declarative programming where end conditions are described but the order in which actions are to be taken is not. This type of programming can be confusing to programmers used to imperative programming.
Makefiles can contain the following constructs:
  • Explicit rule: defines when and how to update a target, listing prerequisites and commands that define the update action, called the recipe
  • Implicit rule: defines when and how to remake a class of files based on their names, including how a target depends on a file with a name similar to the target and an update recipe
  • Variable definition: associates a text value with a name that can be substituted into later text
  • Directive: instruction to do something special such as include another makefile
  • Comment: line starting with

    Rules

Each rule begins with a dependency line which consists of the rule's target name followed by a colon, and optionally a list of targets on which the rule's target depends.
target :

.
.
.

Usually a rule has a single target, rather than multiple.
A dependency line may be followed by a recipe: a series of TAB indented command lines that define how to generate the target from the components. If any prerequisite has a more recent timestamp than the target file or the target does not exist as a file, the recipe is performed.
The first command may appear on the same line after the prerequisites, separated by a semicolon,

targets: prerequisites ; command

for example,

hello: ; @echo "hello"

Each command line must begin with a tab character. Even though a space is also whitespace, Make requires tab. Since this often leads to confusion and mistakes, this aspect of makefile syntax is subject to criticism. Eric S. Raymond describes it as "one of the worst design botches in the history of Unix" and The Unix-Haters Handbook said "using tabs as part of the syntax is like one of those pungee stick traps in The Green Berets". Feldman explains the choice as caused by a workaround for an early implementation difficulty, and preserved by a desire for backward compatibility with the very first users:
GNU Make since version 3.82 allows the choice of any symbol as the recipe prefix using the.RECIPEPREFIX special variable:

.RECIPEPREFIX := :
all:

Each command is executed in a separate shell. Since operating systems use different shells, this can lead to unportable makefiles. For example, GNU Make executes commands with /bin/sh by default, where Unix commands like cp are normally used. In contrast, Microsoft's nmake executes commands with cmd.exe where batch commands like copy are available but not necessarily cp.
Since a recipe is optional, the dependency line can consist solely of components that refer to other targets:

realclean: clean distclean

The following example rule is evaluated when Make updates target file.txt via. If file.html is newer than file.txt or file.txt does not exist, then the command is run to generate file.txt from file.html.

file.txt: file.html
lynx -dump file.html > file.txt

A command can have one or more of the following prefixes :
  • minus specifies to ignore an error from the command
  • at specifies to not output the command before it is executed
  • plus specifies to execute the command even if Make is invoked in "do not execute" mode
Ignoring errors and silencing echo can alternatively be obtained via the special targets and.
Microsoft's NMAKE has predefined rules that can be omitted from these makefiles, e.g..