Guide to the MMK Make Utility

Guide to the MMK Make Utility


October, 2008

This manual describes the MMK Make Utility, a "make" utility for VMS systems.

Revision/Update Information: This is a revised manual.

Operating System and Version: VAX/VMS V5.2 or later; OpenVMS Alpha V1.5 or later; OpenVMS IA64 V8.2 or later

Software Version: MMK V4.1


10 October 2008

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The following are trademarks of Hewlett-Packard Development Company, LP:
AXP DEC OpenVMS
VAX VMS  

UNIX is a registered trademark of USL, Inc.

Copyright ©2008 Matthew Madison. All rights reserved.

Copyright ©2008 Kednos Corporation. All rights reserved.

Contents


Preface

This guide explains how to install and use MMK.

Intended Audience

This manual is intended for all MMK users, primarily programmers who need to build software systems.

MMK is patterned after VAX DEC/Module Management System (DEC/MMS), which is in turn based on the UNIX make utility. The reader is assumed to have at least cursory knowledge of make or DEC/MMS.

Note

This document does not provide a general tutorial on make utilities. New users are advised to learn more about description files (makefiles) by reviewing either DEC/MMS documentation or books on the UNIX make utility.

Document Structure

tbs

Related Documents

tbs

Conventions

In this document, the following convention will be used for the names of the three similar utilities:


Chapter 1
Introduction

This chapter describes MMK. It includes an overview of MMK and basic information on its use.

1.1 Overview

MMK is a tool for building a "software system;" that is, a collection of one or more executable images or other types of files that are related to a particular project. Building a complex system by hand can be a difficult and time-consuming task; using command procedures can make the task easier, but it may still be time-consuming.

With MMK, you create a file called a Makefile or MMS description file to describe your software system: the objects (i.e., source files, object files, etc.) that comprise the system, the dependencies between those objects, and the commands used to build the system. When you invoke MMK, it performs the following steps:

  1. MMK reads and parses the description file, constructing a tree from the objects and dependencies listed in the file.
  2. It then identifies the object to be built (called the target).
  3. The tree of dependencies is traced from the target, and the revision dates for the files in that path are compared. If an object doesn't exist or is older than the object it depends on, the commands to build the object are executed in a subprocess. This continues until all objects along the dependency path have been checked and the target has been brought completely up-to-date.

In this way, MMK can execute the commands to rebuild only those pieces of your software system that need rebuilding due to a change that you have made. This can drastically reduce development time for a project.

1.2 Invoking MMK

Provided that MMK has been installed using the steps laid out in the installation instructions (file AAAREADME.INSTALL in the kit), you can invoke MMK from DCL as a foreign command:


$MMK

Full command syntax is given in MMK. By default, MMK looks for a description file called DESCRIP.MMS in the current directory; if that file does not exist, it then looks for a file called MAKEFILE. If it cannot find that file, an error is signaled. You can use the /DESCRIPTION qualifier to specify a different name for your description file, if needed.

MMK starts by reading the description file and constructing a tree from the objects listed in the description file (e.g., source files, include files, object files, etc.) and a tree of dependencies between those objects. It then identifies the target object to be built, and traverses the dependency tree to identify those objects that need to be built (called intermediate targets) in order to build the target.

MMK compares each target's revision date/time against the objects on which it depends and executes the actions for that building the target only if needed. You can force a complete rebuild by using the /FROM_SOURCES qualifier on the MMK command.


Chapter 2
Description Files

The key to successfully building your software system with MMK is the creation of a complete and accurate description file. This chapter describes the format for a description file and its components.

2.1 Description File Components

A description file is a collection of the following components:

Here is an example of a simple description file:


PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ 
    LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ 
MAIN.OBJ : MAIN.FOR 
    FORTRAN MAIN 
SUBROUTINES.OBJ : SUBROUTINES.MAR 
    MACRO SUBROUTINES 

This is a simple collection of dependencies and actions for building an image called PROGRAM.EXE. PROGRAM.EXE depends on two object files, called MAIN.OBJ and SUBROUTINES.OBJ; MAIN is a FORTRAN module and SUBROUTINES is a MACRO module.

MMK accepts either a colon or the DEC/MMS DEPENDS_ON keyword to separate a target object from its sources. In either case, the separator must be surrounded by blanks---this differs from make, but is consistent with DEC/MMS syntax.

2.2 Using Inference Rules

MMK includes a collection of built-in inference rules and actions for most VMS programming languages. The rules are driven by the file type suffix attached to the object name; you must use the default file types in order to make use of the default rules.

