Jump to content

make (software)

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by 65.114.169.144 (talk) at 20:28, 16 August 2011 (→‎Origin). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

make
Original author(s)Stuart Feldman
Initial release1977
Typebuild automation tool

In software development, make is a utility that automatically builds executable programs and libraries from source code by reading files called makefiles which specify how to derive the target program. 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.

Origin

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 authoring of this widespread tool.[1]

Before make's introduction, the Unix build system most commonly consisted of operating system dependent "make" and "install" shell scripts accompanying their program's source.[citation needed] 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.

Applications

Make is typically used to build executable programs and libraries from source code. Generally though, any process that involves transforming a dependency file to a target result (by executing some number of arbitrary commands) is applicable to make. To cite an example, make could be used to detect a change made to an image file (the dependency) and the target actions that result might be to convert the file to some specific format, copy the result into a content management system, and then send e-mail to a predefined set of users that the above actions were performed.

Modern versions

Make has gone through a number of rewrites, including 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. 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 allowing functionality like listing the 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. GNU make and BSD make can be configured to look first for files named "GNUmakefile" and "BSDmakefile" respectively,[2][3] which allows one to put makefiles which use implementation-defined behavior in separate locations.

Advantages and disadvantages

Make orders 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 human error. A forgotten or an extra dependency may not be immediately obvious and may result in subtle bugs in the generated software. It is possible to write Makefiles which generate these dependencies by calling third-party tools, and some Makefile generators, such as the Automake toolchain provided by the GNU Project, can do so automatically.

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, which generate shell scripts named configure that the user runs prior to the build process.

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 the building of 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. Another problem is the source files being in the future. This triggers too much rebuilding, which also inconveniences developers.

The commands in a makefile are executed by a shell. Since operating systems use different shells this leads to unportable makefiles. E.g.: GNU make executes commands with bash, therefore Unix commands like cp will be used. In contrast to that Microsofts nmake executes commands with cmd.exe, therefore batch commands like COPY will be used.

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.[4][5][6][7] This class of language, in which necessary end conditions are described but the order in which actions are to be taken is not important, is sometimes confusing to programmers used to imperative programming languages.

Makefile structure

A makefile consists of dependency lines of text which define a target (a rule) followed by a colon and optionally a set of files on which the target depends. The dependency line is arranged so that the target (left hand of : character) depends on components (right hand of : character).

After each dependency line, a series of lines of tab-indented text may follow which define how to transform the components (usually source files) into the target (usually the "output"). If any of the components have been modified, the command below are run. The basic structure is:[8]

    # Comments are started with the hash(#) symbol.
    target [target ...]: [component ...]
    [<TAB>command 1]
	   .
	   .
	   .
    [<TAB>command n]

Note: Usually multiple targets are separated on their own lines. Also the command lines are optional. The dependency line can consist solely of components that call other targets like:

    realclean: clean distclean

The commands that follow are usually arranged so that they generate the target. An example: if "file.html" is newer, it is converted to text. The contents of makefile:

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

The above is run by invoking make with the target name file.txt:

    make file.txt

A makefile also can contain definitions of macros and some make commands can include other makefiles. Macros in makefiles may be overridden in the command-line arguments passed to the make utility. This allows users to specify different behavior for the build scripts and to invoke programs during the build process, among other things. For example, the macro "CC" is frequently used in makefiles to refer to the location of a C compiler, and the user may wish to provide an alternate compiler to use. An example of GNU make:

    # Makefile for GNU make

    # Just a snippet to stop executing under other make(1) commands
    # that won't understand these lines

    ifneq (,)
    This makefile requires GNU Make.
    endif

    include makefile/environment.mk
    include makefile/common.mk

    # Define macros. In this case "simple variables that don't expand"
    # Can be overridden on command line

    CC     = gcc
    CFLAGS = -Wall -pedantic -g

    all:
	echo "Nothing to do, yet"

Syntax

Command line

  • The make searches the file to run from current directory. E.g. the GNU make(1) searches files in order GNUmakefile, makefile, Makefile.
  • The make, without arguments, runs the first TARGET that appears in the file, which is traditionally named all.
  • Multiple targets can be called at invoking make command from command line:
    make TARGET [TARGET ...]
  • Macros in the makefile can be modified on the command line before calling targets. The macros are usually referred to as "variables" when they hold simple string definitions, like in make CC=gcc all. The generic syntax is:
    make MACRO="value" [MACRO="value" ...] TARGET [TARGET ...]

Makefile content

Shell variables that are part of the environment are available as macros. New macros (or simple "variables") are also traditionally defined using capital letters:

    MACRO = definition

Macros, when expanded, are traditionally enclosed inside (). Very rarely, though possible, inside {}.

    NEW_MACRO = $(MACRO)-$(MACRO2)

Macros can be composed of shell commands by using the Command substitution operators, or backticks ``.

    YYYYMMDD  = ` date `

