Using Make





Overview

Make is a program designed to simplify the maintenance of other programs. Its input is a list of specifications as to the files upon which programs and other files depend. This list is usually stored in a file named "makefile" or "Makefile".

When files (say, one or more source files used to build a given program) are modified, you can use make to bring the executable version of the program up to date. Make uses the dependencies specified in the makefile to ensure that all "derived" files are brought up to date after source files change, while doing the minimum possible amount of work. Make only recompiles when it is necessary.


Comments

Comment lines start with a '#' character (anywhere except in a command line), and continue until the end of the line.


Directives

A "directive" describes the relationship between a "target" (the file to be built), its "dependencies" or "sources" (the files used to create the target), and zero or more "command lines" that define the build process for the target:
target: source1 source2 ...
	command1
	command2
Long lists can be continued over multiple lines using "\" as a line continuation character. Command lines must begin with a <TAB> character. By placing a "@" character at the beginning of a command, you can keep it from being echoed to stdout by make as it is executed. By placing a "-" character at the beginning of a command, you can instruct make to ignore any non-zero exit status for that command.


What Will make Do?

To see what "make" will do without having it actually invoke any commands, use the "-n" command option on the command line. Then make will echo the commands it would have performed on stdout, but it will not actually invoke any of the commands.


Variables

You can define variables in a makefile and use them:
LIST_OF_FILES = file1 file2 \
		file3 file4

program1: $(LIST_OF_FILES)
	compile ${LIST_OF_FILES} -o program1


Environment Variables

You can refer to environment variables defined in your shell within a makefile just as if they were declared right in the makefile. Further, environment variable definitions override any global definitions appearing in the makefile when make is invoked with the "-e" option.
% export LIST_OF_FILES="file1 file2 file3 file4 file5"
% make -e program1


Variables on the Command Line

You can also define/redefine variables on the make command line:
% make LIST_OF_FILES="file1 file2 file3 file4 file5" program1
These definitions override whatever appears in the makefile itself.


Default Suffix Rules

It is possible to define "default" rules for constructing certain kinds of files from their dependencies. Such rules will be used if no command lines are given for a particular target. For example, to say how a C program should be compiled into an object file:
.c.o:
	$(CC) $(CFLAGS) $< -o $@
Here, the "$< and "$@" are special variables that refer to the source file for the current line, and the current target file, respectively. The default suffix rules for updating an object library are:
.c.a :
	$(CC) -c $(CFLAGS) $<
	ar rv $@ $*.o
	rm -f $*.o
Here "$*" refers to the filename part (without suffix) of the prerequisite. An example of a library reference in a makefile is:
prog : lib(sub1) lib(sub2) lib((module1)) prog.o
	$(CC) -o $@ prog.o lib


System Default Make Definitions

Make actually reads its default rules and default macro definitions from system files stored in /usr/share/mk. The file "sys.mk" in this directory is normally read by make. It defines rules for C, C++, FORTRAN, Pascal, assembly, lex, yacc files. It also defines basic macros/variables for the compilers used for such files.


mkdep

By default, the FreeBSD version of make will read the file ".depend" in the current directory in addition to "[Mm]akefile". It is normally invoked as:
	mkdep [cc-options] file1.c file2.c ...
It automatically produces directives (with no command lines) for all listed files, using the C preprocessor to determine the exact dependency list. Correct use of default rules and variables can then be used to direct the compilation of the corresponding C files.


gccmkdep

The GNU version of mkdep.




Using RCS


RCS (Revision Control System) is used for managing software development projects. It controls access to, and changes to, files by permitting only one authorized user at a time to modify a file. By default, RCS controlled files are stored in a directory RCS, and have the suffix ,v. Version numbers have the form release.level.branch.sequence, e.g., 4.2.1.20.



Sample RCS session

127 Cayuga> mkdir RCS
128 Cayuga> rcs -i blitz      # initialize file in RCS system
RCS file: RCS/blitz,v
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> Shell script for blitzing directories, named after the
>> Wehrmacht Blitzkrieg tactic.
>> .
done
129 Cayuga> rcs -alat,egm,ribbens,mcquain blitz #authorize users
RCS file: RCS/blitz,v
done
130 Cayuga> rcs -elat blitz     # deauthorize user
RCS file: RCS/blitz,v
done
131 Cayuga> ci blitz    # check in file, version number assigned
RCS/blitz,v  <--  blitz
initial revision: 1.1
done
132 Cayuga> co -l blitz   # check out file with exclusive right to modify
RCS/blitz,v  -->  blitz
revision 1.1 (locked)
done
133 Cayuga> ex blitz      # edit file
"blitz" 14 lines, 879 characters
:$a
Junk line at end.
.
:wq
"blitz" 15 lines, 897 characters
134 Cayuga> ci blitz   # check modified file back in
RCS/blitz,v  <--  blitz
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single '.' or end of file:
>> Added junk line at end using ex.
>> .
done
135 Cayuga> rcs -o1.1 blitz   # delete old version
RCS file: RCS/blitz,v
deleting revision 1.1
done
136 Cayuga> rlog blitz   # gives modification history




Layne Watson <ltw@cs.vt.edu>
Last modified: Tue Feb 3 16:19:27 EST 1998