For example, the description file in the last section could be simplified to just:


PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ 
    LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ 
MAIN.OBJ : MAIN.FOR 
SUBROUTINES.OBJ : SUBROUTINES.MAR 

MMK's built-in inference rules automatically define the actions for building a .OBJ file from a .FOR (using the FORTRAN command) and for building a .OBJ file from a .MAR file (using the MACRO command).

The description file could even be simplified further, to just:


PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ 
    LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ 

MMK automatically searches the suffixes list when constructing the dependency tree and locates inference rules for the .OBJ files automatically. This illustrates the second use for inference rules: they are used not only for inferring actions for a dependency that omits them, but they may also be used for inferring dependencies themselves based on a combination of source and target suffixes. This second purpose can greatly simplify your makefiles, and makes the build process more automatic.

2.3 Defining Inference Rules

You can define your own inference rules, either to extend or replace the ones built into MMK. You may include these rule definitions in your makefile, or in a separate file called a rules file. Rules files can be included by the use of a logical name or through the /RULES qualifier on the MMK command; see the MMK for further information.

MMK supports two types of inference rules: generic and prefixed. Generic rules are based solely on suffixes (file types), as in:


.C.OBJ : 
    CC/OBJECT=$(MMS$TARGET) $(MMS$SOURCE) 
which says, to build filename.OBJ from an existing file called filename.C, use the CC command." In general, generic rules work best when the source and target files reside in the same directory.

Prefixed inference rules are based on both suffixes and "prefixes"---device and directory specifications. This provides a way to have MMK automatically infer dependenices between files that reside in different directories. For example: For example, the prefixed rule:


{SRC$:}.C{OBJ$:}.OBJ : 
    CC/OBJECT=$(MMS$TARGET) $(MMS$SOURCE) 

tells MMK, "to build OBJ$:filename.OBJ from an existing file called SRC$:filename.C, use the CC command." This works like the generic rule above, but with the additional provision of having the source and target reside in different locations.

You can have more than one prefixed rule for a particular pair of suffixes; you may also mix generic rules and prefixed rules for a pair of suffixes. When attempting to infer a dependency, MMK will first use the prefixed rules, then fall back to using the generic rule.

In prefixed rules, the curly braces ("{" and "}") are required. One of the two prefixes may be null, but specifying two null prefixes is equivalent to defining a generic rule.

In order to match a prefixed rule, file specification as it exists in the description file must match the prefix in the rule; MMK performs no logical name translation on prefixes, nor can it identify equivalencies between two prefixes that reference the same directory using different syntax.

The first inference rule for a pair of suffixes, whether it is generic or prefixed, must specify an action list; subsequent rules for the same pair of suffixes (with different prefixes) may have the action list omitted, in which case MMK will use the action list from the first rule. For example, MMK already has a built-in generic rule for .C.OBJ, which is:


.C.OBJ : 
    $(CC)$(CFLAGS) $(MMS$SOURCE) 

If you are simply adding a set of prefixed rules for the .C.OBJ suffix pair, you do not need to specify an action list on those rules; MMK will use the action list from the built-in generic rule.

2.4 Forced Setup/Teardown Actions in Inference Rules

MMK recognizes two special modifiers on action lines specified for inference rules. The setup modifier, "<", forces the execution of an action prior to any unmodified action. The teardown modifier, ">", forces the execution of an action after all other actions. Setup and teardown actions are performed for all dependencies matching the inference rule, even if a dependency includes explicit actions.

For example, the inference rule


.C.OBJ : 
    < DEFINE/USER DECC$SHR V6_ROOT:[SYSLIB]DECC$SHR 
      $(CC)$(CFLAGS) $(MMS$SOURCE) 

would cause the logical name DECC$SHR to be defined prior to the invocation of the C compiler for all compilations into .OBJ files. This would apply even on dependencies containing explicit actions, such as


FRED.OBJ : FRED.C 
  $(CC)$(CFLAGS)/DEFINE=FRED $(MMS$SOURCE) 

2.5 Modifying the Suffix List

MMK uses a suffix list to determine the inference rules it should search for inferring a dependency. MMK has a built-in suffix list which goes with its list of built-in inference rules; see Appendix B for more information on the built-in rules and suffix list.

You can augment or replace the built-in suffix list with your own suffixes by using the .SUFFIXES directive in a rules file or a makefile.

For example, let's say you have a Modula-2 compiler on your system, whose source files have a file type (suffix) of .MOD. MMK has no built-in inference rules for this file type; you could add one with the following sequence:


