Chapter 10: Make Up Chapter 10: Make Chapter 11: amake 

10.1 Makefiles

The following advice assumes that you are using GNU make (which has several constructs not available in other older versions of make).

10.1.1.1 Include File

Here is a sample set of definitions for an Aubit4GL Makefile:
# ---- Declare the following suffixes meaningful to make
.SUFFIXES: .afr .per
.SUFFIXES: .ao .4gl
.SUFFIXES: .iem .msg

# ---- Pattern rules for the above suffixes

%.afr : %.per   # equivalent to the old make form .per.afr:
(TAB)  fcompile $< 

%.ao : %.4gl
(TAB)  4glc -c $?

%.iem : %.msg
(TAB)  amkmessage $< $@
These definitions should be put into a separate file (say makedefs) in the parent directory. You can then include the makedefs file in the Makefile itself with the statement:
include ../makedefs
The benefit of using include files in this way is that you avoid repetition of the included elements, and maintenance is reduced to a single file.

10.1.1.2 Make glossary:

$? = all the newer prerequisites (which need recompiling)
$@ = the current target (left of the : in the prereq line)
$< = the first of the newer prerequisitess. This is suitable when the command can only compile 1 file at a time (like aubit fcompile).
$^ = all the prereqs (not just the newer ones). Use this when you need to relink all the object modules.
$* = the stem (matching % in prereq line).
%  = wildcard matches any sequence of zero+ chars. Note: the 2nd and subsequent % is the same sequence that the 1st % matched.
$?, $(?), and ${?} are all the same variable. If a variable has more than a 1 char identifier you must enclose the identifier in () or {}s
A modifier D, or F, can be used with $?, $@, $<, or $^ to return just the D(irectory part) or the F(ile part) of the filename.
e.g. if $? = ../lib/options.4gl then
$(?D) = ../lib and $(?F)= options.4gl
Note that these D and F modifiers are defined in make’s built-in rules as:
?D=$(patsubst %/,%,$(dir $?))
?F=$(not-dir $?)
etc
The $(dir arg) and $(not-dir arg) macros are available for use with any variables whether user defined or builtin. Note that the $(?D) definition removes the trailing slash from the directory path (substituting %/ with %)

10.1.1.3 Makefile Example

#
GPATH = ../lib ../per

.PHONY: all

all: prog prog.iem prog.afr proga.afr prog.iem

srcfiles = prog0.4gl prog1.4gl prog2.4gl ../lib/options.4gl
objfiles = $(srcfiles:.4gl=.ao)

prog : $(objfiles)
(TAB) aubit 4glc -o $@ $^

# Note the subtle difference here $^ (all prereqs are needed)
#  $? would link only the newly compiled objects

The example file above is for a program consisting of 4 modules:
This structure was common with Fourgen generated programs.

10.1.1 Pattern Rules

Rules in Makefiles take the form:
target : prereq1 [[prereq2 ] ... ]
(TAB) command1
...
Note that the invisible tab is a crucial part of the syntax of Make. These sometimes get corrupted into spaces in ftp transfers - so be careful!. A make rule specifies that the target files depend on the listed prerequisite files and supplies the command that make should execute whenever a prerequisite file is newer (that is modified more recently than) the target file(s).

10.1.2 Make variables

In Makefiles like the above, we use variables srcfiles and objfiles to minimise the work of changing definitions. Note that the assignment to objfiles is done using a substitution expression (.ao replaces .4gl from the srcfiles list). If we add another library module to the srcfiles list (say ../lib/names.4gl), no other change need be made to the Makefile.
Traditionally we have used uppercase for variable names in Makefiles. The GNU people now recommend that you use lowercase for better readablity.

10.1.3 GPATH and VPATH

Normally make will search only the current directory. If you want to force it to look elsewhere then you can set GPATH or VPATH to a list of search directories.
Directories listed in GPATH will we searched and the targets compiled into the remote directory.
Directories listed in VPATH will be searched but the targets compiled into the current directory.
In the example Makefile, options.ao will be compiled into ../lib/options.ao

10.1.4 .PHONY

Nearly all Makefiles have phoney targets: all, clean, install, and maybe others. GNU make allows you to declare these phoney targets (i.e. targets which are not real files to be built by commands). The benefit of doing this is the .PHONY declaration tells make to ignore any files called clean, install. etc. Omitting the .PHONY declaration might result in an accidentally created file called install, preventing make from executing the install commands.

10.1.5 Implicit rules

Note in the example that there is no specific rule for the help file and forms. These will be built by make using the make definitions we put into the include file. The targets: prog.iem, prog.afr, and proga.afr will be compiled using the %.iem : %.hlp and %.afr : %.per pattern rules in ../makedef.

10.1.6 Syntax

comments the hash symbol # comments out the rest of the line (i.e make ignores what follows the #).
quotes both single quotes ’ and double quotes " are treated literally. Do not use them in Makefiles. In shell programs you use quotes to inhibit interpretation and the shell strips them from its input. make does not do anything special to quotes.
longlines break a long line by putting a backslash \ before the end of line. This will tell make to remove the backslash and the end of line, and interpret the result as a single line.

10.1.7 Debugging make

A botched Makefile can destroy your sourcefiles.
To help debug your Makefiles, use the -n and -p options.
-p will display all the rules (including the builtins) that make is using
-n will cause make not to actually execute the command but display them to the screen
Type the command:
make -np prog
will cause make to display all its definitions and rules, and to display all the commands it would run if you had typed the command: make progAmake
amake is an x4GL specific set of rules and tools for GNU "make"
 Chapter 10: Make Up Chapter 10: Make Chapter 11: amake