Make (software)
- This article is about the programming utility make. For the magazine, see Make (magazine)
make is a utility that automates the process of converting files from one form to another, doing dependency tracking and invoking external programs to do additional work as needed. Its dependency tracking is very simple and centers around the modification time of the input files. Most frequently it is used for compilation of source code into object code, joining and then linking object code into executables or libraries. It uses files called "makefiles" to determine the dependency graph for a given output, and the build scripts which need passed to the shell to build them. The term "makefile" stems from their traditional file name of "Makefile".
make is now only one such utility, but is one of the most wide-spread, primarily due to its inclusion in UNIX, starting with the PWB variant, which featured a variety of tools targeting software development workloads. It was originally created by Stuart Feldman in 1977 at Bell Labs. In 2003 Dr. Feldman received the ACM Software System Award for the invention of this important tool.
make has gone through a number of rewrites, and a number of from-scratch variants which used the same file format and basic algorithmic principles, and also provided a number of their own non-standard enhancements, in the time that followed. The two main variants of the traditional make utility are:
- 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. Most notably, it has a series of conditionals and iterative loops which are applied at the parse stage and may be used to conditionally, and programmatically, construct the makefile, including generation of targets at runtime.
- GNU make, which is part of most GNU/Linux installations and is frequently used in conjunction with the GNU Build Tools. Its notable departures from traditional make are most noticeable in pattern-matching in dependency graphs and build targets, as well as a number of functions which may be invoked to have the make utility do things like collect a list of all files in the current directory. Where BSD make has a rich set of internal macros at parse time, GNU make typically encourages the use of an external macro package like m4.
POSIX includes standardization of the basic features and operation of the make utility, and is implemented with varying degrees of completeness in UNIX-based versions of make. In general, simple makefiles may be used between various versions of make with reasonable success. GNU make and BSD make will look first for files named "GNUmakefile" and "BSDmakefile" respectively, which allows one to put makefiles which use implementation-defined behaviour in separate locations.
A makefile consists of lines of text which define a file (or set of files) or a rule name as depending on a set of files. Output files are marked as depending on their source files, for example, and source files are marked as depending on files which they include internally. After each dependency is listed, a series of lines of indented text may follow which define how to transform the input into the output, if the former has been modified more recently than the latter. In the case where such definitions are present, they are referred to as "build scripts" and are passed to the shell to generate the target file. The basic structure is:
# Comments use the pound sign (aka hash) file : dependencies command 1 command 2 . . . command n
A makefile also can contain definitions of variables and inclusion of other makefiles. Variables in makefiles may be overridden in the command line arguments passed to the make utility. This allows users to specify different behaviour for the build scripts and how to invoke programs, among other things. For example, the variable "CC" is frequently used in makefiles to refer to a C compiler, and the user may wish to provide an alternate compiler to use.
Like most software which has been around for as long as make has, it has its share of fans and detractors. Many problems have surfaced with scaling make to work with modern, large software projects, some contend, but many also point out that for the common case, make works very well, and has very simple, but powerful, expressiveness. In any event, make is still used for the building of many complete operating systems, and modern replacements are not entirely different in their basic operation.
With the advent of modern Integrated Development Environments, especially on non-UNIX platforms, many programmers do not manually manage dependency tracking, or even the listing of which files are part of a project, and instead leave that task to be automated by their environment. Likewise, many modern programming languages have language-specific ways of listing dependencies which are more efficiently tracked through the use of language-specific build utilities.
There are also many tools which are like make, but which are not compatible with its makefile format. A comprehensive list is available on the A-A-P website. Some of the most notable are:
- ant, which is popular for Java development and uses an XML file format.
- jam, which is a generally enhanced, ground-up tool which is similar to make.
- Maven, which is very similar to ant.
- mk - developed originally for Plan 9, said to have "improved upon make by removing all the vowels from the name", and introducing a completely new syntax that many consider to be easier to read and more powerful. It has been ported to Unix as part of plan9port.
- MPW Make -- Developed for MacOS Classic and loosely similar to but not compatible with Unix make; MacOS X comes with GNU make. Available as part of the Macintosh Programmer's Workshop as a free, unsupported download from Apple.
- Module::Build, which is a Perl module for the building and installation of other Perl modules. It replaces the existing ExtUtils::MakeMaker module, which actually used make to do the building.
- SCons, which is based around the Python programming language, and integrates a broader set of features than make. It is based on a Perl build driver called Cons.
Example Makefile
Here is a very simple makefile that would compile a source called "helloworld.c" using gcc. The PHONY tag is a technicality that tells 'make' that a particular target name does not stand for an actual file. The $@ and $< are two of the so-called automatic variables and stand for the target name and first dependancy, respectively. There are a number of other automatic variables.
helloworld : helloworld.o gcc -o $@ $< helloworld.o : helloworld.c gcc -c -o $@ $< .PHONY : clean clean : -rm -f helloworld helloworld.o
Criticism
Though make is a standard tool on Unix platforms, its syntax is notoriously temperamental. It was to be replaced early on in the Unix product cycle but wound up being kept due to a rapid influx of users.