.SUFFIXES : .MOD 
 
.MOD.OBJ : 
    MODULA2/OBJECT=$(MMS$TARGET) $(MMS$SOURCE) 

The .SUFFIXES directive above adds the .MOD suffix to the end of the suffix list. This is followed by the inference rule for creating an object file from a Modula-2 source file.

Specifying the .SUFFIXES directive with nothing to the right of the colon clears the current suffix list. You can do this to prevent MMK from using any inference rules for the current build, or to follow it with another .SUFFIXES directive that specifies only those suffixes for which you want inference rules to be enabled.

2.6 Using Conditionals

MMK provides several directives that can be used to modify the build sequence based on conditions. These directives are .IF, .IFDEF, .IFNDEF, .ELSE, and .ENDIF. The .IFDEF, .ELSE, and .ENDIF directives work the same as for MMS; the .IF and .IFNDEF directives are MMK extensions. The .IFNDEF directive provides the logical inverse to .IFDEF; the check succeeds if the specified macro is not defined. The .IF directive supports more general comparisons. Its syntax is


.IF "expression1" comparison "expression2" 
where expression1 and expression2 can be any string that does not contain quotation marks. Macro references may be used in the expressions as long as the macro values do not contain quotation marks. The comparison operator is either EQL (equals) or NEQ (not equals). The quotation marks around the two expressions are required. Comparisons are performed without regard to upper/lower case.

2.7 Deferring Macro Substitution

MMK provides a way to defer the resolution of a macro that is referenced in the right-hand side of a macro definition, as an extension to MMS. Macros are normally referenced using the $(name) syntax, which causes the value of the macro to be substituted immediately when a line is parsed (except for MMK's "special" macros, such as MMS$SOURCE and MMS$TARGET).

You can defer this substitution in MMK by using the syntax ${name} instead. However, this syntax is only recognized on the right-hand side of a macro definition. This can be useful when defining macros in a rules file that rely on macros that do not get defined until another rules file or a description file gets processed. For example, you might have the following definition in a rules file:


CFLAGS = /OBJECT=$(MMS$TARGET)/NOLIST/DEFINE=(VMS_BUILD,${MOREDEFINES}) 
then in your description file, you can define the MOREDEFINES macro:


MOREDEFINES = ANOTHER_C_DEFINE 
This will complete the CFLAGS macro value when it is referenced later in the description file.

2.8 Macro String Substitution

MMK provides two mechanisms for causing string substitution to occur when resolving a macro reference: suffix substitution and general string substitution.

2.8.1 Suffix Substitution

When a string contains a list of file specifications, you can replace the file type suffixes on each file specification with a different suffix. The general form of this type of substitution is:

$(macro-name:old-sfx=new-sfx)

which causes the replacement of all occurences of the file type suffix old-sfx with new-sfx. Both suffixes must begin with a dot.

For example, in these macro definitions:


SOURCES = FIRST.C, SECOND.C, THIRD.C 
OBJECTS = $(SOURCES:.C=.OBJ) 
the OBJECTS macro would have the value FIRST.OBJ, SECOND.OBJ, THIRD.OBJ. This form of substitution works with file specification lists separated by either blanks, commas, or both. The substitution rule following the colon may also contain blanks, which are ignored. Substitutions are case-insensitive.

2.8.2 General String Substitution

General string substitution in macro references is an extended feature of MMK. It looks very similar to suffix substitution, but uses a double colon ("::") instead of a single colon and allows the substitution to occur anywhere within the string. The syntax is:

$(macro-name::old-str=new-str)

which causes the replacement of all occurences of the string old-str with new-str. You may use a backslash "\" as a "literal-next" escape when one of the strings contains an equals sign. Neither string may contain a right parenthesis character (")"), even quoted with a backslash, although this restriction will be lifted in a future release of MMK. For example, the following macro definitions:


SOURCES = FIRST.C,SECOND.C,THIRD.C 
SOURCEPLUS = $(SOURCES::,=+) 
would cause SOURCEPLUS to contain the list of filenames separated with plus signs (+) rather than commas.

General string substitutions in macro references are case-insensitive, but do not ignore blanks in the macro value or in the substitution rule. For example, in the following definitions:


TEST      = Xyz xYz xyZ 
REPLACED  = $(TEST::YZ =YZ,) 
the REPLACED macro would have the value XYZ,xYZ,xyZ, due to the case-blind comparisons and the inclusion of the space in the old-str specification.


Next Contents