From Seo Wiki - Search Engine Optimization and Programming Languages
|Original author(s)||Stuart Feldman|
|Type||build automation tool|
In software development, make is a utility for automatically building executable programs and libraries from source code. Files called makefiles specify how to derive the target program from each of its dependencies. Make can decide where to start through topological sorting. Though Integrated Development Environments and language-specific compiler features can also be used to manage the build process in modern systems, make remains widely used, especially in Unix-based platforms.
There are now a number of dependency-tracking build utilities, but make is one of the most widespread, primarily due to its inclusion in Unix, starting with the PWB/UNIX 1.0, which featured a variety of tools targeting software development tasks. 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.
Before make's introduction, the Unix build system would most likely consist of "make" and "install" shell scripts accompanying a program's source. Being able to combine the commands for the different targets into a single file and being able to abstract out dependency tracking and archive handling was an important step in the direction of modern build environments.
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. Some of them 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 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 frequently used in conjunction with the GNU build system. Its 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.
- Microsoft nmake, commonly available on Windows. It is fairly basic in that it offers only a subset of the features of the two versions of make mentioned above. Microsoft's nmake is not to be confused with nmake from AT&T and Bell Labs for Unix.
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. Some versions of 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.
Advantages and disadvantages
Make requires a dependency list for files to build, for example which C header files contribute to a specific object file. This keeps Make general and useful with any kind of file, but also opens up a possibility for mistakes. A forgotten or an extra dependency might not be immediately obvious, but instead serves as subtle bugs in the generated software. Such faulty makefiles are common. It is possible to write makefiles that generate these dependencies by calling external tools, but a more common solution is to use one of the available generators to make, e.g. the Automake toolchain provided by the GNU Project.
Another problem not well handled by make is the tailoring of a build process to a given platform. E.g., the compiler used on one platform might not accept the same options as the one used on another. This problem is typically handled by generating platform specific build instructions, which in turn are processed by make. Common tools for this process are Autoconf and CMake.
Make decides whether a target needs to be regenerated by comparing file modification times. While this is a simple solution to the problem of avoiding to build files which are already up to date, it fails when a file changes but its modification time stays in the past. Such changes are frequently caused by the use of revision control software, or when a network filesystem is a source of files and its clock or timezone is not synchronized with the machine running Make. The user must handle this situation by forcing a complete build. An alternate problem is the source files being in the future. This triggers too much rebuilding, which also inconveniences developers.
The syntax used by Make gives tab, a whitespace character, a different meaning from the space character. This is problematic, since there is usually no visual difference between a tab and a number of space characters. Thus, the syntax of make is often subject to criticism. For programmers using makefile generators or text editors with explicit makefile support, this issue is likely unimportant.
With 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. Instead, the task is automated by the integrated 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. These approaches typically have the drawback that support for arbitrary build instructions is limited.
The make language is similar to declarative programming. This class of language, in which necessary end conditions are described but the order in which actions are to be taken is not, is sometimes confusing to programmers used to imperative programming languages.
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 on files which they include internally, since they all affect the output. After each dependency is listed, a series of lines of tab-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 hash symbol target: 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.
Below is a very simple makefile that would compile a source called "helloworld.c" using cc, a C compiler, and specifies a "clean" target to remove the generated files, for example to start over. The .PHONY tag is a technicality that tells make that a particular target name does not produce an actual file. The
$< are two of the so-called internal macros and stand for the target name and "implicit" source, respectively. There are a number of other internal macros.
# Commands start with TAB not spaces helloworld: helloworld.o cc -o $@ $< helloworld.o: helloworld.c cc -c -o $@ $< .PHONY: clean clean: rm -f helloworld helloworld.o
Many systems come with a make configured to handle common tasks like compiling based on file suffixes, allowing one to leave out the actual instructions from the target and source specification. Assuming such a system, the above example could be shortened as follows:
helloworld: helloworld.o helloworld.o: helloworld.c .PHONY: clean clean: rm -f helloworld helloworld.o
Make allows for custom suffix rules to be defined, allowing for powerful abstraction of rules by separating the file build relationships from the construction rules.
- Apache Ant
- configure script
- GNU Automake
- Debian Package Maker
- ↑ Matthew Doar (2005). Practical Development Environments. O'Reilly Media. pp. 94. ISBN 978-0596007966.
- ↑ http://phoenix.labri.fr/wiki/doku.php?id=an_overview_on_dsls
- ↑ http://www.cs.ualberta.ca/~paullu/C201/Slides/c201.21-31.pdf
- ↑ http://lists.w3.org/Archives/Public/www-ws-arch/2002Aug/0105.html
- ↑ http://www.robots.ox.ac.uk/~tgtjr/makefiles.html
- ↑ 6.0 6.1 Note that make is sensitive to whitespace; the indented lines in the example below would be preceded by tab characters in functional code.
- ↑ A listing of some make internal macros at opengroup.org
- The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition manual
- The GNU make manual
- FreeBSD make manual page
- OPUS Makefile Tutorial
- Recursive Make Considered Harmful
- What is wrong with make?
- What’s Wrong With GNU make?
- Advanced Auto-Dependency Generation.
- GNU make Standard Library.
- Microsoft NMAKE reference.