CC Omake
CC Omake
CC Omake
Windows Edition
800-012616-000
ClearCase OMAKE Manual
Document Number 800-012616-000 December 1999
Rational Software Corporation 20 Maguire Road Lexington, Massachusetts 02421
IMPORTANT NOTICE
Copyright Notice
Copyright © 1992, 1999 Rational Software Corporation. All rights reserved.
Copyright 1989, 1991 The Regents of the University of California
Copyright 1984–1991 by Raima Corporation
Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana 47907
Trademarks
Rational, the Rational logo, Atria, ClearCase, ClearCase MultiSite, ClearCase Attache, Clear DDTS,
ClearQuest, ClearGuide, PureCoverage, Purify, Quantify, Rational Rose, and SoDA are trademarks or
registered trademarks of Rational Software Corporation in the United States and in other countries. All other
names are used for identification purposes only and are trademarks or registered trademarks of their
respective companies.
Microsoft, MS, ActiveX, BackOffice, Developer Studio, Visual Basic, Visual C++, Visual InterDev, Visual J++,
Visual Studio, Win32, Windows, and Windows NT are trademarks or registered trademarks of Microsoft
Corporation.
Sun, Solaris, and Java are trademarks or registered trademarks of Sun Microsystems, Inc.
Oracle and Oracle7 are trademarks or registered trademarks of Oracle Corporation.
Sybase and SQL Anywhere are trademarks or registered trademarks of Sybase Corporation.
U.S. Government Rights
Use, duplication, or disclosure by the U.S. Government is subject to restrictions set forth in the applicable
Rational License Agreement and in DFARS 227.7202-1(a) and 227.7202-3(a) (1995),
DFARS 252.227-7013(c)(1)(ii) (Oct 1988), FAR 12.212(a) 1995, FAR 52.227-19, or FAR 52.227-14, as applicable.
Patent
U.S. Patent Nos. 5,574,898 and 5,649,200 and 5,675,802. Additional patents pending.
Warranty Disclaimer
This document and its associated software may be used as stated in the underlying license agreement, and,
except as explicitly stated otherwise in such license agreement, Rational Software Corporation expressly
disclaims all other warranties, express or implied, with respect to the media and software product and its
documentation, including without limitation, the warranties of merchantability or fitness for a particular
purpose or arising from a course of dealing, usage or trade practice.
Technical Acknowledgments
This software and documentation is based in part on BSD Networking Software Release 2, licensed from the
Regents of the University of California. We acknowledge the role of the Computer Systems Research Group
and the Electrical Engineering and Computer Sciences Department of the University of California at Berkeley
and the Other Contributors in its development.
This software and documentation is based in part on software written by Victor A. Abell while at Purdue
University. We acknowledge his role in its development.
Preface .......................................................................................................................................xv
About This Manual ..........................................................................................xv
ClearCase Documentation Roadmap .......................................................... xvi
Typographical Conventions ........................................................................ xvii
Online Documentation ................................................................................ xviii
Technical Support ........................................................................................ xviii
1. Introduction ........................................................................................................................... 1
1.1 File Manifest........................................................................................................ 1
1.2 Configuring omake ............................................................................................ 2
1.3 Notes on Using omake ...................................................................................... 2
omake’s Configuration Management Features.............................................. 2
Configuration Lookup................................................................................ 3
Derived Object Sharing .............................................................................. 3
Configuration Record Creation................................................................. 3
Express Builds ............................................................................................. 3
Command-Line Options ............................................................................ 3
Location of Temporary Files...................................................................... 4
Non-MVFS Dependencies ......................................................................... 4
Differences Between omake and Standard Make Tools ...............................4
Running omake .................................................................................................. 5
Makefiles.............................................................................................................. 5
Supporting Both omake and clearmake .................................................. 5
Parallel and Distributed Build Operations..................................................... 6
Build Scripts and the rm Command................................................................ 6
Pathnames in CRs .............................................................................................. 6
1.4 Auditing 16-bit Tools......................................................................................... 7
Contents iii
Contents v
3. omake Reference................................................................................................................41
3.1 Command-Line Options..................................................................................41
Initial Command-Line Parameters: OMAKEOPTS .....................................41
The Command-Line Options ..........................................................................42
The Current Options ........................................................................................46
3.2 Locating the Initialization File ........................................................................46
Disabling the Initialization File ......................................................................46
3.3 The Make Process .............................................................................................47
Read Time ..........................................................................................................47
Run Time............................................................................................................47
Run-Time Initialization and Deinitialization ........................................48
Updating the Time Stamp ...............................................................................49
3.4 Targets ................................................................................................................49
Case-Sensitivity of Target Names ..................................................................49
A Target Has a Name and a Pathname .........................................................49
Using the Path Separator in Names ...............................................................50
The First Target in the Makefile Is the Default Target ................................50
Targets May Appear on Several Dependency Lines ...................................50
Double-Colon Dependency Lines ..................................................................51
Mixing Single-Colon and Double-Colon Dependency Lines.....................51
Targets Without Dependencies ......................................................................51
Target Groups ...................................................................................................51
3.5 Macros ................................................................................................................52
Macro Modifiers................................................................................................52
Filename Components ..............................................................................53
Absolute Pathname ...................................................................................53
Append and Prepend Strings ..................................................................54
Change Case...............................................................................................54
Expand Pathnames....................................................................................54
Include File .................................................................................................54
Contents vii
Contents ix
Contents xi
E. Regular Expressions.......................................................................................................167
E.1 Configuration of Regular Expressions ........................................................167
Regular Expression Components .................................................................167
Referencing the Matched Expression ..........................................................169
E.2 Macro Modifiers in OMAKE.........................................................................169
Regular Expressions for the M Modifier .....................................................169
Regular Expressions for the S Modifier.......................................................170
Glossary ...................................................................................................................................171
Index..........................................................................................................................................175
Tables xiii
The ClearCase omake software build program provides compatibility with Windows NT-based
make tools.
This manual is for users who are new to the omake tool and who may have other experience with
make tools. It provides information on setting up omake, gives an overview of building
programs using omake, and describes omake usage. The appendices contain information on
error messages, macros and rules, compatibility, and regular expressions.
If you are already familiar with the build process and makefiles, the recommended sequence for
proceeding through the documentation is:
If you are not familiar with the build process and makefiles, the recommended sequence for
proceeding through the documentation is:
Building Software with ClearCase provides additional information about using the clearmake and
omake build tools.
Preface xv
ClearCase Documentation Roadmap
Project
Development Management
Developing Managing
Software with Projects with
ClearCase ClearCase
Orientation
Introduction to
ClearCase
ClearCase and
MultiSite Release
Notes ClearCase Build
ClearCase Administration Management
Tutorials
Administering ClearCase
ClearCase OMAKE Manual
(Windows)
ClearCase
Product Family Building
Installation Notes Software with
ClearCase
ClearCase
MultiSite Manual
More Information
ClearCase Reference
Manual
ClearCase Quick
Reference Guide
ClearCase Online Help
clearcase.rational.com
➤ ccase-home-dir represents the directory into which the ClearCase Product Family has been
installed. By default, this directory is C:\Program Files\Rational\ClearCase.
➤ attache-home-dir represents the directory into which ClearCase Attache has been installed.
By default, this directory is C:\Program Files\Rational\Attache, except on Windows 3.x,
where it is C:\RATIONAL\ATTACHE.
➤ Bold is used for names the user can enter; for example, all command names, file names, and
branch names.
➤ Italic is used for variables, document titles, glossary terms, and emphasis.
➤ A monospaced font is used for examples. Where user input needs to be distinguished
from program output, bold is used for user input.
➤ Nonprinting characters are in small caps and appear as follows: <EOF>, <NL>.
➤ Key names and key combinations are capitalized and appear as follows: F1, SHIFT,
CTRL+G.
➤ {} Braces enclose a list from which you must choose an item in format and syntax
descriptions.
➤ ... In a syntax description, an ellipsis indicates you can repeat the preceding item or line
one or more times. Otherwise, it can indicate omitted information.
NOTE: In certain contexts, ClearCase recognizes “...” within a pathname as a wildcard, similar
to “*” or “?”. See the wildcards_ccase reference page for more information.
➤ If a command or option name has a short form, a “medial dot” ( ⋅ ) character indicates the
shortest legal abbreviation. For example:
lsc·heckout
This means that you can truncate the command name to lsc or any of its intermediate
spellings (lsch, lsche, lschec, and so on).
Preface xvii
Online Documentation
There are three basic ways to access the online help system: the Help menu, the Help button, or
the F1 key. Help➔Help Topics provides access to the complete set of ClearCase online
documentation. For help on a particular context, press F1. Use the Help button on various dialog
boxes to get information specific to that dialog box.
ClearCase also provides access to full “reference pages” (detailed descriptions of ClearCase
commands, utilities, and data structures) with the cleartool man subcommand. Without any
argument, cleartool man displays the cleartool overview reference page. Specifying a command
name as an argument gives information about using the specified command. For example:
> cleartool man man (display the cleartool man reference page)
> cleartool man checkout (display the cleartool checkout reference page)
ClearCase’s –help command option or help command displays individual subcommand syntax.
Without any argument, cleartool help displays the syntax for all cleartool commands. help
checkout and checkout –help are equivalent.
Additionally, the online ClearCase Tutorial provides important information on setting up a user’s
environment, along with a step-by-step tour through ClearCase’s most important features. To
start the ClearCase Tutorial, choose Tutorial from the Getting Started tab of the ClearCase Home
Base.
Technical Support
If you have any problems with the software or documentation, please contact Rational Technical
Support via telephone, fax, or electronic mail as described below. For information regarding
support hours, languages spoken, or other support information, click the Technical Support link
on the Rational Web site at www.rational.com.
Preface xix
xx ClearCase OMAKE Manual
1 Introduction
1
omake is a programming tool that helps you maintain programs, particularly those that are
constructed from several component files. omake controls the entire process of building your
program, whether it involves preprocessing files, compiling, linking, or other steps. It keeps
track of the project files, recompiling and relinking them only when required. Moreover, omake
maintains important information, such as compiler and linker options, in an editable text file
called a makefile. If you've ever returned to a project after a long absence, you know how hard
is to remember all the parameters that were used the last time the project was built. omake
remembers everything about the project for you.
ClearCase includes two independent build programs: clearmake and omake. Both incorporate
the major ClearCase build-related features, including configuration lookup, derived object sharing,
and configuration record maintenance. The omake program’s strength lies primarily in its support
for users who require compatibility with other PC-based build programs, including Borland®
Make, Microsoft® NMAKE, PolyMake, and Opus Make.
NOTE: omake is intended for use in dynamic views. You can use omake in a snapshot view, but none
of the features that distinguish it from ordinary make programs — build avoidance, build
auditing, derived object sharing, and so on — works in snapshot views. The rest of the
information in this manual assumes you are using omake in a dynamic view.
1 - Introduction 1
make.ini Sample omake initialization file
omake.exe omake executable
One of the major features of omake is its ability to emulate either PolyMake/PVCS
Configuration Builder or Microsoft NMAKE. The emulation is enabled with a command-line
option. See PM/CB Emulation on page 152 and NMAKE Emulation on page 158 for more
information. Throughout this document, PM/CB refers to PolyMake/Configuration Builder,
and NMAKE refers to Microsoft NMAKE.
For more information on the ClearCase build model, see Building Software with ClearCase and the
clearmake reference page.
The features described here constitute the core of ClearCase build configuration management.
ClearCase omake uses a build-avoidance scheme based on configuration lookup that is more
sophisticated than the conventional make and Opus Make schemes, which are based on time
stamps of built objects. For example, the omake build-avoidance scheme guarantees correct
build behavior as C-language header files change, even if the header files are not listed as
dependencies in the makefile. By default, omake uses configuration lookup when you are
working in a view, and the target is located in the MVFS.
Developers working in different views can share the MVFS objects created by omake builds. See
the clearmake reference page for details.
omake audits the build operations, generating software bill-of-materials records, called
configuration records, that fully document a build. In the process, omake also performs automatic
dependency detection. By default, configurations records are created whenever you run omake
from a ClearCase view, and derived files are stored in the MVFS. See the clearmake and catcr
reference pages for details.
Express Builds
You can use either omake or clearmake during an express build, which is a build that creates
nonshareable derived objects. Express builds do not write DO information to the VOB, and
therefore enhance site-wide performance because they do not block other users’ access to the
VOB. For more information on express builds, see Building Software with ClearCase.
Command-Line Options
1 - Introduction 3
Location of Temporary Files
The CCASE_AUDIT_TMPDIR environment variable controls the location of build audit temporary
files. By default, these files are stored in the directory named by the TMP environment variable.
If you do not set CCASE_AUDIT_TMPDIR, make sure that TMP is set to a valid temporary storage
directory on a FAT, NTFS, or LAN Manager file system. Note that setting CCASE_AUDIT_TMPDIR
to a location on a remote file system increases build times.
Non-MVFS Dependencies
➤ If the dependency resides on a local drive, you can use the local drive letter. However, to
share the applicable derived object, users on other hosts must access the dependency using
the same drive-specific pathname.
➤ If the dependency resides on a remote host, you must use UNC names. (If you use drive
letters, only users with identical network drive configurations can share the resultant DOs.)
➤ Double-colon (::) rules. If any instance of a double-colon rule is out of date (based on
configuration lookup), all double-colon build scripts for the affected target are executed.
Conversely, if an error occurs during a build of the target of a double-colon rule, the target’s
remaining build scripts are not executed, and no config records or derived objects are
constructed. For example:
install::foo.exe
copy foo.exe \inst\bin
install::bar.exe
copy bar.exe \inst\bin
If foo.exe or bar.exe is out of date, both build scripts are executed. (Both programs are
copied.)
Typically, you run omake from a view using the following procedure:
1. Set a view context by assigning a drive to a view (with Tools➔Map Network Drive in
Windows Explorer or the net use command) and changing to that view:
c:\> f:
f:\>
You are using a view context to prevent VOB pathnames from being dependent on the view
the build occurs in. From f:, you (and your makefiles) can access versioned objects with
non-view-extended, absolute VOB pathnames such as \vob2\src\main.c in either cleartool
commands or standard operating system commands.
If you work directly on M:, in view-extended namespace, full pathnames to VOB objects
include a view-specific prefix, which can affect configuration lookup so as to prevent DO
sharing between views.
Makefiles
There are several rules to follow when constructing, or converting, makefiles for use by omake
on a Windows NT host.
It is possible, but not trivial, to prepare makefiles that can be used with either omake or
clearmake. The general approach is to supply omake-specific macro definitions in the makefile,
and to supply clearmake-specific macro overrides in a build options specification (BOS) file;
clearmake reads the BOS file, but omake does not. When clearmake executes, it looks for macro
definitions in two locations:
1 - Introduction 5
➤ %HOME%\.clearmake.options
➤ makefile.options, in the same directory as makefile (substitute the actual name of your
makefile, if it is not makefile)
BOS files at other locations can be passed to clearmake with the –A option.
Each omake build executes serially on the local Windows NT host. Parallel and distributed build
operations are not available.
It is common for a makefile to include a target whose build script invokes a command such as
rm to delete files. Some Windows NT installations include rm commands that do not actually
delete a file, but move it to a deleted directory instead. As a result, build script temporary files
become sibling DOs of the targets. To avoid this problem, use a remove command—del, for
example—that actually deletes files.
Pathnames in CRs
In a config record created on Windows NT, MVFS object pathnames begin with the VOB-tag and
do not include view-tag prefixes. For example:
...
---------------------------- MVFS objects: ----------------------------
\proj1\include\cmsg.h@@\main\nt3\39 <22-Jul-94.17:49:53>
\proj1\lib\fsutl.h@@\main\12 <22-Jun-94.12:07:24>
...
Pathnames in this format can be cut and copied, and applied elsewhere as is, if you are on a drive
assigned to a view (with Tools ➔ Map Network Drive in Windows Explorer or the net use
command).
The program vdmaudit allows auditing of 16-bit tools. To use vdmaudit, you need to have
omake run vdmaudit and let it call the 16-bit tool. This involves either editing the makefile
where it calls the 16-bit tool, or if your makefile defines a macro for each 16-bit tool, redefining
the macros in the makefile or on the omake command line.
If the makefile defines a macro for each 16-bit tool, you can change the macros to call vdmaudit.
For example, if your makefile contains macros like
CPP=cl.exe
LINK=link.exe
CPP=vdmaudit cl.exe
LINK=vdmaudit link.exe
You can redefine the macros on the omake command line like this:
Call all 16-bit tools from vdmaudit; if you do not, omake does not audit all tools and the
configuration record is incomplete.
An alternative method for auditing 16-bit tools is to use the ClearCase Virtual Device Driver
(VDD). To install the VDD during ClearCase installation, select 16-bit build auditing on the
ClearCase Client Options or ClearCase Server Options page. The VDD runs any time a 16-bit
tool is run, whether during an audit or not. However, the VDD can cause 16-bit tools to fail to
display all output or to fail to clear the screen when done.
1 - Introduction 7
8 ClearCase OMAKE Manual
2 Overview of Using omake
2
This chapter provides an overview of using omake to build and maintain programs. It describes
the process omake uses to build programs, the files you use to control omake’s operation, and
some selected features of omake.
➤ read time, when it reads the files (called makefiles) that provide it with a project description
A project consists of one or more targets. A target is a thing that can be made, usually a file, such
as a source file, object file, or executable file. The target is said to exist if the file is present on disk.
The pathname to a target is its location on disk. The target’s configuration record (CR) is a software
bill of materials record that fully documents the build of the target and supports omake’s ability
to rebuild. The CR includes the following information:
➤ Which MVFS file system objects (and which versions of those objects) were used by the
build as input data
The target's time stamp is the time the target was last changed. This is usually the creation or
modification time of the file.
The things a target depends on are its dependencies. In fact, dependencies are also targets because
they can be (and are) made.
To make or build a target means to bring it up to date. A build script (sometimes referred to as a
shell line) is a command that omake executes to bring a target up to date. For example, a link
command updates an executable file. The command returns an exit status, which lets omake
know whether it succeeded. If the command succeeds, omake generates and stores a
configuration record. This configuration record is attached to each file modified or created by
executing the build script. A file produced by the build and associated with a configuration
record is called a derived object (DO).
If the target (derived object) is located in the MVFS, omake uses configuration lookup to
determine whether it is necessary to rebuild a derived object by executing a build script or by
reusing an existing instance of the derived object. omake traverses the dependency tree and
compares the configuration record of each target to the build configuration of the current view
(the set of dependency versions, the current build script, and the current build options),
rebuilding the target if necessary. For each target, the tree is traversed to the bottom and back up.
If the target is not in a VOB, omake compares the time stamp of the target to those of its
dependencies. If the target is older than any of its dependencies, omake rebuilds it.
Note that if you are working in a snapshot view, omake does not perform configuration lookup
and it does not create derived objects or configuration records. For more information about
snapshot views, see Developing Software with ClearCase.
NOTE: In this chapter, the examples assume that the files are in a VOB.
Each macro is a macro definition of the form name=[value]. Macros defined on the command line
take precedence over macros defined in the makefile. See Macros on page 21.
Each target is a target you want omake to build. If no targets are listed on the command line,
omake builds the makefile's default target.
Each @file directs omake to read file for additional options, macros, targets and @files. The @file is
treated as if the contents of file were on the command line except that each end-of-line character
in file is treated as a space.
You do not have to group options, macros, or targets on the command line; you can intermix
them. However, omake reads makefiles in order of their placement on the command line, and
builds targets in order as well. If the same macro or parameter is defined more than once on the
command line, the last definition is the one omake uses.
The initialization file contains instructions for all make programs and is used to customize the
operation of omake. omake reads the initialization file, ccase-home-dir\bin\make.ini, whenever
it starts up.
The initialization file contains targets, inference rules, and macro definitions that you do not
want to duplicate in every makefile, and it is used to customize the operation of omake. The
initialization file is processed like a makefile, with the following exceptions:
➤ The first target in the first makefile is the default target and is built if no command-line
targets are specified. There is no special significance to the first target in the initialization
file.
The Makefile
The makefile has instructions for a specific project. The default name of the makefile is literally
makefile, but you can specify a different name with the –f option. The –f file command-line
option names the makefile, and several –f options can be given; each makefile is read in the order
it appears on the command line. If there are no –f command-line options, omake tries the file
named makefile. If it doesn't exist, omake tries makefile.mak.
Continued Lines
Lines in the makefile can be very long; the total makefile line length is limited only by available
memory. For easier reading, a long line can be broken up by typing \<ENTER> after part of the
line and typing the rest of the logical line on the next physical line of the makefile. For example,
the line
first_part_of_line second_part_of_line
is the same as
first_part_of_line \
second_part_of_line
To have the backslash (\) as the last character on the line, use \\<ENTER> or \<SPACE>,<ENTER>.
Comments
The simplest makefile statement is a comment, which begins with the comment character (#).
Everything on a makefile line after the # is ignored. Use \# for a literal # character. The following
large comment may appear in a makefile to describe its contents:
#
# Makefile for omake
#
# Compiler: Microsoft Visual C++ 5.0
# Linker: Microsoft(R) 32-Bit Incremental Linker Version 5.00.7022a
#
If \<ENTER> appears on a commented line, the comment acts until the end of the line and the
following line is still continued. The following examples are equivalent:
line_one \
line_two # more_line_two \
line_three
With a few exceptions, the initialization file holds the same kind of information as a makefile.
Both the initialization file and makefiles consist of these components:
➤ Rules
➤ Dependency lines
➤ Build scripts
➤ Macro definitions
➤ Inference rules
➤ Response files
➤ Directives
2.4 Rules
A rule tells omake both when and how to make a file. For example, suppose your project involves
compiling source files main.c and io.c, and linking them to produce the executable project.exe.
The following makefile manages the task of making project.exe:
main.obj : main.c
cl /c main.c
io.obj : io.c
cl /c io.c
This makefile shows three rules, one each to make project.exe, main.obj, and io.obj. These rules
are called explicit rules because they are supplied in the makefile. omake also has inference rules
that generalize the make process. Inference rules are discussed in Inference Rules on page 29.
To the left of the colon is the target of the dependency. To the right of the colon are the dependencies
needed to make the target. The target depends on the dependencies. For example, the following
line states that project.exe depends on main.obj and io.obj:
There can be one or more targets, optionally a list of target attributes, a colon, one or more space
or tab characters, and an optional list of dependencies. (Other make programs may call the
dependency a source, dependent, or prerequisite.) The first target name must start in the first
column of the makefile.
Dependency lines specify when to make the target. omake uses configuration lookup to
determine whether to build the target or reuse an existing derived object.
The dependencies that are listed explicitly on dependency lines are called explicit dependencies.
For example, the line
declares that test.exe depends on main.obj and sub.obj. When omake builds test.exe, it uses
configuration lookup to compare test.exe with your current build configuration to see whether
it must be updated.
A dependency line can declare that several targets have several dependencies. In the following
line, both main.obj and sub.obj depend on both system.h and io.h:
omake also has inference rules to infer a dependency of a particular target. Sources determined
using inference rules are called inferred dependencies. For a discussion of inference rules, see
Inference Rules on page 29.
The name of the target (and its root name) can be referenced in a dependency line through the
use of macros. For example:
omake processes the target main.obj first; the expression $* evaluates to the root of the target
name, main. The dependency line declares that main.obj depends on main.h and io.h. Next,
sub.obj is processed, with $* evaluating to sub. Thus, this line also declares that sub.obj depends
on sub.h and io.h.
A basic feature of omake is to make a target's dependencies before the configuration lookup is
performed for the target. The following line instructs omake to make main.obj and io.obj before
performing configuration lookup for project.exe:
This line instructs omake to make main.c before performing configuration lookup for main.obj:
main.obj : main.c
Unlike standard make variants, omake does not require you to declare source-file dependencies
in the makefile; omake detects dependencies automatically. This feature guarantees, for
example, correct build behavior as C-language header files change, even if the header files are
not listed as dependencies in the makefile. However, the list of dependencies must include
build-order dependencies, for example, object modules and libraries that must be built before
executables.
NOTE: You may want to include source-file dependencies in your makefile to ensure portability
to another group or company that is not using omake.
The dependency side of a dependency line can use a wildcard specification such as this:
main.exe : *.obj
omake provides this feature, but using it can cause problems if a required file is missing. For
example, the line
main.exe : *.obj
link /out:$(.TARGET) $(.SOURCES)
works fine until a required .obj file is accidentally deleted. omake works until the next update of
main.exe, when the link command isn’t called with all the required object names.
The colon (:), which separates targets and dependencies on a dependency line, is also the
character used as the drive separator in Windows NT. To distinguish this colon from the drive
separator, you must put white space in front of it or put a space (target:<SPACE>), a tab
(target:<TAB>), a semicolon (target:;), another colon (target::), or nothing (target:<ENTER>) after it.
We suggest putting at least one space before and after it.
Assume the program test.exe is linked from main.obj and sub.obj. These object modules are
compiled from source files main.c and sub.c, respectively. The makefile looks like this:
Line D-1 declares that test.exe depends on main.obj and sub.obj. Lines D-2 and D-3 declare that
main.obj depends on main.c and sub.obj depends on sub.c.
Assume that since the last build of test.exe, main.c has been changed and sub.c has not. Running
omake causes the first target in the makefile, test.exe, to be evaluated. test.exe depends on
main.obj, which depends on main.c. main.c doesn't depend on anything. Comparing the
configuration record of main.obj with the current view’s build configuration shows that
main.obj must be rebuilt using the selected version of main.c. This is done with the build script:
cl /c main.c
Next, sub.obj, which depends on sub.c, is evaluated. Configuration lookup shows that sub.obj
does not need updating.
Comparing the configuration record of test.exe with the current build configuration shows that
test.exe must be rebuilt with the selected version of main.obj. The following build script updates
test.exe:
Running the command omake again causes omake to display this message:
For example, the following makefile specifies that making project.exe requires running the
program link to link main.obj and io.obj. This build script is run only if omake determines that
project.exe needs to be rebuilt.
A build script can appear on the dependency line by separating it from the last dependency by
a semicolon. For example, the following lines are equivalent:
test.exe : test.c
cl /c test.c
A target can have a build script with multiple lines, listed one after the other. For example:
The first line shows that Windows NT command processor commands can be executed by
omake. The second line shows redirection of output, where the output of the link program is
redirected to the link.out file.
➤ By passing the build script to a shell program such as cmd.exe. This method is slower and
takes additional memory, but is necessary if the build script requires a feature that only the
shell program can provide.
Each build script runs in its own child process or subshell of omake, starting in the current
directory. This behavior has special consequences for commands that are supposed to have effect
between build scripts. For example, the build scripts
copy_to_tmp :
# Comment and blank lines are allowed
chdir some_directory
copy *.* c:\temp
copy the files that match *.* in the current directory to c:\temp. This occurs because the copy
command starts in the current directory, irrespective of the chdir command executed before it.
See Using Multiple-Command Build-Script Lines on page 73 for the correct way to do this.
Auto-Detection Mode
By default, omake detects when to use the shell program (defined by the .SHELL directive; see
Table 15 on page 92) and when to use direct execution. The shell program is used when the
command is or does one of the following:
break, call, cd, chdir, cls, copy, ctty, date, del, delete, dir, echo, erase, for, if, md, mkdir, path,
pause, prompt, rd, rem, ren, rename, rmdir, set, time, type, ver, verify, vol
To change the list of internal commands, use the SHELLCOMMANDS macro. See Table 5
on page 67.
The standard execution mode is to use the shell program for every build script. For Windows NT,
the default shell program is named in the COMSPEC environment variable. If this EV is not
defined, cmd.exe is used.
omake can execute the build script without using the shell program if the command being run
is executable and the build script does not use I/O redirection. Use the colon (:) build-script
prefix to have omake execute the build-script line without using the shell program (see Select the
Shell Program on page 71).
After it executes each build-script line, omake checks the command exit status. The exit status is
a number the program returns and is tested by omake. At the Windows NT command line, you
can check the exit status of the last executed program by using the if errorlevel command.
By convention, programs return a zero exit status when they finish without error and a nonzero
status when an error occurs. The first build-script line that returns a nonzero exit status causes
omake to display this message:
This usually means that the program being executed failed. Immediately after displaying this
message omake does any necessary deinitialization and exits. You can control this behavior with
the –i or –k command-line options (see Command-Line Options on page 41), with build-script line
prefixes (see Build-Script Line Prefixes on page 69), or with target attributes (see Target Attributes
on page 101).
Some programs return a nonzero line exit status inappropriately; you can have omake ignore the
exit status by using a build-script prefix. Prefixes are characters that appear before the program
name and modify the way omake handles the command script. For example:
The dash (–) prefix causes omake to ignore the exit status of that build-script line. If the exit status
is nonzero, omake displays the following message:
2.7 Macros
A macro is a makefile line that consists of a macro name, an equal sign ( = ), and a macro value. In
the makefile, a macro reference is an expression of the form $(name) or ${name}. The reference is
macro-expanded to produce value. When name is a single character, the ( ) or { } around name are
optional; for example, $X, $(X), and ${X} all specify the value of macro X. The macro character ($),
always instructs omake to expand the macro that follows. When you need a dollar sign in your
makefile, you must use $$.
In the following makefile, the text main.obj io.obj occurs more than once. To reduce the
amount of repeated text, you can use a macro definition to assign a symbol to the text.
main.obj : main.c
cl /c main.c
io.obj : io.c
cl /c io.c
Here is the same makefile written with the introduction of four macros:
project.exe : $(OBJS)
link $(OBJS) /out : project.exe
main.obj : main.c
$(CC) $(CFLAGS) main.c
io.obj : io.c
$(CC) $(CFLAGS) io.c
The value of the OBJS macro is the list of object files to be compiled. The macro definitions for
CC and CFLAGS make it easier to change the name of the C compiler and its options.
Macro Precedence
Macros can be defined in makefiles, defined on the command line, or predefined by omake.
omake also accesses the values of environment variables as if they were macros.
Where a macro is defined determines its precedence. To redefine an existing macro, the new
definition must have at least as high a precedence. This is the order of precedence:
2. Command-line definition
By default, the lowest precedence for a macro is the environment definition. The –e
command-line option gives the environment definition a higher precedence than the makefile
definition. With this option, a macro definition in a makefile does not redefine a macro from the
environment.
Macros are defined at read time in a makefile with macro definition lines of the form
name = [ text ] standard definition
name ?= [ text ] conditional definition
name := [ text ] expanded definition
name += [ text ] appended definition
where name is the macro name starting in the first column of the makefile. The name can include
any characters except the equal sign (=), the colon (:), and white space. By convention, the name
is composed of uppercase letters, periods (.), and underscores (_). Any macro references in name
are expanded; if you want a literal dollar sign in name you must use $$.
At read time, some parts of a makefile are macro-expanded; other parts are not expanded until
later.
For macro definitions, expansion depends on the separator between the macro name and the value:
= macro name is expanded; value is not expanded until referenced
(In NMAKE compatibility mode, value is expanded before assignments)
?= macro name is expanded; value is not expanded until referenced
+= macro name is expanded; value is not expanded until referenced
:= macro name is expanded; value is expanded
%if condition
%elif condition
The condition is macro-expanded and evaluated only if the previous enclosing condition is true.
For example:
%if condition_1 (expanded & evaluated)
% if condition_2 (expanded & evaluated only if condition_1 is true)
% endif
%else
% if condition_3 (expanded & evaluated only if condition_1 is false)
% endif
%endif
This definition defines macro name and sets its value to text. If text is not given, the value of the
macro is the null string, “”. White space before or after the = is ignored.
This definition is like the standard macro definition, but the macro is defined only if it isn't
already defined. White space between name and ?= and between ?= and text is ignored.
This definition defines macro name and sets its value to the macro-expansion of text. The text is
arbitrary text and can refer to the value of other macros with expressions of the form
$(other_macro), which are expanded. If text is not given, the value of the macro is the null string
(“”). White space between name and := and between := and text is ignored. Expanded macro
definitions are useful when the text is expensive to calculate (it may require reading a file, for
example).
This definition appends text to the current value of macro name. White space between name and
+= is ignored. If there is no white space between += and text, the new value is OLDVALUEtext.
Otherwise, the new value is OLDVALUE <SPACE> text (with one intervening space). If name is an
undefined macro, this definition is the same as a standard macro definition.
By default, for Windows NT omake macro names are case-insensitive. The .CASE_MACRO and
.NOCASE_MACRO directives turn case-sensitivity on and off.
By convention, macro definitions appear at the beginning of the makefile. Macros must be
defined before they are expanded; if they are not, their expanded value is the null string.
Usually name starts in the first column of the makefile line, but macro definitions can be indented
(for example, inside an %if...%endif conditional directive). Indenting is allowed only before the
first target in the makefile, or after a nonindented macro definition. This restriction is a
consequence of omake's use of indenting to indicate a target's build scripts.
Undefining Macros
%undef CFLAGS
Some macros that omake predefines cannot be undefined with this directive.
➤ This defines the macro OBJS as main.obj sub.obj. $(OBJS) is main.obj sub.obj.
➤ This defines PROJECT as $$/Make. $$ is a literal dollar sign. This means that $(PROJECT)
is $/Make.
PROJECT= $$/Make
➤ These define the macro DEBUG as 7 and the macro CFLAGS as –Z$(DEBUG). $(DEBUG)
is 7 and $(CFLAGS) is –Z7.
DEBUG = 7 (defined as 7)
DEBUG ?= i (not redefined)
CFLAGS = –Z$(DEBUG)
➤ This shows an appended macro definition inside a conditional directive. If the OPT macro
is defined, the CFLAGS macro's value has <SPACE>–Od appended to it. The new value of
CFLAGS is –Z$(DEBUG) –Od and $(CFLAGS) is –Z7 –Od.
%if defined(OPT)
CFLAGS += –Od
%endif
➤ This defines macro OBJSLIST as project.lst and then defines OBJS. The := causes the right
side to be expanded. OBJSLIST is expanded, producing project.lst and the @ macro
modifier (see Macro Modifiers on page 52) reads the file project.lst. The contents of this file is
the value of OBJS. The expression := is useful here because reading the file is a relatively
slow process that you want done only once. If OBJS is defined with a standard macro
definition, each occurrence of $(OBJS) causes omake to read project.lst. By using :=,
project.lst is read only once, when OBJS is defined.
OBJSLIST = project.lst
OBJS := $(OBJSLIST,@)
Macros can be defined on the command line, and the value of the command-line macro overrides
a makefile macro or environment definition with the same name. Only standard macro
definitions are allowed on the command line. A command-line macro that contains spaces must
runs omake with BSCFLAGS defined with the value –n and CFLAGS defined with the value
–Zi –Od.
Dynamic Macros
omake defines some special macros whose values are dynamic. These run-time macros return
information about the current target being built. For example, the .TARGET macro is name of
the current target, the .SOURCE macro is the name of the inferred dependency (from an
inference rule) or the first of the explicit dependencies, and the .SOURCES macro is the list of all
dependencies.
project.exe : $(OBJS)
link /out:$(.TARGET) $(OBJS)
main.obj : main.c
$(CC) $(CFLAGS) –c $(.SOURCE)
io.obj : io.c
$(CC) $(CFLAGS) –c $(.SOURCE)
As you can see, the build scripts that update main.obj and io.obj are identical when dynamic
macros are used. Dynamic macros are important for generalizing the build process with
inference rules, as shown in Inference Rules on page 29.
Macro Modifiers
Macros can be used to reduce the amount of repeated text. They are also used at run time to
generalize the build process with inference rules. You often want to start with the value of a
SRCS = $(OBJS,.obj=.c)
This definition uses the from=to macro modifier to replace the from text in the expansion of OBJS
with the to text. The result is that $(SRCS) is main.c io.c. In general, to modify a macro, expand
it with
$(name,modifier[,modifier ...])
Each modifier is applied in succession to the expanded value of name. Separate modifier with
comma.
There is a complete set of macro modifiers for accessing parts of file names. For example, with
this macro definition:
Tokenize
The Wstr modifier replaces white space between elements of the macro with str, a string. The str
can be a mix of regular characters and special sequences, the most important sequence being \n,
which represents a newline character (like pressing the <ENTER> key). For example:
Environment Variables
Environment variables are placed into the environment with this command:
set name=value
NOTE: This example applies to cmd.exe; the command varies depending on the shell you use.
Expanding a macro also expands any macro references recursively. For example:
In a macro reference $(name), name can reference other macros. For example, given the definitions
SYS = NT
NTFLAGS = –DNT –UNT
Macros in build scripts are expanded immediately before the build scripts are executed. There
are several macros whose values change dynamically at run time. They are discussed in
Predefined Macros: Run-Time Macros on page 60.
NOTE:NMAKE supports recursive macro definitions as shown in this section. When omake is
emulating NMAKE, recursive macro definitions are supported.
A macro value may reference other macros. If the value circularly references itself, omake
displays a warning message when the macro is expanded. For example, the values
A = A $B
B = B1 $A B2
%echo $A
You can make this kind of recursive reference by using the expanded macro definition:
B := B1 $A B2
This type of definition expands any references in the right side before the macro definition of B
occurs.
Inference rules also provide build scripts to update the target from the inferred dependency. The
target inherits these build scripts if it does not have its own.
omake predefines several inference rules, and you can change their definitions or define your
own rules.
Inference rules (also called metarules) are identified by the use of the rule character (%) in the
dependency line. This character is a wildcard, matching zero or more characters. For example,
here is an inference rule for building .obj files from .c files:
%.obj : %.c
$(CC) $(CFLAGS) –c $(.SOURCE)
This rule states that a .obj file can be built from a corresponding .c file with the build-script line
$(CC) $(CFLAGS) –c $(.SOURCE). The .c and .obj files share the same root of the file name.
When the dependency and target have the same file name except for their extensions, this rule
can be specified in an alternative way:
.c.obj :
$(CC) $(CFLAGS) –c $(.SOURCE)
omake predefines the %.obj : %.c inference rule as listed above so the example now becomes
much simpler:
project.exe : $(OBJS)
link /out:$(.TARGET) $(OBJS)
[ Tp ] % [ Ts ] [ attribute ... ] : [ Sp ] % [ Ss ]
build script
.
.
.
On the target side of the dependency line is a pattern: a target prefix Tp, a %, and a target suffix
Ts. Any target attributes (see Target Attributes on page 101) appear next. On the dependency side
of the line is a dependency prefix Sp, a %, and a dependency suffix Ss. The prefixes can contain
any character except % and, in particular, can be a directory. The suffixes can contain any
character (including %, which is taken literally).
In order for a rule to match a target, Tp and Ts must match the first and last parts of the target
name, with % matching everything in between. The inferred dependency name is Sp followed
by the characters matched by %, followed by Ss.
Following the dependency line are the build-script lines that update the target from the inferred
dependency. If a target doesn't have its own build scripts, it inherits the build scripts and
attributes of the inference rule. Target attributes take precedence over rule attributes.
.source_extension.target_extension :
build script
.
.
.
The source_extension is the extension of the dependency. The target_extension is the extension of
the target. This alternative form is compatible with other make utilities and is discussed in
Compatibility with Suffix Rules (.SUFFIXES) on page 37. The suffix-only form is converted by
omake to the equivalent metarule form:
omake uses inference rules when building a target that has no build scripts. Even when targets
have build scripts, you can cause omake to use inference rules by giving the target the .INFER
target attribute.
In either case, omake first builds the target's explicit dependencies (those listed on dependency
lines), and then uses its inference rules to search for an inferred dependency. The search proceeds
by finding all rules that match the target, building each possible inferred dependency name in
turn, and checking whether the inferred dependency exists as a file. If it exists, omake proceeds
as follows:
1. If the target has no build scripts, the target inherits the inference-rule build scripts and
attributes. When this is a conflict between the attributes, the target's attributes take
precedence.
Inference rules can build several targets (a target group) from a single dependency. To do this put
the targets on the target side of the rule, with a plus sign (+) between them. (There must be white
space between the + and the target names.) When omake executes the rule's build scripts to
update any target in the group, all targets are updated.
For example, here is a rule for building both .c and .h files with a yacc program, which takes a .y
file as input:
Note the use of $(.TARGET,num), which evaluates to the names of both the .h and .c files. The
num macro modifier selects the numth element of the macro. So, for example, $(.TARGET,1) is
parse.h when the inferred dependency is parse.y.
When omake tries to find the inferred dependency of a target, it first tries all rules that directly
produce the target. If the inferred dependency cannot be found with one rule, omake chains rules
into twos, threes, and so on. omake always chooses the smallest number of rules (the shortest
path) between a target and its inferred dependency.
If a multiple-rule path is found, omake creates the targets between the inferred dependency and
the target, and chains them. Chained targets have special properties:
➤ omake deletes chained targets as part of the build; as soon as it finishes running the build
scripts, it deletes any intermediate chained targets. A chained target is not considered a
sibling derived object.
➤ For the purposes of time stamp comparisons, a chained target is the same age as the target
that depends on it. This allows omake to compare the time stamp of the target at one end of
the chain with the time stamp of the inferred dependency at the other end and correctly
determine whether the target needs updating.
NOTE:Although the characters matched by % are the same within a single inference rule, the %
can match different characters for the different rules of a multiple-rule path.
To illustrate how the deletion of chained targets works, here are rules for extracting a .obj file
from a .c file and for compiling the .obj file into a .exe file:
%.obj : %.c
$(CC) $(CFLAGS) -c $(.SOURCE)
Assume that omake is trying to build main.exe and that main.c exists, but main.obj does not.
omake finds the two-rule inference that uses the %.obj : %.c rule to produce main.obj, and the
%.exe : %.obj rule to produce main.exe. omake retrieves main.c and compiles it to produce
main.obj. It then links main.obj to produce main.exe. After running the %.exe and %.obj
build-script lines, omake deletes main.obj because it was marked as being chained.
To prevent this deletion, write a rule that combines the rules in the multiple-rule path but that
has a shorter path. A one-step rule between main.exe and main.c that leaves behind main.obj is
%.exe : %.c
$(CC) $(CFLAGS) -c $(.SOURCE)
$(LINK) /out:$(.TARGET) $(LINKFLAGS) $(.SOURCE)
A second way to prevent this deletion is to use the .PRECIOUS attribute. omake does not delete
targets with this attribute. Modify the %.obj : %.c rule as follows:
A target with the .NOCHAIN attribute instructs omake to try only the one-step paths for finding
the inferred dependency.
A rule with the .NOCHAIN attribute cannot be used in the middle of a multiple-step rule. That
is, it means this rule is terminal.
To determine which inference rules to use, omake gathers all rules that can build the current
target and sorts them from best score to worst score. For each rule in this sorted list, omake
constructs the dependency name and tests whether it exists as a file. If so, omake chooses this
rule as the inference rule, and this file as the inferred dependency.
The score is defined as the number of characters in the target name that % matches; the best score
is zero. Often, many rules may have the same score (for example, all rules that build %.obj
targets), and omake puts these rules in creation order. For identical scoring rules, the rule created
first (usually built in to omake or in make.ini) is first on the list.
Sometimes the rule ordering is inappropriate. For example, you may have both video.c and
video.cpp that can be used to build video.obj, and you want omake to use video.c. By making
video.obj depend on video.c, omake chooses the %.obj : %.c rule to update video.obj:
video.obj : video.c
If you find yourself doing this, you can prevent omake from doing the inference rule search by
supplying your own build scripts. For example:
video.obj : video.c
$(CC) $(CFLAGS) –c $(.SOURCE)
One problem with supplying the build scripts explicitly is that they must change if the
%.obj : %.c rule changes. To avoid this problem, use the %do directive to execute the build
scripts of the %.obj : %.c rule:
video.obj : video.c
%do "%.obj : %.c"
When the target name has a directory component (for example, objs\video.obj), omake uses the
following methods to find a rule:
1. The rules with directory components in their targets are matched against the complete target
name.
2. If no rules match in Step #1, the rules without directory components in their targets are
matched against the file name of the target, by default. The .UNIXPATHS directive changes
this behavior. When you use .UNIXPATHS, the rules without directory components are
matched against the full target name.
Inference rules can be redefined any number of times. To redefine an inference rule, provide
a new definition in one of two places:
To change an inference rule's attributes, use a dependency line with the new attributes and
don't specify a build script. These attributes are combined with the current attributes.
To disable an inference rule, use a dependency line with no attributes and no build script:
%.obj : %.c
...or...
.c.obj :
omake searches for an inferred dependency for targets that have no build script. You can
omit the inference search with the .NOINFER attribute. For example:
The all target only drives the build of its dependencies, so no inference search is needed.
➤ Using % in nonrules
A % on the target side of a dependency line indicates that this line is an inference rule. To use
a literal % without indicating a rule, give the target the .NORULE attribute:
The .RULE_CHAR directive sets the rule character. For example, to change it to an asterisk:
.RULE_CHAR : *
omake predefines several rules. You can reject them by using the –r (reject rules) command-line
option or the .REJECT_RULES directive. The built-in rules are listed in Inference Rules on
page 142.
Many make utilities, such as PM/CB, NMAKE, and Borland Make, have a simple style of
inference rule, called suffix rules. These rules use only the suffix (extension) of the file name. Here
is a suffix rule:
.c.obj :
$(CC) $(CFLAGS) –c $<
Some make utilities also use a .SUFFIXES directive to control the search order of the suffix rules.
The .SUFFIXES directive lists the suffixes in the order that inference rules are to be attempted.
Each appearance of .SUFFIXES prepends to the current list of suffixes, but a .SUFFIXES directive
with nothing on the dependency side clears the list:
.SUFFIXES : (clears list)
.SUFFIXES : .lib (list is: .for .lib)
.SUFFIXES : .exe .obj (list is: .exe .obj .lib)
When looking for an inference rule to build a target, the list is traversed from left to right with
each extension being combined with the target extension to form the name of a suffix rule. If that
suffix rule exists, omake forms the name of the corresponding inferred dependency and, if it
exists, the inference search is complete.
omake converts suffix rules into equivalent omake inference rules. If .SUFFIXES is used, omake
uses the suffixes order to sequence only its suffix rules. Nonsuffix rules are left in creation order.
By default, all inference rules are in creation order. Note that a .SUFFIXES directive with no
suffixes on the dependency side effectively disables all suffix rules, but nonsuffix rules remain
enabled.
Response files can also be coded inline in your makefile. For example:
project.dll:$(OBJS)
link @<<
$(OBJS)
/out:$(.TARGET)
$(.TARGET)
<<
The link program is invoked as link @response_file, where response_file is a name generated by
omake. The response_file contains:
2.10 Directives
Makefile directives control the makefile lines omake reads at read time. The following makefile
uses conditional directives (%if, %elif, %else, and %endif) to support both Borland and
Microsoft compilers. Comments have been added for documentation.
CFG = Release
OBJS = main.obj io.obj
# Configuration-dependent section
%if $(CFG) == Release
CFLAGS = /O1
LINK_FLAGS =
%elif $(CFG) == Debug
CFLAGS = /Od /Zi
LINK_FLAGS = /debug
%else
%abort Unsupported configuration $(CFG)
%endif
%.obj: %.c
cl $(CFLAGS) /c $(.SOURCE)
The layout of this makefile is fairly traditional; macros are defined first, and the primary target
follows the macros.
This example also uses the %abort directive to abort omake if the makefile does not support a
particular compiler. Directives can also be used at run time, to control the build scripts omake
executes. For more information, see Makefile Directives on page 74.
In the keep-working mode, a build script error while omake is updating a target causes omake
to stop working on the current target. The make process continues, with omake noting that the
current target was incompletely built. Future targets are updated only if they do not depend on
any incomplete targets.
Because omake does as much work as possible, you only have to fix the problem targets and start
omake again. The keep-working mode does the maximum amount of safe and correct work.
This mode is enabled with the .KEEPWORKING makefile directive (see Dot Directives on
page 91) or –k command-line option (see Command-Line Options on page 41).
3
This chapter contains reference information for omake.
omake –n –d –f project.mak –p
omake –ndpf project.mak
omake –f ../makefile -- –readme–
The first and second example are identical and show how options can be grouped. The third
example shows the use of the double dash to indicate the end of options. This is required to
prevent omake from interpreting –readme– as more options.
Before parsing the command line, omake looks for the OMAKEOPTS environment variable and, if
it is found, parses its value. After reading the initialization file, omake also parses the value of
the MFLAGS macro for additional command-line parameters. MFLAGS can be defined on the
3 - omake Reference 41
command line, in make.ini or in the environment (but an MFLAGS definition in the makefile is
ineffective). Using the –z command-line option causes omake to ignore MFLAGS. Setting
MFLAGS in make.ini is strongly discouraged, because directives can be used instead. After the
OMAKEOPTS environment variable is parsed, the command line itself is parsed.
The options in Table 2 are parameters for omake’s native mode. Many parameters are different
for NMAKE and PolyMake emulation modes.
Option Meaning
–a Updates all targets whether or not they are out of date. If no targets are specified
on the command line, the default target is updated.
–A Uses automatic dependencies. This option is enabled only if you are not using
configuration lookup (because you are processing non-MVFS files or using the
–W option).
–b file Names file as the initialization (built-ins) file (The default is make.ini.) If file is
the empty string, no initialization file is read. You can specify this on the
command line with "–b<SPACE>", –b"<SPACE>" or –b<SPACE>"".
The value of the BUILTINS macro is set to the full pathname of file.
–D Keep-directory mode. The first access of the current directory or any search
directory to look for a file reads the directory into memory. Subsequent accesses
to the directory use the in-memory version and are much quicker.
–EN Sets omake's emulation mode to NMAKE. Selecting this emulation causes the
rest of the command line to be interpreted as an NMAKE command line. See
Microsoft NMAKE Compatibility on page 158 for more information.
Option Meaning
–EP Sets omake's emulation mode to PM/CB. Selecting this mode causes the rest of
the command line to be interpreted as a PM/CB command line. See PM/CB
(Intersolv Configuration Builder and PolyMake) on page 145 for more information.
–E2 Sets omake's emulation to Opus Make v5.2x. See Opus Make v5.2x Compatibility
and Emulation on page 162 for more information.
–f file Specifies file as the makefile. More than one –f option may appear, and the files
are read in order. omake first tries to read file, but if file does not exist, omake
tries file.mak. If file is con or – the console is read for the makefile and
<CTRL+Z>,<ENTER> (<CTRL+D> for UNIX) as the last input finishes the input.
If no –f options are specified, omake tries makefile and then makefile.mak.
The value of the MAKEFILE macro is the file of the first –f option.
–i Ignores exit status, which causes the nonzero exit status from any build scripts
to be ignored. This option can be used to collect all errors into a single file
without stopping omake. See also the –k option.
Many compilers send their error messages to standard error. This
command-line option redirects standard error either into a file or to the
standard output. With it, the command
omake –i –x – > errs
collects all messages into the errs file. See the –x command-line option.
3 - omake Reference 43
Table 2 omake Command-Line Options (Part 3 of 4)
Option Meaning
–k Keep-working mode. Any errors when updating a target cause work on that
target to be stopped, but the make process continues. Because the target was
incompletely made, any other targets that depend on it are prevented from
being updated.
This mode is handy for long, unattended builds because it maximizes the
amount of making without completely ignoring the exit status as the –i
command-option does.
–L Disables configuration lookup and config record creation. See also clearmake
–F.
–M Makes makefile. omake makes the makefile before reading it. See the section
Makefile Directives on page 74.
–n No execute. Displays, but does not execute, the build scripts that update the
targets. This option is useful for debugging makefiles and for showing the work
that will be done. To override this option for a recursive make, use the .MAKE
target attribute (see Target Attributes on page 101) or & shell-line prefix (see
Build-Script Line Prefixes on page 69).
–p Prints debugging information to screen. Macros are listed with their location of
definition and value; search directories are indicated; inference rules are
displayed and targets, build scripts and attributes are printed. The
interpretation of the output is discussed in Chapter 4, Debugging Makefiles.
–r Rejects inference rules. omake ignores inference rules that are built in and that
are defined in the initialization file. Only inference rules defined in the makefile
are used.
–s Silent mode. Build scripts are usually displayed before they are executed. The
–s option prevents this display.
Option Meaning
–v Increases output verbosity during the build process (particularly with respect to
configuration lookup and config record creation).
–x file Redirects error messages into file. As a special case, if file is –, the error messages
are redirected to the standard output. For example:
omake –x make.err (errors go into make.err)
omake –x – >> make.err (errors are appended to make.err)
–z Ignores MFLAGS. The MFLAGS macro is not examined for additional options.
–#8 Debugging option—leaves behind generated response files and batch files.
omake uses several temporary files, which are usually deleted before omake
quits. This option causes omake to leave them behind so they can be examined.
Debugging features can be specified as a sum or as a comma-separated list. For example, both
–# 7 and –# 1,2,4 display makefile lines, warn about undefined macros, and warn about
unrecognized makefile lines). See also the description of the .DEBUG directive in the section Dot
Directives on page 91.
3 - omake Reference 45
The Current Options
After reading its initialization file, omake exports all command-line options except –b and –f into
the MFLAGS macro (unless you are using omake in an emulation mode). Also, the state of each
command-line option is kept in the macros listed in the section Predefined Macros: State Macros on
page 63 and in Appendix C, Built-In Macros and Rules.
When the initialization file is found, omake searches its directory for its ancillary files (omhelp.*
and builtins.*).
omake does not look for the initialization file if you use the command-line option –b"<SPACE>"
or if you set the OMAKECFG environment variable to the empty string. To set the environment
variable:
set OMAKECFG=<SPACE><ENTER>
Read Time
At read time, omake parses the command line, reads the initialization file, and reads one or more
makefiles. Steps in the start-up process:
4. If the MFLAGS macro is defined and the –z command-line option was not specified, the
macro is expanded and parsed as a command line.
omake reads the initialization file and makefiles, collecting macro definitions, dependency lines,
rules, and build scripts. Dependency lines are built into a set of dependency trees, with each
target node connected by a dependency arc to each of its dependency nodes. Because each
dependency is itself a target, it is connected to its own dependencies. At the leaf nodes of the trees
are targets without any dependencies.
Run Time
At run time, omake makes the command-line targets or, if none are specified, the first normal
target in the first makefile. In this context, “normal” means not a directive, special target,
attribute, or inference rule. This first normal target is called the default target. Briefly, these are
the steps involved in making a target:
Look for the target as a file on disk and, if found, record its location.
3 - omake Reference 47
Make the target's explicit dependencies.
If the target has no build scripts, use inference rules to look for an inferred dependency. If the
inferred dependency is found, add it as a dependency of the target and add the rule's build
scripts to the target. Then, make the inferred dependency.
If the target was found in Step #1, omake assumes its location stays the same. If the target was
not found, omake makes a second attempt to locate it on disk. In either case, omake also updates
its internal copy of the target's time stamp.
The consequence of Step #2 and Step #3 is that omake makes a target's dependencies recursively.
omake goes as far as it can down the dependency tree and works back up, using configuration
record matching and build avoidance, as described in Step #4. If the target is not in a VOB, omake
checks the time stamp of the target against its dependencies. For targets that have at least one
newer dependency, the target's build scripts are executed to update the target.
The utility of Step #3 is that it generalizes the make process. Inference rules are akin to statements
such as “all .obj files can depend on like-named .c or .cpp files.”
An extensive example that shows the read-time steps in the make process is in Chapter 4,
Debugging Makefiles.
Before making any targets, omake executes the build scripts of the .BEFORE special target if it is
defined.
Immediately before exiting, omake executes the build scripts of the .AFTER special target if it is
defined. omake then removes any temporary files it has created and exits.
If the target is not in a VOB, omake updates its internal copy of a target's time stamp after the
target has been made. The value the time stamp is set to is determined as follows:
➤ If the target has build scripts, the time stamp is set to the current system time after all build
scripts have been executed.
➤ If the target has no dependencies, the time stamp is set to the current system time.
➤ Otherwise, the time stamp is set to the most recent of the target's current time stamp and
those of all its dependencies.
3.4 Targets
This section provides general information about targets.
By default, for Windows NT omake target names are case-insensitive. The .CASE_TARGET and
.NOCASE_TARGET directives turn case-sensitivity on and off.
It is an important fact that a target has both a name (from the makefile) and a pathname (its location
on disk). Each name in the makefile specifies a unique target. The pathname is determined when
omake searches for the target on disk.
If name does not have a path component in it, omake may search multiple directories to locate
the target and the name and pathname may differ. If name has a path component, or if omake is
not instructed to search multiple directories, the name and pathname are the same. See Search
Directories on page 106.
3 - omake Reference 49
Using the Path Separator in Names
On Windows NT, you can use either a slash ( / ) or backslash ( \ ) as the path separator inside of
omake makefiles. Windows NT accepts either character as the path separator when Make looks
in the file system directory.
We suggest you use the slash in your makefiles because the backslash can be used to modify the
meaning of the character that follows it. For example, \<ENTER> continues makefile lines and \#
is a literal #. If you use the backslash as the path separator, you must be aware of how omake
interprets this expression:
\the-following-character
If no targets are specified on the omake command line, the first normal target in the makefile is
made. In this context, a normal target is not a directive, special target, attribute, or inference rule.
It is a common practice to have the default target depend on other targets to be built. Consider
this makefile:
a.exe : dependencies
build scripts
b.exe : dependencies
build scripts
Running omake without a command-line target causes all (a.exe and b.exe) to be made. The
target all is sometimes called a dummy target because it is used to drive the build of other (real)
targets.
A target may appear on the target side of more than one dependency line. The target depends on
all dependencies on all dependency lines that the target appears on, but the build script that
updates the target can be listed after only one of the dependency lines.
When a double-colon (::) separates the target and its dependencies, build scripts can be specified
after each double-colon dependency line. If in the MVFS, all build scripts are executed if any
dependency on any dependency line is newer than the target. Double-colon dependencies are
rarely used. Here is a simple example:
backup :: a.exe
copy $(.SOURCE) c:\backup
backup :: b.exe
copy $(.SOURCE) c:\backup
If you were to execute the omake backup command, a.exe is built and then b.exe . Each target is
copied to c:\backup after it is built.
A target cannot appear on the target side of both double- and single-colon dependency lines. If
it does, omake displays a warning and ignores the offending dependency line.
A target that has no dependencies (neither explicit nor inferred) is up to date if it exists as a file;
if it doesn't exist, it is out of date and must be updated.
Target Groups
Several targets may be made simultaneously from a single dependency. This is called a target
group. Updating any target of the group (by running the target's build scripts) updates all the
targets.
To indicate a target group, put a plus sign (+) between each target on the dependency line. For
example, here is a rule to build parse.h and parse.c simultaneously from parse.y using the
program called yacc:
3 - omake Reference 51
parse.h + parse.c : parse.y
yacc –d parse.y # produce ytab.h & ytab.c
copy ytab.h parse.h # copy ytab.h to parse.h
copy ytab.c parse.c # copy ytab.c to parse.c
del ytab.* # remove the ytab files
Assume that parse.y was changed recently and that some other target depended on parse.h.
Making this other target causes parse.h to be made, which executes the build scripts. If parse.c
is evaluated later in the make process, omake recognizes that it is a member of the same target
group as parse.h, which has already been updated, and does not rerun the build scripts.
3.5 Macros
A macro definition associates a name and a value. The macro expansion of a macro name returns
the value. Macros are used at read time to organize names of files, compiler options, and so on.
At run time, macros provide information about the current target being built.
Macro Modifiers
When a macro is referenced, the expanded value can be modified through the use of macro
modifiers. To modify a macro, expand it with:
$(name,modifier[,modifier ...])
Everything between $( and ) is expanded, the value of name is expanded, and then each modifier
is applied in succession to the expanded value. The separator between name and modifier can be
a comma or colon, but subsequent modifiers must follow a comma. A literal comma is available
by using \,. Some modifiers use regular expressions. The treatment of the backslash, can make it
awkward to use a modifier when a backslash also terminates its argument. You can work around
this by using two backslashes before a comma separator(\\,) or
if possible, move the awkward modifier to the end. If this not possible, use two modifications.
For example,
OBJS = $(SRCS,<obj\,R,>.obj)
OBJS = $(SRCS,<obj\)
OBJS := $(OBJS,R,>.obj)
Filename Components
B The base name part of the element. This is the file name without an extension.
$(SRCS,B) is main sub io
D The directory part of the element. For X:\file, X:file, \file, or dir\file, the directory part is
X:\, X:, \, or dir, respectively. If there are no directory separators the directory part is
the current directory ( . ).
$(SRCS,D) is \src \sys .
F The file name part of the element. The part after the last directory separator.
$(SRCS,F) is main.c sub.cpp io.cpp
P The path part of the element. This is similar to the D modifier, but includes the last
directory separator. So for X:\file, X:file, \file, dir\file, or file the path part is X:\, X:, \,
dir\ or “”, respectively.
$(SRCS,P) is \src \sys
R The root part of the element. The same as its full name minus its extension.
$(SRCS,R) is \src\main \sys\sub io
Z The drive letter part of the element (or the current drive), terminated by a colon
$(SRCS,Z) is V: V: V: (if “V” is the current drive)
Absolute Pathname
A[sep] Convert the element to an absolute pathname. If the element is not already an
absolute path, this modifier prepends the current drive and working directory.
Then, the sep separator replaces the slash and backslash. Finally, .. and . directory
parts are removed. For example, if the current working directory is v:\stage,
then:
3 - omake Reference 53
$(SRCS,A) is v:\src\main.c v:\sys\sub.cpp v:\stage\io.cpp
Change Case
LC Lowercase. Change the letters of the element to lowercase.
$(SRCS,Z,LC) is d: c: c:
Expand Pathnames
X This modifier expands elements into their pathnames. As an example:
.PATH.obj = objs
OBJS = 1.obj 2.obj
project.exe : $(OBJS)
link $(.TARGET), $(OBJS,X);
The .PATH.obj macro defines a search directory where .obj files are located. The X
modifier causes omake to search for each element in its search directories. Assuming
1.obj and 2.obj are in the objs directory:
$(OBJS) is 1.obj 2.obj
$(OBJS,X) is objs\1.obj objs\2.obj
Include File
@ If the macro's value names a file, the value of the macro modification is the contents of
the file with spaces, tabs, and newlines collapsed to single spaces.
This modifier is best used with the := expanded macro definition so the file or project is
read only once, when the macro definition occurs. For example:
FILE = link.rsp (response file)
OBJS := $(FILE,@) (read contents of link.rsp)
Nregex The nonmember selector. It selects elements that do not match regex.
$(SRCS,N\.c) is io.cpp
N"spec" The nonmember selector, where spec is a Windows NT file specification, not a
regular expression:
$(SRCS,N"\src\main.c") is \sys\sub.cpp io.cpp
$(SRCS,F,N"*.c") is \sys\sub.cpp io.cpp
3 - omake Reference 55
Select a Particular Element
number Selects the numberth element of this macro value. If the macro value doesn't
have this numberth element, the modified value is the empty string. This
modifier is particularly useful for inference rules that build multiple targets
from a single dependency.
$(SRCS,2) is \sub.cpp
String Substitution
Sd regex d subst d
The substitution modifier. The d is a single-character delimiter that is neither in regular
expression regex nor in substitution string subst and isn't a comma. If regex matches some
part of a macro element, the matched part of the element is replaced with subst. The
element is not changed if regex does not match it.
If regex is omitted, the last regular expression is reused. This is useful in combination
with the member modifier, M. For example, given that CFLAGS has the value
–AX –Ifoo –Ibar –DX=–IT:
The M modifier selects elements that start with –I, and the S operator substitutes the –I
with nothing. This is quite different from
Notice how the elements unmatched by regex ^–I are not changed.
from=to
This modifier replaces occurrences of from string with to string. If from does not appear
in a macro element, the element is not changed.
from and to can be simple strings or can use the percent sign (%) as a wildcard. If % is
used, the search for from is anchored to the end of the element.
The use of % anchors the search for %.c so it matches main.c but not sub.cpp. The simple
string substitution .c=.obj replaces any occurrence of .c with .obj so matches and
changes sub.cpp to sub.objpp.
For historical reasons, when fromString and toString are simple strings, this modifier
operates on the entire macro value rather than on its elements, and can be used to replace
the white space between elements. However, the W modifier is better suited for this task.
Tokenize
Wstr
This modifier replaces the white space that separates macro elements with str, where
str is treated literally except for the following special sequences:
\n A newline character
\r A return character
\t A tab character
\\ A backslash
\ddd An octal character ddd (1 to 3 digits)
\xdd A hexadecimal character dd (1 or 2 digits)
This example can be used to prepare an inline response file with the OBJS definition
of the X modifier listed above:
$(OBJS,X,W+\n) is objs\1.obj+
objs\2.obj
project.exe;
3 - omake Reference 57
Regular Expressions
The M, N, and S modifiers use pattern-matching strings known as regular expressions. The
regular expression (or regex) matches characters in strings, both literally and with wildcards, and
the match is case-sensitive.
Two directives control the special characters that appear in regular expressions:
➤ .REGEX_CHAR sets the character used to indicate special character sequences. The default
character is a backslash (\).
➤ .REGEX_WILD sets the wildcard character that matches any single character. The default
character is a period ( . ).
The backslash and period are standard characters in UNIX-styled regular expressions, but are
awkward to use in Windows NT because the backslash is the directory separator and the period
is the file extension separator. The .REGEX_CHAR and .REGEX_WILD directives can be used
to change these characters to some other characters.
The default characters are most problematic for the M and N modifiers when you are trying to
match a file name. For this case, use the M"spec" and N"spec" modifiers because the spec is a file
specification rather than a regular expression.
To select files that end in .c, the search can be anchored to the end with the regex character $. To
get $ to the regular expression, you need to use $$ in the makefile:
$(SRCS,M\.c$$) is main.c
Analogous to the $ anchor, the ^ regex character anchors the search to the front of the macro
element:
The [set] regex characters indicate a set of characters, where the set can be single characters ([aA@]
matches a, A or @), a range of characters ([a-z] matches a through z), or a mixture. For example:
One powerful feature of regular expressions is that when used in substitutions, they can access
the matched parts of the string. The down side of the more powerful regular expressions is that
the expressions can be hard to read. For example, when DIR = NT_L, the expression
$(DIR,S/\(.*\)_.*/\1/) is NT.
The \(, \) pair surround a part of the regular expression that is referenced later. Inside the pair
is .*, which matches any character (.) repeated zero or more times (*). Taken together they instruct
omake to match any character, zero or more times, and attach a tag to it. The rest of the regular
expression is _ , which matches _, and .*, which matches any character repeated zero or more
times.
The expression \1 is the stuff matched in the first pair of \( \), so the substitution evaluates to
NT. Simple regular expressions are easy to read, but if you write more complicated expressions,
be sure to provide thorough comments.
If omake is configured for alternative regular expression characters, the following directives
appear in your make.ini:
.REGEX_CHAR : ~
.REGEX_WILD : ?
3 - omake Reference 59
$(SRCS,M.c) is main.c sub.cpp
$(SRCS,M.c$$) is main.c
$(CFLAGS,M–I) is –Ifoo –Ibar –DX=–IT
$(CFLAGS,M^–I) is –Ifoo –Ibar
$(CFLAGS,M^[–/]I) is –Ifoo –Ibar /Ibaz
$(DIR,S/~(?*~)_?*/~1/) is NT
omake defines several macros before it reads the initialization file and makefiles. These macros
come in two general types:
➤ Built-in macros have the same precedence as normal makefile macros, and so can be
redefined in your makefiles or on the command line.
The run-time macros are changed dynamically by omake according to the current target being
built. A key feature of the run-time macros is that their values are pathnames. A target's pathname
is the location the target was found on disk. The run-time macros evaluate to pathnames, which
is important for use on build scripts where the executed command needs the location of the
targets.
All run-time macros have names of the form .name, and several have one- or two-letter aliases
that you are likely to see in makefiles of other make utilities.
Run-Time Macros
.NEWSOURCES (alias is ?)
This run-time macro evaluates to the pathnames of all dependencies newer than the
current target. When configuration lookup is enabled, it evaluates to the pathnames of
all dependencies for the current target, unless that behavior is modified with the
.INCREMENTAL_TARGET directive (see the description in the section Dot Directives
%.obj : %.c
cl –c $(.SOURCE)
cl –c $<
NOTE: The ** macro is the exception to the rule that multicharacter macros need
parentheses or braces around them. The expression $** is the same as $(**).
.TARGET (alias is @)
This run-time macro evaluates to the pathname of the target currently being made. For
example:
%.obj : %.c
cl –o$(.TARGET) –c $(.SOURCE)
cl –o$@ –c $<
This macro can also be used at read time on a dependency line and its value is the name
of the target currently getting dependencies. For example:
3 - omake Reference 61
main.obj io.obj : $(.TARGET,R).c io.h
The .TARGET macro value is set to the name of each target, in turn. The dependencies
are then macro-expanded and added to the target's list of dependencies. The R macro
modifier selects the root of the target name. The above dependency line is equivalent to
the two lines:
For compatibility with other Make utilities. omake treats $$@ on the dependency side of
a dependency line just like $(.TARGET).
.TARGETROOT (alias is *)
This run-time macro evaluates to the pathname of the target currently being made, minus
its extension. This macro can also be used at read time on the dependency side of a
dependency line. Here is the read-time example from the .TARGET macro rewritten
using this macro:
The predefined macros in Table 3 give you information about the current make process. One of
the most important predefined macros is the status macro at the bottom of the table.
$ When you need a literal dollar sign, you must use $$.
FIRSTTARGET The first command-line target or, if one isn't given, the default
makefile target.
INPUTFILE The name of the current makefile. omake can read multiple
makefiles, either with multiple –f command-line options or
with %include directives. The INPUTFILE macro's value is the
current makefile being read.
MAKEARGS The command line with which omake was started, including
command-line options, macros, and targets.
MAKEMACROS The command-line macros with which omake was started. Any
macros that have spaces are enclosed in double quotes so they
can be used on a command line again.
MAKESTATUS The exit status of omake. This can be used in the .AFTER
special target to determine whether omake is exiting with an
error.
MAKEVERSION The version number for omake. Its format is X.Y, where X and
Y are the major and minor release numbers.
OPUS Defined to the value 1. This can be used to test if you are
running omake or some other Make.
status The exit status of the last build script. It is used with conditional
directives to execute other build scripts. For historical reasons,
the name is lowercase.
The state macros provide information about the state of command-line options and read-time
directives. Most command-line options have an equivalent directive, and the value of the state
macro is the same regardless of whether the option or directive was used.
3 - omake Reference 63
In the list of macros in Table 4, the macro values that are the state of a directive or command-line
option mean the value is 1 if the directive or command-line option was used; otherwise the value
is 0.
NOTE: In terms of implementation, .ALWAYS, .IGNORE, and .SILENT are not directives; they
are target attributes. They look like directives when they appear in a makefile on the target side
of a dependency line when there are no dependencies. For example,
.IGNORE :
sets the .IGNORE attribute for every target created after the appearance of this line. The
.ALWAYS, .IGNORE, and .SILENT macros have the correct value, as if these attributes were
directives.
.OPUS_52X The list of Opus Make v5.2x compatibility features, as set by the –E2
command-line option.
.omake The state of the .omake directive and –EO command-line option.
.REGEX_BACK The regular expression literal backslash (\). This is provided for
writing regular expressions that are independent of the value of
.REGEX_CHAR. If .REGEX_CHAR is \,its value is \\; otherwise,
its value is \.
3 - omake Reference 65
Table 4 State Macros (Part 3 of 3)
.SHELL The command to execute the shell program as set by the .SHELL
directive.
Here is an example of how these macros can be used. Suppose you want to debug the contents
of your makefile with the –#1 command-line option. However, this also produces output that
comes from your make.ini file, which probably doesn't need debugging. Modify your make.ini
file with the following:
_OLD_DEBUG := $(.DEBUG) (get current state)
.NODEBUG : 1 (turn off “-#1” if set)
[Original make.ini goes here]
.DEBUG : $(_OLD_DEBUG) (restore state)
Built-in Macros
omake defines the built-in macros with a default value, but they have the same precedence as
normal makefile macros, so you can be redefine them.
CC Used in the %.obj : %.c rule, the name of the C compiler. The default
value is cl, the name of the Microsoft C Compiler.
FC Used in the %.obj : %.for rule, the name of the FORTRAN compiler.
The default value is f77l, the name of the Lahey FORTRAN
Compiler.
LIBEXE Used in the %.lib : %.obj rule, the name of the object librarian. The
default value is lib, the name of the Microsoft Librarian.
LINK Used in the %.exe : %.obj rule, the name of the object linker. The
default value is link, the name of the Microsoft Linker.
MAKE_TMP The name of the directory omake uses for temporary files (response
files under Windows NT).
Initially MAKE_TMP is undefined and omake uses the current
directory for temporary files. If you define MAKE_TMP its value
must be an absolute directory (such as D:\ or D:\tmp, preferably
on a RAM disk. As an example, the environment variable TMP
names the temporary directory some compiler vendors use. You
can put the following in make.ini:
MAKE_TMP = $(TMP)
3 - omake Reference 67
Table 5 Built-in Macros (Part 2 of 2)
MFLAGS After all makefiles have been read, omake defines MFLAGS with
all the command-line options. MFLAGS is useful for invoking
omake recursively, as shown in the definition of the MAKE macro.
NOTE: MFLAGS is a built-in macro only if you are using native
omake mode (that is, if you are not using an emulation mode). In
the emulation modes, it is not predefined by omake; however, you
can redefine it.
A second usage of MFLAGS is to pass initial options to omake. If
MFLAGS is defined in the environment or in make.ini its value
specifies additional command-line options. For example, the
following macro definition placed in make.ini turns on the
keep-directory mode (the –D command-line option):
MFLAGS = –D
Because there are directives for all command-line options, this
second usage of MFLAGS is discouraged, and you should use the
directives.
RC Used in the %.res : %.rc rule, the name of the resource compiler. The
default value is rc, the name of the Microsoft Resource Compiler.
SHELLSUFFIX Suffix used by omake for the batch files it generates. The default
value is .bat.
@
Usually omake echoes (displays) the build-script line to the screen before executing it.
The @ prefix prevents this display except when running omake –n.
ERRS = make.out
$(OBJS) : $(.TARGETROOT).c
%do CCquiet
CCquiet :
@ %echo –n Compiling $(.SOURCE) ...
@ $(CC) $(CFLAGS) –c $(.SOURCE) >>$(ERRS) 2>&1
@ %echo done.
Redirection by >>$(ERRS) 2>&1 means error messages from the compiler go into the
$(ERRS) file. The net effect is that a series of messages of the form:
are displayed and all output from the compiler is redirected into make.out.
See also the .SILENT target attribute to turn on silent mode for this target and the –s
command-line option to enable silent mode for all targets.
@@
The @@ prefix prevents display of the build script before execution, even when running
omake –n.
3 - omake Reference 69
Ignore the Build-Script Line Exit Status
–[num]
Normally a build-script line that returns a nonzero exit status causes omake to terminate
with this message:
The dash (–) prefix causes omake to ignore the exit status returned from the build-script
line and to continue. The message now becomes
If num is given, omake ignores the exit status if it is no greater than num. For example,
the prefix –4 tells omake to ignore an exit status of 1, 2, 3, or 4. There must be at least one
space after num.
Importantly, the status macro is set to the exit status of the build-script line so it can be
tested later. See the -- prefix for an example.
See also the .IGNORE target attribute to turn on ignore mode for this target and the –i
command-line option to turn on ignore mode for all targets.
--[num]
Ignores the exit status and does not display the warning message.
If num is given, omake ignores the exit status if it is less than or equal to num.
For example, the CCquiet target of the previous example can be changed to this:
CCquiet :
@ %echo –n Compiling $(.SOURCE) ...
@– – $(CC) $(CFLAGS) –c $(.SOURCE) >>$(ERRS) 2>&1
%if $(status) != 0
% abort FAILED! See $(ERRS) for errors.
%endif
@ %echo done.
~~[num]
Ignores the exit status, does not display the warning, and retains status.
&
Use & to override the –n command-line option for this build script. This prefix is useful
if you are using omake to call itself recursively.
It is usually better to use the .MAKE target attribute instead because it overrides the –q
and –t command-line options as well as –n.
omake executes all build-script lines with the shell program. This default can be changed with
the .SHELL directive, which selects use of the shell program, and the .NOSHELL directive,
which selects direct execution.
The following prefixes override the general execution mode for the current build script:
: Executes the build script directly.
+ Executes build scripts by the shell program.
!
Iterates the build-script line for each element of $? (i.e. $(.NEWSOURCES)) or $** (that
is, $(.SOURCES)), on the basis of which appears first on the build-script line. The
build-script line is executed once for each element of the original $? ($**) with the value
of $? ($**) taking on successive elements of the original $? ($**).
If neither $? nor $** appears on the build-script line, the build-script line is iterated once
for each element of $**.
3 - omake Reference 71
omake performs iteration explicitly over any number of build scripts with its %foreach
directive, and the use of the ! prefix is discouraged.
Miscellaneous Prefixes
|
The bar (|) prefix can be used to mark the end of the prefixes. This is useful when the
command to be executed starts with one of the prefixes.
>
The right-angle bracket (>) prefix inserts an extra carriage return/linefeed after the build
script is executed. This prefix is supplied for PM/CB compatibility.
For PM/CB compatibility, omake supports named prefixes such as (Silent) and (Ignore).
recursion :
chdir subdir
omake $(MFLAGS)
Similarly, setting environment variables does not work as expected because the environment
variable is set in one shell, the shell exits back to omake, and the next command is executed in a
new shell that doesn't have the variable set. For example, this line
setenv :
set USER=dgk (for UNIX: setenv USER dgk)
echo %USER% (for UNIX: echo $$USER)
NOTE: In NMAKE emulation mode, omake handles internally any commands that start by
setting an environment variable, rather than calling the shell.
The syntax for executing more than one command in the same shell is
The build-script line is enclosed in parentheses, and the commands are separated by a semicolon
(;). (Use \; to specify a literal semicolon). In terms of implementation, omake writes each
command to a batch file and uses the shell program named by the .SHELL directive to execute
the batch file.
recursion :
( chdir subdir & omake $(MFLAGS) )
Simultaneous support of all operating systems is possible with a conditional macro definition
such as this:
%if $(OS) == NT
; = &$; is ”&”
%else
; = ;$; is “;”
%endif
3 - omake Reference 73
Using Directives: %chdir and %setenv
Rather than use a multiple-command build script to work around the change-directory problem,
you can use a directive. The %chdir directory directive causes omake to change to directory, where
it stays until the next %chdir directive or until omake exits. The recursion example becomes
recursion :
%chdir subdir (change to the subdirectory)
omake $(MFLAGS) (do the recursive Make)
%chdir $(MAKEDIR) (change the directory back)
Likewise, to work around the environment-variable problem you can use a directive. The
%setenv name val directive sets environment variable NAME to the value val. Like %chdir,
%setenv has effect until the next %setenv or until omake exits. The setenv example becomes
setenv :
%setenv USER dgk
echo %USER% (for unix: echo $$USER)
For more information and recommendations on using the %setenv directive, see the %setenv
entry in Table 14 on page 90
➤ Percent directives, which use a percent sign (%) as the first non-white-space character on
the makefile line.
➤ Dot directives, which look like dependency lines but use special target names.
Percent Directives
Percent directives (usually called directives) have names of the form %name, where the directive
character is the first non-white-space character on the makefile line. White space is allowed
between % and name.
Conditional Directives
The directives in Table 6 control the flow of the make process at read time and at run time.
Conditional and iteration directives can be nested up to 31 levels deep.
Iteration Directives
The directives in Table 7 provide iteration control. Iteration and conditional directives can be
nested up to 31 levels deep.
3 - omake Reference 75
Other Percent Directives
Other directives behave like commands built into omake. At run time, these directives can be
preceded with build script prefixes, which must appear before the %. See Table 8.
% set name [+]= value Set macro name with value run
Conditional Directives
Conditional directives control the makefile lines that omake reads at read time and control the
build scripts that are executed at run time. These directives take this form:
Each %if must be matched with an %endif. There can be several %elif or %elseif clauses and at
most one %else. Lines between %if or %elif and the next %elif, %else, or %endif are a block. If
condition is true, the makefile lines are read or the build-script lines are executed. If none of the
conditions is true and there is a %else clause, the block between %else and %endif is read or
executed.
If the % of these directives is in the leftmost column of the makefile, the directive is evaluated at
read time; otherwise, the directive is evaluated at run time. There can be white space between %
and the name of the directive. No shell-line prefixes are allowed before the %.
%ifdef name
%ifndef name
%ifdef is true if macro name is defined. %ifndef is true if macro name is not defined.
Directives can be used to conditionally select the continued makefile text. For example:
OBJS = main.obj parse.obj \ (the continuing line)
%ifdef Debugging
version.obj \ (continues here if Debugging defined)
mymalloc.obj
3 - omake Reference 77
%endif
a blank line (continues here if Debugging undefined)
If the Debugging macro is not defined, the OBJS macro value is main.obj parse.obj. If the macro
is defined, the value is main.obj parse.obj version.obj mymalloc.obj.
The way this example is written makes the blank line after the %endif necessary because the
continuing line is continued on the first line after the %endif if Debugging is undefined. Using
an %else clause instead is done like this:
OBJS = main.obj parse.obj \ (the continuing line)
%ifdef Debugging
version.obj \ (continues here if Debugging defined)
mymalloc.obj
%else
(continues here if Debugging undefined)
%endif
Conditional Expressions
The %if, %elif, and %while directives use the same conditional expressions. These expressions
compare strings and numbers and combine the comparisons with logical operations. As well, the
status of macros, command-line targets, and files can be determined. All macro references in the
conditional expression are expanded before the expression is evaluated.
The conditional expressions here are organized by type. Some examples follow each type. For the
examples, the following macros are assumed to be defined:
DEBUG = 0
MODEL = S
NONE =
OBJS = 1.obj 2.obj
Simple Expressions
value
'value'
"value"
Comparison Operators
The operators in Table 9 make a numerical or alphabetical comparison of two values, returning
1 if the comparison is true and 0 if false.
If both values start with a digit, the comparison is done numerically; otherwise, it is done
alphabetically. If either value contains spaces or is null, it must be enclosed in quotes. The
case-sensitivity of the string comparison is the same as for target names and can be set with the
.CASE_TARGET and .NOCASE_TARGET directives.
3 - omake Reference 79
%if $(MODEL) == S true
%if ABC > DEF false
%if $(DEBUG) != 0 false
%if $(XYZ) == 1 error! $(XYZ) is null
%if $(XYZ)x == 1x false
%if $(OBJS)x != x error! $(OBJS) has spaces
%if "$(OBJS)" != "" true
All function operators take one or more arguments and return a value that is false (0), true (1) or
some other number. See Table 10.
File-Test Operators
The file-test operators return the state of files and directories. Most of these operators have been
made obsolete by the equivalent functional operators. See Table 11.
Command-Execution Operator
The command-execution operator executes a command using the shell program. See Table 12.
Here is an example that runs a hypothetical mkproto program that freshens the prototype files
for its source files:
You can ignore the exit status of the executed command by using an %if ... %endif pair that
doesn't encapsulate anything. The following idiom is seen in VC++ makefiles:
3 - omake Reference 81
!if [ if exist MSVC.BND del MSVC.BND ]
!endif
Logical Operators
The logical operators are used to combine other expressions. Each expression is evaluated from
left to right, but parentheses can be used to order the evaluation. See Table 13.
exp1 && exp2 True if both exp1 and exp2 are true.
Unlike the C programming language, the logical expressions do not short-circuit. That is, exp1
and exp2 are always evaluated. For example:
%if %defined(NONE) && %null(NONE) (true)
%if %defined(XYZ) && %null(XYZ) (false)
%if ! ( ! –f file || –z file ) (false if file is absent or is zero length)
Iteration Directives
The %while and %foreach directives provide iteration capability. At run time, they allow build
scripts to be executed multiple times. %foreach can also be used at read time to replicate makefile
lines.
The list_of_names is a set of names separated by white space. The value of macro name is set to the
first name in the list_of_names, and the makefile lines after this %foreach and before %end are
read (at read time) or executed (at run time).
If the % of these directives is in the leftmost column of the makefile, the directive is evaluated at
read time; otherwise, the directive is evaluated at run time. No shell-line prefixes are allowed
before %foreach or %end.
When %end is reached, name is set to the next name in list_of_names, and the loop is restarted.
When there are no more names, the loop is done and name returns to its previous value. For
PM/CB compatibility, the optional keyword in is supported and %endfor can be used in place
of %end.
If %foreach is used at read time, the makefile lines between %foreach and %end are parsed
multiple times with name taking on successive values from the list_of_names. As the lines are
parsed, all macro references to name are expanded.
All $(var) references are replaced with the current value of var. omake treats the previous
%foreach loop as if it has read the following makefile lines:
3 - omake Reference 83
macro_io = $(value_io) $(other_macro)
io.obj : io.c
cl –c $(.SOURCE)
Here is an example run-time use of %foreach to build a linker response file using the inline
response file syntax (see Inline Response Files on page 115):
project.exe : $(OBJS)
link @<< (link @response_file)
%foreach x in $(.SOURCES)
$x (adds each .obj +)
%end
(adds a blank line)
$(.TARGET); (add the executable name)
<< (end the response file)
%while condition
[ build script and directives ]
.
.
.
%end
While condition is true, the build script and directives are executed. When %end is reached the
loop is restarted at the top, condition is reexpanded (because it may contain macros) and retested.
This is repeated until condition is false. No shell-line prefixes are allowed before %while or %end.
When you use omake in a VOB, there is a side effect with the %foreach and %while directives:
the build script in the CR does not expand loop macros. For a makefile like this one,
all:
%foreach platform in i386,alpha
$(MAKE) -f makefile.$(platform)
%endfor
you may expect the configuration record to include the commands that were executed. For
example:
Note also that the platform macro has a value only while inside the loop, so the macro in the
configuration record is expanded to nothing.
%break and %continue interrupt the iteration. %break stops the iteration immediately.
%continue restarts the iteration at the top. For %while, the condition is reexpanded and retested.
For %foreach the name is advanced to the next in the list_of_names.
The ! shell-line prefix iterates the build script for elements of either the .SOURCES (or **) or
.NEWSOURCES (or ?) macro, depending on which appears first on the build script. During
iteration, ${.SOURCES} (or $**) or ${.NEWSOURCES} (or $?) evaluates to each element, in turn,
of the macro value. We discourage the use of ! for iteration, preferring the explicit %foreach
directive.
A Sample Makefile
io.obj : io.c
%while 1 (Loop forever)
––$(CC) $(CFLAGS) –c io.c >io.err (Compile and gather errors)
2>&1
%if $(status) == 0 (Run-time conditional)
%break (Quit if no compiler errors)
%endif
3 - omake Reference 85
notepad –mnext_error io.c (Else edit the file)
%if %time(io.c) < %time(io.err) (Was io.c written?)
%error Compile of $(.SOURCE) failed (No, exit with an error)
%endif
%end
erase io.err (Remove the error file)
This example shows a compile-edit loop. The file io.c is compiled with all compiler messages
redirected into file io.err. The 2>&1 redirection is compatible with Windows NT and UNIX. It
means that standard error is redirected to standard output. The previous > io.err means standard
output is redirected into io.err. Together, they mean that standard error and standard output both
are redirected to io.err.
If the compile is successful, the %break directive breaks out of the %while 1 loop and erase the
io.err file.
Otherwise, notepad (the Notepad editor) is started and told to jump to the first error. After
Notepad finishes, check the time of the io.c file to see whether it is more recent than io.err,
indicating it has been changed. If it hasn't, omake breaks out of the compile-edit loop by calling
the %error directive. Otherwise, the loop restarts and the file is recompiled.
Table 14 lists other percent directives, the times at which they are applicable, and their
descriptions.
Appl.
Directive Description
Time
%abort [ status ] [ message ] read, At read time and run time, terminates omake with the
run user-supplied exit status (1 if status is not supplied). If message is
supplied, omake prints it on the error output (standard error)
before terminating; otherwise, the termination is silent.
When you use %abort while running omake in a VOB, no
configuration records are written. Any output files created by the
build script before it executes %abort will not be derived objects.
Appl.
Directive Description
Time
%chdir directory run Changes the current directory to directory. This is the directory in
which each subsequent build script starts. For example:
copyit:
%chdir subdir (change into subdir)
omake $(MFLAGS) (do recursive Make)
%chdir .. (change back to parent)
%do [ target ] [ macro[+]=value ... ] run Executes the build scripts of the named target. The exit status of the
%do is the exit status of the last build script of target. If nothing
appears after the %do, this directive does nothing. If target does
not exist, omake issues a warning unless %do is preceded by the
@ shell-line prefix. During the %do, the attributes of target are the
combination of the attributes of the current target and of target,
with the current target having precedence.
macro=value is a macro definition that is in effect during this %do.
macro+=value appends value to the current value of macro. For
either form of redefinition, the old value is restored after the %do
is finished.
Spaces in target or between the start of macro and the end of value
must be enclosed in double quotes. Up to 10 macro definitions are
allowed per %do, separating the definitions with spaces. For
example, the directive
sub.obj : sub.c
%do COMPILE.c CFLAGS="–Od –Zi" OUT= –Fo$(.TARGET)
COMPILE.c :
%echo Compiling ==== $(.SOURCE) =====
cl $(CFLAGS) $(OUT) –c $(.SOURCE)
%echo Done ==== $(.SOURCE) =====
produces the following build scripts when sub.obj is updated:
Compiling ==== sub.c =====
cl –Od –Zi –Fosub.obj –c sub.c
Done ==== sub.c =====
3 - omake Reference 87
Table 14 Other Percent Directives (Part 3 of 6)
Appl.
Directive Description
Time
MakeCFile:
@echo Building an object from a .C source file
$(CC) /c $<
%echo [ –n ] message [ >[>] file ] read, Prints message either to standard output, or to file if redirected. The
run message is followed by a line feed unless –n is specified.
%error [ status ] [ message ] read, At read time, omake terminates with the user-supplied exit status
run (1 if status is not supplied). At run time, this returns the exit status
which is treated like any other build script exit status. If message is
supplied, omake prints this message to the error output (standard
error) before terminating or returning the exit status.
%exec command_line read Executes the command_line and sets the status macro to the exit
status.
Appl.
Directive Description
Time
%include [ < or " ]name[ > or " ] read Reads the contents of name into this makefile. omake looks in
different places depending on whether the file is specified as name,
"name", or <name>.
If name is an absolute pathname, it is only looked for there.
Otherwise, "name" is looked for in the directory of the including
file, then in the directory of make.ini. For Windows NT, omake
looks in the directory of omake.exe, then in directories of the INIT
environment variable, and finally in directories of the INCLUDE
environment variable.
<name> is looked for in the same manner as is "name", except the
directory of the including file is not used.
For example:
%include c:\home\make.ini (use the absolute path)
%include <c:\home\make.ini> (use the absolute path)
%include make.sub (use dir. of including file)
%include "make.tpl" (use the search scheme)
%restart [ command_line ] read, Restarts the make process. If command_line is not supplied , omake
run is restarted with the original command line. This calls omake
recursively; it can be done at read time, and you don't have to keep
track of the command line.
When you use %restart while running omake in a VOB, %restart
writes a configuration record before restarting. Note that if a target
with %restart in the build script is ever winked in, the %restart
doesn’t occur. Therefore, if your build script has a rule to rebuild
the makefile and then has %restart to re-read the updated makefile
and continue building, this won’t have the desired effect if the
makefile is winked in. omake winks in the makefile, but no restart
occurs, and the old makefile is used for the rest of the build. In this
case, use –M or .MAKE_MAKEFILES to build the makefile before
reading it. In all other cases, mark any target with %restart in it as
.NOWINK_IN.
3 - omake Reference 89
Table 14 Other Percent Directives (Part 5 of 6)
Appl.
Directive Description
Time
%set name [+]= value read, Sets macro name to value at run time, although it can be used at read
run time. Use += to append to the current definition. As an example,
the build scripts of the following set_debug_flags target sets the
LDFLAGS value to /CO and appends –Od –Zi to the CFLAGS
value:
set_debug_flags :
%set LDFLAGS = /CO
%set CFLAGS += –Od –Zi
Any white space between = and value is ignored. Any white space
between += and value is condensed to a single space.
%setenv name [=] value read, Sets environment variable NAME (converted to uppercase on
run Windows NT) to value. The variable is available to omake and to
the build scripts executed by omake. If NAME is also a macro, the
macro value is also updated to value. After omake terminates, the
variable reverts to its previous value.
The main use of this directive is in the .BEFORE special target to
set up the environment for the makefile. For example:
.BEFORE .MAKE :
%setenv INIT=$(MAKEDIR);$(INIT)
We recommend that you not use this command with configuration
records at run time. It can cause evaluation of environment
variables to differ from run to run and prevents shopping from
finding an appropriate derived object to wink in. For example, in
one build, target A is built and changes the value of an EV; target
B is then built and references the value of that EV. The next time
the build is run, B may be built first and because A hasn’t modified
the environment variable yet, it runs differently than it did the first
time.
Appl.
Directive Description
Time
For PM/CB compatibility, omake supports the %exit directive and %status functional operators.
For Microsoft NMAKE compatibility, omake supports the !CMDSWITCHES and !message
directives. See Appendix D, Compatibility and Emulation, for details.
Dot Directives
Dot directives (usually called directives, also) appear on a dependency line where the target
name is a period followed by uppercase letters. Dot directives only work at read time.
At read time, dot directives modify the operation of omake from the point the directive is
encountered in the makefile. Most command-line options have an equivalent dot directive.
The current state of each dot directive is kept by omake in a state macro with the same name as
the directive. For example, the .DEBUG directive sets the debugging mode and the $(.DEBUG)
is the value of the debugging mode. (The state macros are described in Predefined Macros: State
Macros on page 63 and listed in condensed form in Table 22 on page 139.)
Directives that are effective on only some operating systems are noted.
Some directives accept lists of patterns as their dependents. Pattern lists may contain the pattern
character %. When evaluating whether a name matches a pattern, the tail of the prefix of the
name (subtracting directory names as appropriate) must match the part of the pattern before the
%; the suffix of the name must match the part of the pattern after the %. For example,
3 - omake Reference 91
/dir/subdir/x.o matches the patterns %.o, x.o, subdir/%.o, and subdir/x.o, but does not match
/dir/subdir/otherdir/x.o.
.DEPENDENCY_IGNORED_FOR_REUSE:
.DO_FOR_SIBLING:
.INCREMENTAL_REPOSITORY_SIBLING:
.INCREMENTAL_TARGET:
.SIBLING_IGNORED_FOR_REUSE:
.WINK_IN:
Table 15 lists omake directives, their equivalent command-line options (if applicable), and the
actions that the directives perform.
3 - omake Reference 93
Table 15 omake Directives (Part 3 of 10)
.INCLUDE : file ... The files are included at this point in the makefile. Each
file is treated as if %include file happened at this point.
3 - omake Reference 95
Table 15 omake Directives (Part 5 of 10)
.MACRO_CHAR : char Selects char as the new macro character. It is best to put
this directive in make.ini. For example, to change from
the default $ to + use the following:
.MACRO_CHAR : +
These characters cannot be the macro character:
(){},:=#'@*<&
3 - omake Reference 97
Table 15 omake Directives (Part 7 of 10)
.NOCMP_SCRIPT : tgt ... Builds the specified targets as if the –O option were
specified; build scripts are not compared during
configuration lookup. This is useful when different
makefiles (and, hence, different build scripts) are
regularly used to build the same target.
The list of targets may be specified with a tail-matching
pattern, for example, %.obj.
.RESPONSE.XXX : [ response definition ] Controls automatic response files (see Response Files on
page 110).
.SHELL : [ .AUTO | .NOMULTI Names both the shell program and its flags and specifies
| .NOREDIR ] ... [ program flags ] that the shell program be used to execute every build
script. The .NOSHELL directive specifies that all build
scripts are executed directly, without using the shell
program. However, the + (use shell) and : (suppress
shell) shell-line prefixes override any .SHELL and
.NOSHELL directives.
The .AUTO keyword tells omake to determine when
to use the shell program. Without this keyword, the
.SHELL directive specifies that the shell program is
used for every shell line.
The .NOMULTI keyword tells omake not to do special
processing for multiple-command shell lines. By
default, omake turns the multiple-command shell line
into a batch file, which is executed.
The .NOREDIR keyword tells omake not to handle
redirection of I/O on the shell line. By default, omake
handles redirection except |. With this keyword, only
the shell program handles redirection. If .NOREDIR is
used with .AUTO, any redirection on the shell line
causes the command to be executed by the shell
program.
A .SHELL directive that is not given a program reverts
to the remembered shell program:
.SHELL :
to execute every build script. The initial value of
.SHELL:
.SHELL : $(COMSPEC) /C
To use the MKS shell, use the following syntax:
.SHELL : “$(ROOTDIR)\mksnt\sh”
3 - omake Reference 99
Table 15 omake Directives (Part 9 of 10)
.SIBLING_IGNORED_FOR_REUSE : file ... Ignores files when omake determines whether a target
object in a VOB can be reused (is up to date). This is the
default behavior, but this directive can be useful in
conjunction with the .SIBLINGS_AFFECT_REUSE
directive or –t command-line option. This directive
applies only to reuse, not to winkin.
You can specify the list of files with a tail-matching
pattern, for example, %.lock.
Unlike the files listed in most directives, the files on this
list refer to the names of sibling objects, not to the
names of targets. As such, the directive may apply to
the siblings of many targets at once. This directive is
most useful when identifying a class of siblings found
in a particular toolset for which common behavior is
desired across all targets that have that sibling.
.SUFFIXES : [ extension ... ] Limits and orders the inference rules. .SUFFIXES is
provided for compatibility with other make utilities
and its use is discussed in the section Compatibility with
Suffix Rules (.SUFFIXES) on page 37.
omake supports many other directives for NMAKE, PM/CB, and Borland Make compatibility.
See Appendix D, Compatibility and Emulation for details.
Attributes are given to targets on dependency lines, but there are two forms:
Each form assigns the attributes to the indicated targets. The first form places the attributes after
the targets and before the colon, and each target is given all attributes.
The second form has attributes only to the left of the colon and targets to the right. Each target is
given all attributes. If no targets are listed, the attributes are given to all targets defined in the
makefile after this line. This is very useful. To give all targets in a makefile an attribute, put a line
of this form before any other dependency lines. This example that gives all targets defined after
this line the .PRECIOUS attribute:
.PRECIOUS : (near the top of the makefile)
Inference rules can have attributes, and the target being made with the inference rule inherits the
additional attributes of the rule.
A target's attributes have a higher precedence than a rule's attributes. If a target and a rule specify
an inconsistent attribute, the target's attribute is accepted.
List of Attributes
Attribute Definition
Attribute Definition
.NOCMP_NON_MF_DEPS : tgt ... Builds the specified targets as if the –G option were
specified; for each specified target, any dependency
not explicitly declared in the makefile is not used in
configuration lookup.
Attribute Definition
.NOCONFIG_REC : tgt ... Builds the specified targets as if the –L option were
specified; modification time is used for build
avoidance, and no CRs or derived objects are
created.
.AFTER : [ source ... ] After omake builds its last target and immediately before it
exits, any sources to .AFTER are built, and the build scripts of
.AFTER are executed. To execute the build scripts even when
using omake –n, give .AFTER the .MAKE attribute.
.BEFORE : [ source ... ] Before omake builds its first target, any sources to .BEFORE
are built, and then the build scripts of .BEFORE are executed.
To execute the build scripts even when using omake –n, give
.BEFORE the .MAKE attribute.
For PM/CB compatibility, we support .DEINIT, .EPILOG, .INIT, and .PROLOG. See
Appendix D, Compatibility and Emulation.
With omake’s search directory support you write dependency lines, such as
and have omake figure out where main.c and io.h are actually located.
omake uses the search directories to locate files. It is clear that if the file exists, the location of the
file is the directory it was found in. What happens if the file is missing? In this case omake
assumes that the missing file is located in the first directory of the appropriate search directory,
or . (the current directory) if none is appropriate.
Search directories are set up with macro definitions. omake supports .PATH macros and VPATH
macros, but issues a warning if you use both.
The .PATH[.ext] macros define the directories omake uses to find files that don't have a path
component. The optional .ext makes the .PATH.ext macro extension-specific. That is, .PATH.ext
defines the search directories only for files with extension .ext. The .PATH macro (with no
extension) controls the search for all files that aren't handled by a specific .PATH.ext.
The value of the .PATH macros is a list of directory names separated by semicolons (;). Here are
two examples:
.PATH = .;..
.PATH.obj = ..\obj
The first definition tells omake that all files can be found in . (the current directory) or .. (the
parent directory). The second definition tells omake that files with extension .obj can be found
in directory ..\obj (and in no other directory). Note that we have defined both a nonspecific
.PATH and an extension-specific .PATH.obj. omake uses directories defined in .PATH.obj to
search for files with the .obj extension, and uses .PATH for all other files.
project.exe : $(OBJS)
link $(.SOURCES), $(.TARGET), $(.TARGET,B);
The .c files are located only in the parent directory (..). Because no .PATH macro is defined,
omake searches for all other files only in the current directory.
The VPATH macros are similar to the .PATH macros with one major exception: the VPATH
macros specify search directories in addition to the current directory. That is, the VPATH macros
always have . as the first directory.
Macros in omake usually serve as a simple text replacement. However, the run-time macros
(.TARGET, .SOURCE, .SOURCES, and so on) include the location the target or source was
found. For example,
.PATH.obj = objs
main.obj : main.c
%echo $(.TARGET)
displays objs\main.obj because the main.obj target is located in the objs directory, and the
value of the .TARGET macro is the pathname of the target.
Here is a %.obj : %.c rule for Borland C that uses two run-time macros:
%.obj : %.c
$(CC) $(CFLAGS) –o$(.TARGET) –c $(.SOURCE)
The –o option names the output object file. $(.TARGET) is the name of the .obj file to be created,
including its path component, according to where omake found the file. If the .obj file was not
found, .TARGET is the implied location, either the first directory in .PATH.obj, if defined.
Otherwise, it is the first directory in .PATH, if defined, or finally, in the current directory.
When omake searches for a file that has no directory component, it looks in the appropriate
search directories. After the file has been located, omake assumes the file's location is permanent.
Occasionally, this behavior is in error. For example, suppose a project's current .c and .obj files
reside in a remote directory that .PATH references. You want to change a local copy of the
project's main.c and then compile and link the resulting local main.obj with the remote .obj files,
to produce a local .exe file.
%.obj : %.c
$(CC) $(CFLAGS) –c $(.SOURCE)
project.exe : $(OBJS)
link $(.SOURCES), $(.TARGET);
You change the local copy of main.c. If there is a remote main.obj but no local main.obj, when
you run omake, these commands are executed:
cl –c main.c
link c:\remote\main.obj c:\remote\io.obj c:\remote\keyboard.obj, project.exe;
The compilation uses the local main.c to produce a local main.obj, but the link uses
c:\remote\main.obj rather than the local main.obj. This is because there was no main.obj in the
current directory when omake started, and omake found main.obj in the c:\remote directory.
This example illustrates a general problem with omake. For reasons of speed, omake looks for a
file (target) one time only. After that, omake assumes the location of the target is constant. As you
have seen, this assumption can be wrong.
You can use the .REREAD target attribute to change this behavior. After executing the build
scripts that update the target, omake searches again for any targets with the .REREAD attribute
on disk. In the example, the make works correctly if the inference rule is given the .REREAD
attribute:
The inference rule has the .REREAD attribute because main.obj inherits the build scripts and
attributes of the matched inference rule.
When omake tries to find an inferred dependency for an inference rule, it constructs a particular
file name. If the file name has no path component, omake tries the file name in each search
directory in order. Because each search directory is searched for each possible inferred
To debug your search directory choices, use the –p command-line option to print a section titled
Search directories.
For PM/CB compatibility, we support the .SOURCE directive, which is an additional way to
specify search directories. The .SOURCE directive can specify the search directory for specific
files, rather than for file extensions only.
For NMAKE compatibility, we support their search paths for dependents. See Microsoft NMAKE
Compatibility on page 158.
omake supports:
➤ Automatic response files and variables, where it generates a response file or places long
command lines into an environment variable.
➤ Inline response files, where you place response file syntax around your build scripts.
The advantage of automatic responses (both files and variables) is that you don't worry about the
command-line limit. When the build script exceeds the limit, a response file or variable is
generated and the command is executed, using the response file or variable. You set up
automatic responses once, for your linker, librarian, and so on. Thereafter, the build script for
those programs can be arbitrarily long.
Inline response files are supported by a variety of other make utility vendors, and we support
the syntax they use.
A response class is a generalization that describes how and when to generate a response file or
variable. When a response class has been defined, you tell omake which program names accept
that class of response. We predefine most popular response classes, so you need only give omake
the names of programs that accept these predefined responses.
To tell omake which programs accept response files or use environment variables, use the
.RESPONSE.xxx directive, where xxx is a name of a response class. For example, we predefine a
LINK response class that describes the response file acceptable by Microsoft Link.
The .RESPONSE.xxx directive is used to define or modify a response class and to add program
names to an existing response class:
The parameters describe the response class. Each program is either a base name (having neither
path nor extension) or a pathname. Normally, you use a base name only, but for special
circumstances you can use a pathname. If you use a pathname, you can have different response
classes based on the literal name of the shell-line program, the pathname to the shell-line
program, or the base name of the shell-line program.
To add program names to an existing response class, list them to the right of the directive. For
example, adding LINK-style automatic response file support for SLR Systems optlink and
Borland tlink is done as follows:
The response classes are searched for program names in order from most recently defined to first
defined, so your use of a program name overrides any predefined usage.
Table 18 shows the parameters, the meaning of each parameter and its default value, and
whether the parameter is used in response files and/or response variables.
Used in Used in
Parameter Meaning and Default
Files? Variables?
pre=ppp ppp is the prefix before the response file. If ppp yes yes
contains white space it must be enclosed in
double quotes.
To define a new response class or to modify an existing response class, use a .RESPONSE.XXX
directive with only parameters. One of pre, suf, or env is required when defining or modifying
a response type.
If env is defined, the response uses an environment variable, otherwise a file is used.
A directive with neither parameters nor program names removes support for this response class.
For example, you can turn off all LINK response files with this directive:
.RESPONSE.LINK :
This declares the LINK response class has a prefix of @, a suffix of .rsp, logical lines on the
command line are separated with commas, and physical lines in the response file are connected
into one logical line with +<ENTER>. This directive also declares that the program named link
accepts LINK-style response files. With this definition, the build script
is executed as
link @tempfile.rsp
The prefix @ tells link that what follows is the name of a response file. tempfile is a unique name
of the form tempdir\MAKEnum, where num is a 4-digit number, and the response file suffix .rsp
appears as the extension of the name. The response file contents:
The first logical line module1.obj ... moduleN.obj is broken up in to several physical lines in the
response file, each line ending with +<ENTER>. The next logical line test.exe; appears as the next
physical line in the response file.
The CL response class uses environment variable CL, and e:\c6\bin\cl.exe accepts this kind of
response. Because a pathname is used, the command line
cl
Write the build script as if the length of the command line were unlimited. When the build script
gets too long, the automatic response is generated, a modified build script is executed, and the
automatic response is removed.
To generate an automatic response, omake determines whether the program name given on the
build script matches a .RESPONSE.xxx program name (the response names). To see whether
there is a match, omake does the following:
➤ If any response names have path components, it first compares the literal shell-line program
name with all response names. If there are no matches, it looks on disk for the pathname
that corresponds to the shell-line program name and compares the pathname to all
response names.
➤ If no match has been found yet, it compares the base name of the program and with the
response names.
When the response class specifies a response file, the response file is generated if the build script
is longer than the in=num parameter.
When the response class specifies an environment variable and the build script is longer than the
in=num parameter, omake places the contents of the build script in the response environment
variable, appending to the value of the environment variable if it exists.
Automatic response files are deleted after the build script that generated the response file is
executed, unless the –#8 command-line option was used. Each automatic response variable is
restored to its previous value after the build script that generated it executes.
omake has built-in automatic response file support for Gimpel lint and Microsoft cl, lib & link.
In addition to automatic response files, omake also supports response files coded inline in the
makefile. Here is the syntax for an inline response file:
target :
command [ prolog ] << [ response_file ]
[ line copied to response file verbatim ]
.
.
.
<< [ epilog ]
The first << introduces the response file; the last << terminates it. response_file names the file. If
the name is omitted, omake generates a unique name of the form tempdir\MAKEnum.rsp, where
num is a unique number. Everything between the pair of << is placed in the response file and the
command is invoked as
The prolog and epilog are optional text. Usually, prolog is used to indicate that the following
argument is a response file, and @ is the most common prolog.
The epilog can be used for redirection or other text. There are three special words that can appear
in the epilog:
➤ ECHO specifies that the contents of the response file be displayed. omake also shows the
contents of the response file when the –n command-line option is used.
Inline response files are deleted unless the –#8 command-line option is used, or the KEEP
keyword appears in the epilog. Response files named by omake are deleted after the build script
is executed. User-named response files are deleted immediately before omake exits.
program.exe : $(OBJS)
link @<< $(MAKE_TMP)\link.rsp
$(OBJS,W+\n)
$(.TARGET)
$(.TARGET,B,>.map)
$(LIBS,W+\n)
$(.TARGET,B,>.def);
<< KEEP ECHO
Here, $(OBJS) and $(LIBS) are assumed to be strings separated by white space. The W macro
modifier replaces the white space with +<ENTER>, which is the appropriate line continuation for
Microsoft link. If OBJS has the value 1.obj 2.obj, and LIBS has the value 3.lib, these build scripts
evaluate to
link @$(MAKE_TMP)\link.rsp
1.obj+
2.obj
program.exe
program.map
3.lib
program.def;
The KEEP keyword has omake leave behind the response file. Otherwise, omake deletes it after
the build script finishes. The ECHO keyword tells omake to display the contents of the response
file after the link @$(MAKE_TMP)\link.rsp line is displayed. The default behavior is to display
the contents only when doing omake –n.
omake supports PM/CB local input scripts, NMAKE inline files and Borland Make's &&
redirection operator. See Appendix D, Compatibility and Emulation, for details.
4
This chapter describes the process of debugging omake makefiles.
➤ The –#1 option displays each makefile line as it is parsed. Blank and comment lines are
removed, and conditional directives are shown in normal, expanded, and evaluated forms.
➤ The –p option displays omake's internal information. With this option, you can examine the
following:
➣ The values of all macros, to see where they were defined. Make sure they have the correct
values.
➣ All targets, their attributes, and their build scripts, to see where they were defined. This
list also shows which target is the default target.
➤ The –d option prints a run-time trace of omake. With this option, you can do the following:
➣ Ensure that the correct initialization file and makefile are being read.
➣ Watch omake use configuration lookup to compare the target to each dependency.
For additional help with macros, the .DEBUG : 2 directive (–#2 option) causes omake to print a
warning if a macro is used without being defined.
Finally, the .DEBUG : 4 directive (–#4 option) warns about makefile lines that omake does not
know how to handle. This can catch misspellings of directives that you may have a hard time
detecting. This directive is especially useful if you are trying to use a makefile from some other
make utility.
PATH.h = .;C:\SRC\H
For the purposes of this example, an empty make.ini file was created. Here is the output, with
annotations in italics.
+
8: %if defined(CV) (Conditional directive is shown
:---> true and evaluated)
9: CFLAGS = –Od –Z7 (Conditional was true, so this line and
10: LINKFLAGS = -debug -debugtype:both this line are processed)
11: %else (End of first true conditional block)
14: %endif (Lines are skipped until the "%endif")
+
18: $(TARGET) : $(OBJS) (The default makefile target)
+
21: b.obj : $(TARGET,B).h (An additional dependency)
+
23: .PATH.h = .;C:\SRC\H
Following output by the –#1 option, –p prints out information internal to omake, including facts
about macros, targets, search directories, and inference rules. The output begins with this line:
*** Begin print out *** (Starts the -p printout)
The first block of output is the macro definitions including the names and values of macros and
the location they were defined. The location is any of the following:
built in Defined by omake, but changeable by you
predefined Defined by omake, but cannot be changed by you
command line Defined by you on the omake command line
file:number Defined by you in makefile file on line number
For brevity, most omake state macros have been omitted from this list:
.DEBUG_PRINT = 1 # predefined (state macro: the
–p flag)
.omake = 1 # predefined (state macro:
emulation)
BUILTINS = C:\Program Files\Rational\ClearCase\bin\ # predefined (name of the
make.ini built-ins file)
CC = cl # built in (name of the C
compiler)
CFLAGS = –Od –Z7 # demo:9 (C compiler flags)
CV = # command line (command-line
macro)
IMPLIB = lib # built in
LINK = link # built in (name of linker)
LINKFLAGS = -debug -debugtype:both # demo:10 (linker flags)
MAKE = C:\Program Files\Rational\ClearCase\bin\ # built in (make location)
omake.EXE
MAKEARGS = -ndf demo -p -#1 CV= # predefined (make command
line)
MAKEDIR = C:\SRC # predefined (make starting
directory)
MAKEFILE = demo # command line (name of the
makefile)
MAKEFLAGS = dnp -#1 # predefined
The search directories output lists both the extension-specific and nonspecific search directories.
The extension-specific directories are listed first:
A .PATH macro is not defined, so all other files are searched for only in the current directory.
Following the search directories are all automatic response file definitions. Each line of output of
this section appears in exactly the form needed as if it were input to omake.
%.obj : %.cpp
defined in: internal
$(CPP) $(CPPFLAGS) –c $(.SOURCE)
%.obj : %.asm
defined in: internal
$(AS) $(AFLAGS) $(.SOURCE);
%.obj : %.for
defined in: internal
$(FC) $(.SOURCE) $(FFLAGS)
%.res : %.rc
defined in: internal
$(RC) $(RFLAGS) -r $(.SOURCE);
%.exe : %.obj
defined in: internal
%do %.exe
* Meta rules *
%.lib :
defined in: internal
%if ! %null(.NEWSOURCES)
%if %exists(${.TARGET})
$(IMPLIB) -OUT:$(.TARGET) $(LIBFLAGS) $(.NEWSOURCES) $(.TARGET)
%else
$(IMPLIB) -OUT:$(.TARGET) $(LIBFLAGS) $(NEWSOURCES)
%endif
%endif
%.exe :
defined in: internal
$(LINK) -OUT:$(.TARGET) $(LINKFLAGS) $(.SOURCES) $(LINKLIBS)
The *Suffix rules* are rules that can be of the form .fromExt.toExt. The *Meta rules* are all
other inference rules.
A list of the targets follows the inference rules. The default target is listed first.
*** Targets and commands ***
>>> default target <<< (The first target in the makefile)
project.exe : a.obj b.obj (project.exe depends on a.obj & b.obj)
b.obj : project.h (b.obj depends on project.h)
Finally, after all –p output has appeared, you see this message:
A
When omake encounters a problem, it produces an error, warning, or report:
➤ Errors are the most severe, causing omake to display a message followed by the word Stop.
omake does some deinitialization and quits.
➤ Warnings are less severe. A message followed by the text string (warning) is displayed and
omake continues.
➤ Reports are the least severe. A message is displayed and omake continues.
OMAKE: message.
OMAKE: file (line number): message.
In the second, number indicates the line in makefile file that produced the diagnostic. omake
displays the additional file and line information when possible.
However, if the build script is prefixed with the dash, the report message is
A second common mode is omake's keep-working mode, specified with the –k command-line
flag or .KEEPWORKING directive. If omake is in this mode and encounters a problem when
executing a target's build scripts, it stops updating the target immediately. In this mode some
error messages are downgraded to report messages. For example, the previous error message is
now this:
NOTE: All messages that start with Test: are errors in the conditional expression tester.
Bad foreach 'line' error The foreach line has an incorrect syntax. The correct
syntax is
%foreach name [ in ] list_of_values
Bad transformation macro error The PM/CB transformation macro had an incorrect
specification.
Can't @include 'name' warning File cannot be read with the @ macro modifier.
Can't create lock in 'directory' error omake creates a lock file in the directory and bases the
name of its response, swap, and batch files on the name
of the lock file. The directory is either the value of the
MAKE_TMP macro (if defined) or the current
directory.
Can't %do 'name' warning The %do directive specified a nonexistent target name.
Use @ as a shell-line prefix before the %do to inhibit this
warning.
Can't find 'program' on PATH error or omake cannot execute the current build script because
[ (ignored) | (keep working) ] report the program was not found in any of the directories
specified in the PATH environment variable.
Can't have : and :: dependencies for 'target' warning The target was given on the left side of a regular (single
colon) dependency and also on the left side of a
double-colon dependency. These cannot be mixed.
Can't have both .PATH.ext and VPATH.ext error Both .PATH.ext and VPATH.ext macros were specified,
but omake does not know which macro to use to
determine the search directories.
Can't open file report The version control or library file can’t be opened for
or error reading or writing.
Can't open batch file 'file' error When executing multiple commands (see Using
Multiple-Command Build-Script Lines on page 73) the
commands are written to a batch file and the batch file
is then executed. The probable cause of this error is that
the MAKE_TMP macro has not been set properly.
Can't open inline response file 'name' warning The inline response file name can’t be opened for
writing.
Can't open response file 'name' warning The automatic response file name can’t be opened for
writing.
Can't read makefile 'name' warning The makefile name can’t be read.
Can't read response file 'name' warning The response file indicated on the command line by
@name can’t be read.
Can't redirect 'file' error The redirection for file was specified incorrectly.
Can't undefine macro 'name' warning The macro name can’t be undefined because it is a
predefined macro.
COMSPEC not found error The COMSPEC environment variable, used to initialize
the name and flags of the shell program, was not found
in the environment.
Dependency-line wildcard 'spec' is null warning The wildcard specification spec didn’t expand to any file
names.
Device error error or Execution of the build script caused a device error.
[ (ignored) | (keep working) ] report
Directive nesting too deep. Max 31 levels. error Only 31 levels of foreach, if, and while nesting are
supported, and your makefile has more than this.
%do macro missing '=' error A %do macro was missing the equal sign that is needed
for its definition. The most probable cause is that there
are spaces around it. If you need spaces, enclose them
(or the macro definition) in double quotes.
Don't know how to make 'target' error or omake has exhausted all means of making target. If
[ (keep working) ] report omake is in keep-working mode, it marks this target as
unusable and abandons work on it. Use the –d (debug)
and –p (print info) options to determine the cause.
Exec 'command' failed error The %exec command directive cannot be executed.
Inline failed warning The current inline response file couldn’t be generated
correctly.
Internal error: number error Report the internal error number to Customer Support.
Invalid executable 'program' error or The specified program is not a valid executable.
[ (ignored) | (keep working) ] report
Invalid SHELL 'program' warning The specified shell program was not found.
Macro 'name' has no value warning A run-time macro is used before its value was set.
Macro 'name' not found warning The macro called name is undefined. This message
appears only when the .DEBUG directive or –#
command line flag has been set to 2. When debugging
your makefiles, this helps catch misspellings.
Maketmp failed error The routine that generates temporary file names failed,
probably because the directory for the temporary files is
full.
Max 8 response files for 'cmd' error The multiple-command build script generated more
than eight (the maximum) response files.
Missing character in 'name' error omake was looking for character to mark the end of
macro name but came to the end of the line instead.
No targets on dependency line error The dependency line being processed had no targets on
the left side.
Not enough memory to exec 'name' error or There is not enough memory to execute the specified
[ (ignored) | (keep working) ] report program name.
Nothing to make error No target was specified on the command line, and no
default target exists in the makefiles.
Option 'letter' needs value error A required argument with the command-line option
–letter was not specified.
Out of memory error omake ran out of memory. Your makefile may be too
large, or omake may have installed a TSR.
Recursive macro 'name=value' warning The macro called name has a recursive value; the value of
the macro refers to itself. omake ignores the recursion.
Removing target report The target is removed because it was modified when an
error occurred in one of the build scripts that updated
it. Removal prevents partially written files (such as
object files) from being left behind when a compilation
fails. Targets with the .PRECIOUS attribute are not
removed.
Shell line exit status number error or The most recently executed build script had a nonzero
[ (ignored) | (keep working) ] report exit status of number.
Shell line too long error or The build script exceeded the command-line limit. Use
[ (ignored) | (keep working) ] report a response file. See Response Files on page 110.
Shell line without target error There is no target to which this build script belongs.
Build scripts are indented from the left column by a tab
or space character.
Test: bad expression "exp" error The expression exp cannot be parsed.
Test: bad first operand "op" error In a comparison, the first argument op cannot be parsed.
Test: bad operator "op" error The op is not one of the acceptable logical operators:
&&, | |, and = =.
Test: bad second operand "op" error In a comparison, the second argument op cannot be
parsed.
Test: no operand before "text" error There was no argument in a previous functional
operator.
Test: unexpected "text" error The expression is finished logically, but there was more
text on the line.
Test: unmatched quote "text" error Pairs of single or double quotes delimit strings that
contain white space. A quote in text was not matched.
Test: unknown function "name" error An expression of the form name() has an unrecognized
name.
Test: ')' expected; got "text" error A right parenthesis is expected, but text was found
instead.
Too many %do macros. Max of 10. error More than 10 macro definitions were specified for each
%do directive.
Too many shell lines for 'target' warning A target on a regular (single colon) dependency line can
be given build scripts one time only. The additional
build scripts are ignored.
Unexpected what error The what is either end or endif, and there is no previous
%foreach, %while, or %if directive.
Unknown option 'letter' Only the command-line options listed by omake –h are
acceptable.
Unmade 'target' due to source errors warning The –k flag was used to do the maximum useful work.
One of target's dependencies was not made because of
an error, so the target cannot be made.
Unrecognized .RESPONSE keyword warning The .RESPONSE directive does not accept the keyword
'word' word.
Unterminated inline from line number error The inline response file was not terminated before the
end of the makefile.
Unterminated what from line number error The what of if, elif, or else that started on line number
was not balanced before the end of the makefile was
reached.
User interrupt error The user typed <CTRL-BREAK> or <CTRL-C> while omake
was executing a build script.
B
omake controls the execution of other programs, and the memory that omake itself uses is
unavailable to these programs while omake is controlling them. When omake exits, it returns an
exit status indicating the termination reason. The exit status can be tested by the command shell
or, if you are doing a recursive make, by omake itself. The exit status can also be accessed in the
.AFTER special target with the MAKESTATUS macro. For example:
.AFTER :
%if $(MAKESTATUS) == 3
%echo omake: The final build script exited with status: $(status)
%endif
6 The build script was longer than the command processor allowed.
C
This chapter describes the macros and rules that omake uses.
C.1 Macros
This section describes general macros, state macros, and built-in macros.
.NEWSOURCES The list of target dependencies newer than the target; all
dependencies when configuration lookup is enabled and the target is
not marked as .INCREMENTAL_TARGET
.SOURCE The inferred dependency or, if none, the first explicit dependency
CWD The current working directory (the directory in which omake starts)
These predefined macros return the state of omake's command-line flags and directives. In
Table 22, when yes appears in the Directive column, the value of the named macro is the state of
the like-named directive. The Flag column shows the command-line flag that is the equivalent of
the directive (if any).
NOTE: .ALWAYS, .IGNORE, and .SILENT are actually target attributes. They look like directives
when they appear on the target side of a dependency line without any dependencies.
Nevertheless, the .ALWAYS, .IGNORE, and .SILENT macros have the correct value, as if these
attributes were directives.
.ALWAYS Yes –a 0 or 1
.CASE_MACRO Yes 0 or 1
.CASE_TARGET Yes 0 or 1
.DEBUG_PRINT Yes –p 0 or 1
.DEBUG_RUN Yes –d 0 or 1
.ENV_OVERRIDE Yes –e 0 or 1
.ENVMACROS Yes 0 or 1
.GLOBAL_PATH Yes 0 or 1
.IGNORE Yes –i 0 or 1
.IGNORE_MFLAGS –z 0 or 1
.KEEPDIR Yes –D 0 or 1
.KEEPWORKING Yes –k 0 or 1
.MAKE_MAKEFILE Yes –M 0 or 1
.REJECT_RULES Yes –r 0 or 1
.SILENT Yes –s 0 or 1
.UNIXPATHS Yes 0 or 1
1. Exactly one of $(.MS_NMAKE), $(.OMAKE), or $(.POLY_MAKE) is 1.
Built-In Macros
Table 23 lists macros that are defined by omake, but can be changed.
AS Assembler masm
CC C compiler cl
$(name,modifier[,modifier ...])
name is expanded, and each modifier is applied in order to the elements of the value.
Modifier Action
from=to Substitutes occurrences of from with to. If from does not appear in an element,
the element is not changed.
@/from/to/ Includes lines in text file, matching lines with regex from and replacing the
matched part of the line with regex to.
A Converts element to an absolute file name using the default path separator \.
Modifier Action
S/from/to/ Substitutes from (a regular expression) to to. If from does not match an
element, the element is not changed
Notice how the rules make use of macros. For example, the %.obj : %.c rule invokes the program
$(CC) with the flags $(CFLAGS). In your makefile, set CFLAGS to the flags to be passed to the
compiler.
AS = masm
.%.obj : %.asm
$(AS) $(AFLAGS) $(.SOURCE);
FC = f77l
%.obj : %.for
$(FC) $(.SOURCE) $(FFLAGS)
Resource compiler script to resource file, using the Microsoft Resource Compiler:
RC = rc
%.res : %.rc
$(RC) $(RCFLAGS) –r $(.SOURCE)
LINK = link
%.exe :
$(LINK) –OUT:$(.TARGET) $(LINKFLAGS) $(.SOURCES) $(LINKLIBS)
%.exe : %.obj
%do %.exe
D
omake achieves a great deal of compatibility with other make utilities, in that it understands the
makefiles and features of other makes. When a feature or operation of omake differs from that
of the other utilities, we provide emulation, so that omake operates like the other vendor’s make
utility.
System Macros
omake supports the PolyMake/Configuration Builder system macros listed in Table 25:
omake supports PM/CB v5.x, both long and one-letter names. When an omake equivalent
exists, it is listed in the right column of Table 26. Note that PM/CB macros work on text; omake
modifiers work on a macro, which is expanded into text and modified. To use the omake
equivalent, you need to define macro name with value text.
Built-In Functions
%status
This is the exit status of last build script. It is the same as $(status) in omake.
%exit [ status ]
This directive terminates the make process with exit status (0 if status isn't given). Before
terminating, the .DEINIT and .EPILOG special targets are run if they are defined.
.DEINIT is run only if .INIT was run.
Directives
omake supports most PM/CB directives. For read-time interpretation, the directive starts in the
first column of the makefile. For run-time interpretation, PM/CB emulation must be chosen and
the directive must be indented.
Applicable
Directive Description
Time
.Emulate [ Builder | NMAKE ] read time Sets the emulation mode to either Builder (PM/CB) or
NMAKE.
.Include [ = ] file ... read time Reads each file. If PM/CB emulation is chosen, omake
looks for relative file names in the current directory. If
PM/CB emulation is not chosen, omake treats
.INCLUDE file the same as %include(file).
.Keep_Lis read time Prevents local input scripts (inline response files) from
run time being deleted. The negative of this directive is
.NoKeep_Lis.
.Lis_File [ = ] [ filename ] read time Names the local input script file. Unlike PM/CB,
run time omake allows a blank filename to reenable automatic
generation of the local input script name.
Applicable
Directive Description
Time
.Remake read time Targets are fully made each time they are encountered
as sources.
.Shell [ shell_program ] read time Similar to the omake .SHELL directive, but without
run time automatic detection of when to use the shell program.
.Silent read time Build scripts are not displayed on the screen before
execution.
.Source [ = ] dir_list file_list read time Gives search directories to files. The dir_list is a
semicolon-separated list of directories. The file_list is a
space-separated list of filenames or file extensions.
When omake looks for a file, it sees whether the file
name or its extension is on any file_list; if it is, omake
searches for the file on the dir_list.
.Source [ .ext ] : [ dir-1 dir-2 ... ] read time This PM/CB .SOURCE dependency is identical to a
.PATH macro and is treated as an
.PATH.xxx = dir-1[;dir-2]... macro definition.
.Suffixes [ : ] read time Without a colon, this directive acts like omake's
.REJECT_RULES directive. With a colon, it acts like
the omake .SUFFIXES directive.
Applicable
Directive Description
Time
Reserved Targets
.DEINIT [ : ]
If the .INIT special target was used, the build scripts of the .DEINIT target are executed
immediately before the build scripts of .EPILOG are executed.
.EPILOG [ : ]
The same as the omake .AFTER special target. If emulating PM/CB, omake looks only
for .EPILOG. Otherwise, it looks for .AFTER, and then .EPILOG.
.INIT [ : ]
This target's build scripts are executed immediately before any other build scripts.
.PROLOG [ : ]
The same as the omake .BEFORE special target. If emulating PM/CB, omake looks only
for .PROLOG. Otherwise, it looks for .BEFORE, and then .PROLOG.
target :
command [ prolog ] <X<[ text ]
build script
.
.
.
< [ epilog ]
Operation-Line Modifiers
omake supports all PM/CB operation-line modifiers, which are listed in Table 28.
(Always) &
(ExtraLine) >
(Iterate) !
(Shell) +
(Silent) @
(TrackErrors) ~
PM/CB Emulation
omake is highly compatible with PM/CB, but there are differences in how they read makefiles
and in how they run. In PM/CB emulation mode,omake operates like PM/CB.
If PM/CB emulation mode is selected at startup time, omake emulates the PM/CB command
line and selection of the built-ins file. Selection of PM/CB emulation at startup time is done with
the –EP flag, either on the command line or in the OMAKEOPTS environment variable.
To determine the startup emulation mode, omake examines the OMAKEOPTS environment
variable for –Ex flags. It then examines the command-line for –Ex flags. If the last –Ex flag is –EP,
omake starts up emulating PM/CB.
The .POLY_MAKE directive turns on PM/CB emulation mode from the point it appears in the
initialization file or any makefile.
First the OMAKEOPTS environment variable is parsed for options. Then, if omake is emulating
PM/CB at startup, the MAKEOPTS and BUILD environment variables are parsed for options. Then
the command line is parsed. Parsing entails the following:
➤ Mapping options into omake equivalents. The help screen switches to the options available
with our emulation of PolyMake v4.0 and Configuration Builder v5.x. The help screen's
contents are stored in the file omhelp.cb.
Without emulation at startup, the command line is as documented in the section Command-Line
Options on page 41.
If omake is emulating PM/CB at startup, omake reads its internal rules and macros. It then looks
for builtins.cb first in the directory of make.ini, in the directory of omake.exe, and along
directories of the INIT environment variable, in that order. If builtins.cb is found, it is read for
macros and rules that give more complete PM/CB emulation.
PM/CB distinguishes between an initialization file and a built-ins file. Both contain initialization
information. The initialization file is almost always the file named tools.ini. If omake is
emulating PM/CB at startup, omake searches for the initialization file and reads the first one it
finds :
If omake finds the initialization file, it reads information in the file starting with the section
heading [PVCS.
If omake is emulating PM/CB at startup, omake searches for the built-in file, and reads the first
one it finds:
If omake is not emulating PM/CB at startup, it uses the method documented in the section
Locating the Initialization File on page 46 to locate the initialization (built-ins) file.
The Makefile
If omake is emulating PM/CB at start up, omake looks for the default makefile in this order:
script.bld, script, makefile, makefile.mak. The first file found is read. When trying to read a
makefile file that doesn't have an extension, omake tries file, file.bld, and file.mak, in that order.
Makefile Contents
➤ The line continuation character sequence \<ENTER> is removed from the input.
➤ The PM/CB-compatible directives listed in the previous section can be used at run time as
well as read time.
➤ The %end directive is the same as %endif. Without emulation, %end terminates a
%foreach or %while directive.
➤ The TMP, TEMP, and WORK environment variables are tried, in order, for the location of the
directory where temporary files are created. Without emulation, omake uses the value of
the MAKE_TMP macro.
➤ The shell program is used for executing every build script. The * and (NoShell) prefixes
suppress execution of the shell program for this build script.
➤ The build scripts cd dir and chdir dir both change to directory dir and stay there until
changed back explicitly. Otherwise, omake starts each build script from the directory that
omake started in the $(MAKEDIR) directory.
➤ The - shell-line prefix does not print the Error code ... (ignored) message.
When running PM/CB makefiles with omake, be aware of the lack of support for some PM/CB
features. The list here provides a workaround, when it is available.
Iteration Groups
An iteration group does an implicit iteration over the $? macro. For example:
Suffix dependencies allow the specification of a set of suffixes to be tried when building a
particular target. This is not supported by omake.
Command-Line Flags
The following PM/CB command-line flags are not supported: –Batch, –C, –Compile,
–NoEnvInherit, or –Rebuild.
Makefile Contents
The ~ suffix on archive extensions to handle like-named files in different directories is not
supported. Instead, use a pattern-matching rule , such as this:
%.c : c:/apps/archives/%.c
get –q –w $(_SourceRev) $(_Source)($(_Target))
Shared Definitions
omake does not parse the PVCS Version Manager configuration file automatically.
Operation-Line Modifiers
For PM/CB, the (Always) operation-line modifier (Shell-Line Modifiers) overrides the –Touch
flag. This is not supported in omake. You can use the .MAKE attribute instead. For example:
# PM/CB
recursive :
(Always)$(MAKE) $(MAKEFLAGS)
# Omake
recursive .MAKE :
$(MAKE) $(MAKEFLAGS)
Built-In Operations
The built-in operations that handle foot printing are not supported. These operations are
%EAStamp, %ExeStamp, and %ObjStamp.
NMAKE Directives
This read-time directive turns on (+) or off (–) one or more options, opt.
!message message
NMAKE Emulation
omake is highly compatible with NMAKE, but there are differences in how they read makefiles
and in how they run. omake's NMAKE emulation mode causes omake to operate like NMAKE.
If NMAKE emulation mode is selected at startup time, omake emulates the NMAKE command
line and selection of the initialization file. Selection of NMAKE emulation at startup time is done
with the –EN flag, either on the command line or in the OMAKEOPTS environment variable.
To determine the startup emulation mode, omake first examines the OMAKEOPTS environment
variable for –Ex flags, and then the command-line for –Ex flags. If the last –Ex flag is –EN, omake
starts up emulating NMAKE.
NOTE: If you want submakes (recursive invocations of omake) to inherit NMAKE emulation
mode, you must specify the –EN flag in the OMAKEOPTS environment variable.
The .MS_NMAKE directive turns on NMAKE emulation mode from the point it appears in the
initialization file or any makefile.
The OMAKEOPTS environment variable is parsed for options, and then the command line is
parsed. Parsing entails the following:
➤ Switching the help screen to the options available with NMAKE v1.3. The help screen's
contents are stored in the file omhelp.nm.
Without emulation at startup, the command line is as documented in the section Command-Line
Options on page 41.
If omake is emulating NMAKE at startup, omake reads its internal rules and macros, and then
looks for builtins.nm in the directory of make.ini, in the directory of the omake.exe file, and
along directories of the INIT environment variable, in that order. If builtins.nm is found, it is read
for macros and rules that give more complete NMAKE emulation.
If omake is emulating NMAKE at startup, omake reads the tools.ini file found in one of these
directories:
If omake finds the initialization file, it reads information in the file starting with the section
heading [NMAKE.
Makefile Contents
➤ The !else if, !else ifdef, and !else ifndef directives are supported.
are supported and cause $(VAR) to be expanded before VAR is redefined. Other macro
references in the macro value are not expanded.
ENVVAR = value
where ENVVAR is an environment variable, assign to the ENVVAR macro the value, which is
also exported to the environment. If the –E command-line flag is used, makefile macros
cannot override environment macros, and this macro redefinition is ignored.
➤ Search paths for dependents are supported. These look like this:
➤ Inference rule search paths are supported. These look like this:
{fromdir}.fromext{todir}.toext : (build script for inference rule)
➤ Inference rules for targets that have a directory component look for the inferred source in
the directory of the target.
➤ The !include file directive is supported. If file is an absolute pathname, it is used; otherwise,
omake looks for file in the current directory, and then in the directory of the including file. If
file appears inside angle brackets (for example, <file>), omake then looks along the
directories in the INCLUDE environment variable.
Macros
➤ Environment variables override built-in macro definitions (see the section Macros on
page 52).
Most other make programs expand macros when a build script is run, but NMAKE expands
macros when it parses the makefile. When the rule is parsed, it is defined with the expanded
value of the macro, rather than with a reference to the macro. (The reference would be
expanded at run time).
EXCEPTION: NMAKE evaluates run-time macros at run time, because the values to which
they are set are based on the target.
FOO=A
rule:
@echo $(FOO)
FOO=B
Build Scripts
➤ The build scripts cd dir and chdir dir both change to directory dir and stay there until
changed back explicitly.
➤ A set var=val build script is treated specially and sets the environment variable VAR to the
value val. That is, this build script is treated exactly like the omake directive %setenv
var=val.
➤ The filename-parts syntax is supported. You can use this to get at the components of the
name of the first source file. The complete file name is represented with the %s syntax. Parts
of the file name are represented with this syntax: %| [parts] F , where parts is zero or more of
➤ Shell-line prefixes are limited to @, -, and !. The ^ prefix stops processing of prefixes.
omake supports the NMAKE response file syntax, except that multiple inline response files on a
single build script are not support.
NMAKE and omake allow the keywords KEEP or NOKEEP in the epilog of the inline response
file. KEEP causes the response file to be kept (that is, not deleted). The default is NOKEEP.
Multiple inline response files on a single build script are not supported.
The –E2 command-line flag makes omake emulate Opus Make 5.2x.
➤ Automatic dependencies
omake knows how to read the dependency information stored in object files created from the
Borland bcc compiler.
➤ Special targets
.SWAP : .SWAP should only be found in makefiles produced by the Borland
prj2mak program.
where prolog is usually @ and X is a single character (Borland uses ! in its examples). The
build scripts are placed in a response file and the command is invoked with the following
command, where tempfile is a unique filename:
➤ makefile syntax
include filename
where include is in the leftmost column of the makefile includes filename at this point in the
makefile. The makefile expression
$(name:str1=str2)
is a macro modification with string substitution, with strings str1 and str2 both capable of
using the % character as a wildcard to match zero or more characters in the expansion of
name.
➤ Inference rules
omake supports the suffix rules and metarules of UNIX Make. Suffix rules are converted into
omake inference rules. The .SUFFIXES directive is also supported.
E
Regular expression matching is a scheme for string searching. A regular expression is a string of
characters, some normal, some special, that allows the specification of a pattern to be matched.
[4] [ set ] Matches one character in set. If the first character in set is ^, this
form matches characters not in set. A range start–end means
characters from start to end. The characters ] and – aren't special if
they appear as the first characters in set. \t matches a tab character.
For example:
Set Matches
[a-zA-Z@] Lowercase and uppercase alphabetic, or @
[^]–] Neither ] nor –
[^A–Z] Not uppercase alphabetic
[<SPACE> \t] A space or tab (that is, white space)
[5] form* Any regular expression form labeled [1] to [4] followed by the
closure character * matches zero or more of the form.
[7] \( form \) A regular expression in the form [1] to [10], enclosed as \( form \)
matches what form matches. The substring matched by form can be
referenced with a tag (see below).
[9] form1form2 A composite regular expression form1form2, where form1 and form2
are in the form [1] to [9], matches the longest match of form1
followed by a match of form2.
[10] ^ and $ A regex starting with ^ and/or ending with $ restricts the regex to
the beginning of the line and/or the end of line. Elsewhere in the
regex, ^ and $ are ordinary characters.
Once a regular expression has matched, you can reference the matched part:
➤ & refers to the entire matched string (but \& is a literal ampersand).
➤ If \( \) is used to delimit a part of the regular expression, the tag \1 refers to the first
delimited part of the matched substring. Successive pairs of \( \) are tagged \2, \3, ..., \9.
To select files that end in .c, anchor the search to the end with the regular expression character $.
To get $ to the regular expression, use $$ in the makefile:
$(SRCS,M.c$$) is main.c
The ^ regular expression character anchors the search to the front of the macro element:
The [set] regular expression characters indicate a set of characters, where set can be single
characters ([aA@] matches a, A, or @), a range of characters ([a-z] matches a through z), or a
mixture. For example:
One powerful feature of regular expressions is that when they are used in substitutions, they can
access the matched parts of the string. The S/rfrom/rto/ (substitution) modifier uses regular
expression rfrom to substitute the matched part of an element with the rto regular expression. For
example, when DIR = NT_L, the expression $(DIR,S/\(wild*\)_wild*/\1/) is NT
The \( \) pair surround part of the regular expression that can be referenced later. Inside the pair
is wild*, which matches any character repeated zero or more times. Taken together, they mean
instruct omake to match any character, zero or more times, and tag it. The rest of the regular
expression is _, which matches _ and wild*, which matches any character repeated zero or more
times.
The substitution replaces the matched part of the element with the expression \1, which is the
stuff matched in the first pair of \( \). The entire element was matched, so the substitution
produces NT. Table 30 shows other expressions.
Expression Result
$(DIR,S/wild*_\(wild*\)/\1/) L
$(DIR,S/wild*_\(wild*\)/&/) NT_L
ATTRIBUTES. Properties that can be associated with targets. They include .MAKE, .REREAD,
.SILENT and others.
BASE NAME. A file name without any directory components or extension.
BUILD. To bring a target up to date (make it current).
BUILD AVOIDANCE. The ability to fulfill a build request by using an existing derived object, instead
of creating a new derived object by executing a build script.
BUILD SCRIPT. A command executed by omake or passed to the shell program for execution. Build
scripts are used to update targets.
COMSPEC. This environment variable names the program that is the operating system
command processor or shell program. For Windows NT, this is usually cmd.exe.
CONFIGURATION LOOKUP. The process by which omake determines whether to produce a derived
object by performing a target rebuild (executing a build script) or by reusing an existing
instance of the derived object. This involves comparing the configuration records of existing
derived objects with the build configuration of the current view: its set of source versions, the
current build script that would be executed, and the current build options.
DEFAULT TARGET. The first normal target defined in the first makefile. A normal target is not a
directive, special target, attribute, or inference rule. It is the target that is made when omake
is run without any command-line targets.
DEPENDENCY. Anything a target depends on. Dependencies are themselves targets because they
can be made.
DEPENDENCY LINE. The line in a build script that indicates the dependence of a target on its
dependencies. For example,
test.exe : main.obj sub.obj
declares that test.exe depends on main.obj and sub.obj.
DIRECTIVE.The instructions that control how omake proceeds. There are run-time directives and
read-time directives, and some work both at read and run time. Directives are indicated by
Glossary 171
the appearance of either % or ! as the first non-white-space character on a makefile line,
followed by the directive name. If the % (or !) is in the leftmost column of the makefile, the
directive is interpreted at read time; otherwise, it is interpreted at run time.
DIRECTORY SEPARATOR. The character in a pathname that separates directory names and the file
name. For Windows NT, the separator is either \ or /. omake uses either character as the
directory separator.
DOT DIRECTIVES. A read-time directive that modifies the operation of omake from the point at
which it is encountered in the makefile.
EXIT STATUS. A number returned by an executed program and testable by omake. At the
command line, you can check the exit status of the last executed program by using the if
errorlevel command.
By convention, programs return a zero exit status when they finish without error and nonzero
when an error occurs.
EXPLICIT RULE. A dependency line and build scripts that are used to make a target, in this form:
target : dependencies
build script
.
.
.
EXPLICIT DEPENDENCY.A dependency declared in a dependency line. For example, def.h is an
explicit dependency of main.obj in the following:
main.obj : def.h
EXTENSION. The suffix part of the file name, usually used to denote the type of file. The extension
consists of the characters that follow the last period in the file name to the end of the name.
FILE NAME. The part of the pathname after the last directory separator.
HEADER FILE. A file, containing source code, that is included into the body of a source file.
INCLUDE FILE. See header file.
INFERENCE RULE. A rule that generalizes the build process so that you do not have to specify how
to build each target. For example, here is the built-in inference rule for making an .obj file
from a .c file:
%.obj : %.c
$(CC) $(CFLAGS) –c $.SOURCE
INFERRED DEPENDENCY. The dependency determined with an inference rule. For example, if
main.obj is being built and the inference rule %.obj : %.c is used, main.c is an inferred
dependency of main.obj.
INIT. An environment variable whose value is a semicolon-separated list of directory names. For
example:
INIT = c:\home;c:\msc
Glossary 173
SOURCE FILE. A file containing source code that can be compiled into object code.
SPECIAL TARGET. A target whose name is of the form .NAME and that has special meaning to
omake.
STANDARD ERROR/OUTPUT. The two output streams (or file descriptors) that write to the console.
Standard output is usually used to output general messages. Standard error is usually used
to output error messages.
TARGET. Something that can be made. A target is usually a file, such as a source, object, or
executable. The target is said to exist if the file is present on disk.
TARGET ATTRIBUTE. Properties assigned to targets.
TIME STAMP. The time stamp of a target is the time and date that a target was last changed. It is
usually the creation or modification time of the file, as stored by the operating system.
UPDATE (A TARGET) . To execute a target’s build scripts. This brings the target up to date.
UP TO DATE TARGET. A target that is current; that is, it has been compiled, linked, and so on, and is
newer than all its dependencies.
WHITE SPACE. One or more space or tab characters.
WILDCARD CHARACTER. Characters used to match ambiguous part of a file name. Windows NT
treats ? as a wildcard character that matches any single character and * as a wildcard character
that matches any number of characters in a file name or file name extension.
Index 175
Index 177
Index 179
T
target groups 51
inference rules 32, 56
.TARGET run-time macro 26, 61
.TARGETROOT run-time macro 62
targets 9
default 47, 50
dummy 50
existence 9
targets attributes 101
technical support xviii
timestamps 9, 174
(TrackErrors) shell-line prefix 152
transformation macros 147
typographical conventions xvii
U
.UNIXPATHS directive 35, 66, 101
.UNIXPATHS state macro 66
updating targets 48, 174
up-to-date targets 10, 171, 174
V
VPATH macro 108
W
–w file-test operator 81
whitespace 174
wildcards 16, 57, 174
.WINK_IN directive 101
Z
–z file-test operator 81
Index 181