Sunday, 7 August 2011

Make - UNIX Utility

In this post I want to discuss about UNIX make Utility. 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.

The purpose of the make utility is to determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them. You can use make with any programming language whose compiler can be run with a shell command.

To prepare to use make, you must write a file called the makefile that describes the relationships among files in your program, and the states the commands for updating each file. In a program, typically the executable file is updated from object files, which are in turn made by compiling source files.

Once a suitable makefile exists, each time you change some source files, this simple shell command: make suffices to perform all necessary recompilations. The make program uses the makefile data base and the last-modification time of the files to decide which of the files need to be updated. For each of those files, it issues the commands recorded in the data base.
Syntax:

make [ -f makefile ] [option] ... target ...

Make executes commands in the makefile to update one or more target names, where names is typically a program. If no -f option is present, make will look for the makefiles GNUmakefile, makefile, and Makefile, in that order.

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,

# Comments are started with the hash(#) symbol.
target [target ...]: [component ...]
[<TAB>command 1]
.
.
.
[<TAB>command n]
Descripter files
To operate make needs to know the relationship between your program's component files and the commands to update each file. This information is contained in a descriptor file you must write calledMakefile or makefile.
Comments
Comments can be entered in the descriptor file following a pound sign ( # ) and the remainder of the line will be ignored by make. If multiple lines are needed each line must begin with the pound sign.
# This is a comment line
Dependency rules
A rule consist of three parts, one or more targets, zero or more dependencies, and zero or more commands in the following form:

target1 [target2 ...] :[:] [dependency1 ...] [; commands]
[<tab> command]

Note: each command line must begin with a tab as the first character on the line and only command lines may begin with a tab.
Target
A target is usually the name of the file that make creates, often an object file or executable program.
Macros
Macros allow you to define constants. By using macros you can avoid repeating text entries and make descriptor files easier to modify. Macro definitions have the form
NAME1 = text string
NAME2 = another string

Simple Example

This is an example descriptor file to build an executable file called prog1. It requires the source files file1.cc, file2.cc, and file3.cc. An include file, mydefs.h, is required by files file1.cc andfile2.cc. If you wanted to compile this file from the command line using C++ the command would be
Note:In this example  prefixed with a percent character ( % ) it is a UNIX C-shell command line.
    % CC -o prog1 file1.cc file2.cc file3.cc
A descriptor file could run the same command better by using the simple command
    % make prog1
or if prog1 is the first target defined in the descriptor file

     % make

This example descriptor file is much longer than necessary but is useful for describing what is going on.

prog1 : file1.o file2.o file3.o
CC -o prog1 file1.o file2.o file3.o

file1.o : file1.cc mydefs.h
CC -c file1.cc

file2.o : file2.cc mydefs.h
CC -c file2.cc

file3.o : file3.cc
CC -c file3.cc

clean :
rm file1.o file2.o file3.o

Let's go through the example to see what make does by executing with the command make prog1 and assuming the program has never been compiled.
  1. make finds the target prog1 and sees that it depends on the object files file1.o file2.o file3.o
  2. make next looks to see if any of the three object files are listed as targets. They are so make looks at each target to see what it depends on. make sees that file1.o depends on the files file1.cc andmydefs.h.
  3. Now make looks to see if either of these files are listed as targets and since they aren't it executes the commands given in file1.o's rule and compiles file1.cc to get the object file.
  4. make looks at the targets file2.o and file3.o and compiles these object files in a similar fashion.
  5. make now has all the object files required to make prog1 and does so by executing the commands in its rule.


No comments:

Post a Comment