The content of the definition is stored "as is" and is expanded only when the macro is used in the command line statements for a TARGET. An extended example:

    PACKAGE   = package
    VERSION   = ` date +"%Y.%m%d" `
    ARCHIVE   = $(PACKAGE)-$(VERSION)

    dist:
            #  Notice that only now macros are expanded for shell to interpret:
            #      tar -cf package-`date +"%Y%m%d"`.tar

            tar -zcf $(ARCHIVE).tar .

Each command that follows dependency line, i.e. the TARGET to the left, must be indented by a TAB character.

    target: component
    <TAB>command

Each command line runs in a separate shell and each command must be a single line. Concatenation is indicated with a backslash \ character at the end of a line.

    target: component \
            component
    <TAB>command ;          \
    <TAB>command |          \
    <TAB>piped-command

Command lines can have one or more of the following three prefixes: a hyphen (minus sign, "-"), an at sign ("@"), or a plus sign ("+"). These mean respectively that errors are ignored ("-"), that the command is not printed to standard output before it is executed ("@"), and that the command is executed even if make is invoked in a "do not execute" mode ("+"). Ignoring errors and silencing echo can alternatively be obtained via the special targets .IGNORE and .SILENT.[9]

Makefiles can access predefined internal macros.

    target: component1 component2
            echo $? contains those components, that need attention, THAT ARE YOUNGER than current TARGET
            echo $@ evaluates to current TARGET name to the left

Suffix rules are in the form FROM.TO and they can be used to launch actions based on file extension. In the case of suffix rules, internal macro $< refers the component and $@ refers to the TARGET. An example to convert any HTML file into text; notice the shell redirection token > in the middle:

    .SUFFIXES: .txt .html

    # From .html to .txt
    .html.txt:
            lynx -dump $<   >   $@

When called from command line, the above example expands.

    $ make -n file.txt
      lynx -dump file.html > file.txt

Example makefiles

Makefiles are traditionally used for compiling code (*.c, *.cc, *.C, etc.), but they can also be used for providing commands to automate common tasks. One such makefile is called from the command line:

    make                        # Without argument runs first TARGET
    make help                   # Show available TARGETS
    make dist                   # Make a release archive from current dir

The makefile:

    PACKAGE	 = package
    VERSION	 = ` date "+%Y.%m%d%" `
    RELEASE_DIR  = ..
    RELEASE_FILE = $(PACKAGE)-$(VERSION)

    # Notice that the variable LOGNAME comes from the environment in
    # POSIX shells.
    #
    # target: all - Default target. Does nothing.
    all:
	    echo "Hello $(LOGNAME), nothing to do by default"
	    echo "Try 'make help'"

    # target: help - Display callable targets.
    help:
	    egrep "^# target:" [Mm]akefile

    # target: list - List source files
    list:
	    # Won't work. Each command is in separate shell
	    cd src
	    ls

	    # Correct, continuation of the same shell
	    cd src; \
	    ls

    # target: dist - Make a release.
    dist:
	    tar -cf  $(RELEASE_DIR)/$(RELEASE_FILE) && \
	    gzip -9  $(RELEASE_DIR)/$(RELEASE_FILE).tar

Below is a very simple makefile that would compile a source called "helloworld.c" using gcc, 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 $@ and $< are two of the so-called internal macros (also known as automatic variables) and stand for the target name and "implicit" source, respectively. There are a number of other internal macros.[8][10][11]

    CC     = gcc
    CFLAGS = -g

    all: helloworld

    helloworld: helloworld.o
	    # Commands start with TAB not spaces
	    $(CC) $(LDFLAGS) -o $@ $^

    helloworld.o: helloworld.c
	    $(CC) $(CFLAGS) -c -o $@ $<

    clean:
	    rm -f helloworld helloworld.o

    # This is GNU makefile extension to notify that roughly means: 'clean' does
    # not depend on any files in order to call it.
    .PHONY: clean

Many systems come with a version of make configured to handle common tasks like compiling based on file suffixes, which allows 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:

    all: helloworld

    helloworld: helloworld.o

    helloworld.o: helloworld.c

    clean:
	    rm -f helloworld helloworld.o

    .PHONY: clean

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.

See also

References

  1. ^ Matthew Doar (2005). Practical Development Environments. O'Reilly Media. p. 94. ISBN 978-0596007966.
  2. ^ "GNU `make'". Free Software Foundation.
  3. ^ "Manual Pages: make". OpenBSD 4.8.
  4. ^ an overview on dsls, 2007/02/27, phoenix wiki
  5. ^ http://www.cs.ualberta.ca/~paullu/C201/Slides/c201.21-31.pdf [dead link]
  6. ^ Re: Choreography and REST, from Christopher B Ferris on 2002-08-09
  7. ^ Target Junior Makefiles, Andrew W. Fitzgibbon and William A. Hoffman
  8. ^ a b Note that make is sensitive to whitespace; the indented lines in the example below would be preceded by tab characters in functional code.
  9. ^ make, The Open Group Base Specifications Issue 6
  10. ^ A listing of some make internal macros at opengroup.org
  11. ^ Automatic Variables GNU `make'

Reference, manuals, books

Tutorials

Debugging GNU make

Other