m3makefile(7) MODULA-3 PROGRAMMERS MANUAL m3makefile(7)
NAME
m3makefile- The Modula-3 build file written in the quake extension lan-
guage.
m3overrides- Overrides elements of the m3makefile when building
"local".
SYNOPSIS
m3makefile
DESCRIPTION
When building moderately or very complex software packages, the com-
piler needs help identifying all that needs to happen. This is where
the m3makefile and m3overrides file come into play.
The exporting of packages into the modula-3 system wide (or global)
repository is managed from these files.
Both the m3makefile and m3override files are scripts used in the build-
ing of Modula-3, programs and libraries, and identifying items to be
exported as global entities.
A package may be build as either a "local" or "global" entity. The
m3overrides file is only used when building a "local" or non-exported
entity rather than a "global" or exported package. The compiler switch
-override is used to inform the cm3 compiler to read the m3overrides
file before it reads the m3makefile. Some packages may indicate in
their m3makefiles that they are only local , and are not exported to
the global repository. The main procedure called by the m3overrides
file is override(), as described below.
Both the m3makefile and m3overrides files are written in the quake(7)
extension language and are interpreted by the modula-3 compiler (the
interpreter is built into the cm3(1) compiler).
For both these files, cm3 first defines an additional set of func-
tions/procedures beyond the built-in functions and procedures of the
quake language. These are specific to the tasks of building software.
These tasks are not only building both programs and libraries, but also
documentation and other miscellaneous tasks.
Both these files are located in the " src " directory of your project,
and any nested subdirectory that gets included via include_dir (see
include_dir() below).
PACKAGING
Modula-3 is distributed as a set of packages. Each package is contained
in a single directory which conforms to a standard structure. The top
level directory should contain a README file (or index.html), and a src
subdirectory containing Modula-3 source files, and a derived directory
for each platform on which the package has been built.
The location of public packages, as well as any other variable is spec-
ified in the cm3.cfg configuration file which is located in the same
directory as cm3 executable program. You can move the compiler or the
public packages around, as long as the configuration file stays at the
same directory as the compiler.
The m3makefile, that describes the package, resides in the src subdi-
rectory of the package. Although it is common for all the Modula-3
sources to also reside in the src directory, they may be distributed in
a more complex directory structure rooted at src.
There are three primary types of packages: source, program, and
library. A source package contains a collection of sources, like html
files; it builds nothing. A program package constructs a single exe-
cutable program by compiling and linking the contents of a set of
source packages. Similarly, a library package constructs a single
library from a set of source packages.
Source Packages
The m3makefile for a source package simply lists the pieces of
source that are to be included in programs or libraries that
include the source package.
Program Packages
The m3makefile for a program package names the sources needed to
build the program, and the packages that it uses to satisfy its
imports. It ends with a single program() or Program()
invocation. See the example.
Library Packages
The m3makefile for a library package names the sources to be
included in the library, and the packages that it uses to sat-
isfy its imports. It ends with a single library() or Library()
invocation.
Note that as in a program, all the imports of a package must be
satisfied. If a package A builds a library and any of the
objects in that library import interfaces from another library
package B, then import(B) must be specified in A's m3makefile.
Use cm3 -ship command to install a private package in the public
repository. Note that on some systems, you must have special
privileges to install public packages.
PROCEDURES
SOURCES
The most primitive declarations in an m3makefile are those that iden-
tify source files. They can be Modula-3, C or assembler files. A source
file has three attributes: a package, the subdirectory within the pack-
age where the declaration occurs, and a visibility. The visibility has
two values, visible and hidden. When a package A imports a package B,
only the visible sources in B are available to compilations that occur
in A. By default all sources are visible. However, it is possible to
explicitly control the visibility of Modula-3 interfaces.
Source files are named relative to the m3makefile that mentions them.
interface(X)
declares that the file X.i3 contains an interface.
implementation(X)
declares that the file X.m3 contains a module.
module(X)
declares both the interface X.i3 and the module X.m3.
generic_interface(X)
declares that the file X.ig contains a generic interface.
generic_implementation(X)
declares that the file X.mg contains a generic module.
generic_module(X)
declares both a generic interface and module.
h_source(X)
declares that the file X.h contains a C include file.
c_source(X)
declares that the file X.c contains a C module.
s_source(X)
declares that the file X.s contains an assembly module.
pgm_source(X)
declares that the file X contains compilable source (e.g. .ic,
.mc, .is or .ms files).
With the exception of h_source, each of the procedures above
defines a hidden source file. There are capitalized variants
Interface, Module, Generic_interface, Generic_implementation,
and Generic_module that identify their sources as visible.
Remember, only those interfaces that are marked as visible will
be available to importers of your library or package.
template(X)
declares that the file X.tmpl contains quake code that is to be
included in this build, and in all builds that import this pack-
age.
The template call is used to extend the set of available proce-
dures. For example, the table package includes a template that
defines the table procedure which instantiates the generic table
module.
IMPORT
Import reflects the fact that programs are built from separately com-
piled pieces, rather than being compiled as a whole. If we always com-
piled from source, include would suffice.
import(P)
The library and visible sources of package P are available to
satisfy IMPORT requests in the current compilation. The
imported sources are not recompiled.
import_version(P,BuildDir)
Like import(P), but the library and visible sources of package P
are selected from building directory BuildDir rather than the
default building directory for the current platform.
include_dir(D)
Recursively include the sources named in the m3makefile in sub-
directory D of the current directory.
include_pkg(P)
Include the sources named in package P's src/m3makefile. The
location of P may be overridden.
BUILDING
library(X)
compile the sources accumulated so far and build a library, X,
from the resulting compiled object files. The visibility of the
library is hidden. Library(X) The same as library.
program(X)
constructs an executable program named X from the given sources.
Program(X)
like program, but X is exported to /bin.
build_standalone()
ensures that the program being built does not depend on dynamic
linking and shared libraries. To have an effect, this procedure
must be called before program or Program is called.
COMPILER OPTIONS
m3_option(x)
adds option x to the set of arguments passed to the compiler.
Specifically, m3_option adds x to the M3OPTIONS variable. x should be
a single string preceded with a hyphen, e.g. m3_option(-O).
Some of the more useful compiler options include:
-why Explain why each compilation is needed (default).
-commands Print the compilation commands as they are started.
-verbose Print what happens to each file.
-times Print a breakdown of elapsed time.
-g Generate debugging symbols (default).
-O Optimize code.
-keep Preserve intermediate files.
-once Don't recompile modules with new opaque info.
Any compiler option may be specified here. See cm3(1).
OVERRIDE
override(P,D)
Use the version of package P in directory D/P
instead of the one in /pkg/ P.
override alters the behaviour of the include_pkg and import_pkg
procedures, and must be executed prior to any such calls to have
an effect.
To help ensure that the public repositories are consistent, "cm3
-ship", and the older "m3ship" will refuse to install any pack-
age built using overrides.
When the -override option is specified, cm3 looks for a file
named m3overrides in the src directory and, if one exists, exe-
cutes it immediately prior to executing m3makefile. By keeping
all override calls in an m3overrides file and not in an m3make-
file, you can build both private and public versions of packages
without editting any files.
The overrides in effect when a package was built are automati-
cally carried forward into importers of the package, so there is
no need to restate the complete set of overrides at every level,
only of those packages that are directly imported into a given
package.
There is a pre-declared variable, WDROOT, that defines the con-
ventional location of a user's private package repository. (see
\ref{VAR-sec}).
FOREIGN OBJECTS AND LIBRARIES
These procedures allow foreign objects and/or libraries to be included
in a Modula-3 program. Here foreign means not written in Modula-3.
import_lib(X,P)
If P/libX.a is a library, includes -LP -lX in the final link
command. Otherwise, includes -lX in the final link command.
import_obj(X)
Include X in the final link command.
EXPORTING FILES
These functions should be used to export files to the public directo-
ries. These public directories are bound to actual directories via a
set of logical assignments specific to your installation.
BinExport(X)
exports source file X to /bin.
BindExport(X)
exports derived file X to /bin.
DocExport(X)
exports source file X
to /doc.
DocdExport(X)
exports derived file X to /doc.
EmacsExport(X)
exports source file X to /emacs. EmacsdExport(X) exports
derived file X to /emacs. HtmlExport(X) exports source file X
to /html.
LibExport(X)
exports source file X to /lib.
LibdExport(X)
exports derived file X to /lib.
ManExport(X,sec)
exports source file X.sec to section sec of /man.
MandExport(X,sec)
exports derived file X.sec to section sec of /man.
HIDING AND EXPORTING
The following procedures can be used in two ways. First to provide a
clearer indication of visibility than is given by the capitalization
convention (which exists partly to support old style m3makefiles).
Second, to change the visibility of imported components. Generally,
it's much better to convince the owners of the exporting package to
give their sources the correct visibility rather than overriding their
initial decision.
Hidden programs are not copied to the /bin directory, exported ones
are.
hide_interface(X)
sets the visibility of interface X.i3 to hidden.
export_interface(X)
sets the visibility of interface X.i3 to visible.
There are also variants that hide or export programs and generics,
hide_program, hide_generic_interface, hide_generic_implementation,
export_program, export_generic_interface, and export_generic_implemen-
tation.
INSTALLATION DEPENDENCIES
The builder contains some built-in support for machine and operating
system dependencies. The package structure makes provision for separate
build directories for different machine and operating system combina-
tions. The default behaviour of cm3 is to generate the compiled object
files, libraries and programs in the build directory corresponding to
the machine and operating system on which cm3 is executing.
The following set of variables exist to allow m3makefiles to be parame-
terised by machine and operating system.
INSTALLATION DEPENDENCIES
The builder contains some built-in support for machine and operating
system dependencies. The package structure makes provision for separate
build directories for different machine and operating system combina-
tions. The default behaviour of cm3 is to generate the compiled object
files, libraries and programs in the build directory corresponding to
the machine and operating system on which cm3 is executing.
The following set of variables exist to allow m3makefiles to be parame-
terised by machine and operating system.
TARGET This variable defines the machine type on which the library or
program being built will execute. It is chosen from the standard
set of machine types on which Modula-3 runs. Check the runtime
or cm3 packages for the complete set.
OS_TYPE
This variable defines the operating system under which the
library or program being built will execute. Currently, Modula-3
supports two operating system variants, POSIX and WIN32. The
former breaks down further into specific variants, but this
variation is not made available to clients. [There is a way if
you absolutely need it, see the unix package.]
BUILD_DIR
This names the package sub-directory in which object files,
libraries and programs will be built. It is usually, but not
always, the same as TARGET.
The net effect of the above allows a single package to build a
family of architectural variants, in different build sub-direc-
tories, where each variant uses the same set of m3makefiles,
parameterized by the above variables. If this degree of flexi-
bility is insufficient, then the extra variation must be speci-
fied in a separate package, which can use include_pkg to access
the shared sources.
PKG_USE
This defines the location of the public package repository, e.g.
/proj/m3/pkg or /usr/local/lib/m3/pkg.
WDROOT This defines the standard location for a user's private package
repository, typically $HOME/m3/pkg. This is typically used in
override calls.
TARGET This variable defines the machine type on which the library or
program being built will execute. It is chosen from the standard
set of machine types on which Modula-3 runs. Check the runtime
or cm3 packages for the complete set.
OS_TYPE
This variable defines the operating system under which the
library or program being built will execute. Currently, Modula-3
supports two operating system variants, POSIX and WIN32. The
former breaks down further into specific variants, but this
variation is not made available to clients. [There is a way if
you absolutely need it, see the unix package.]
BUILD_DIR
This names the package sub-directory in which object files,
libraries and programs will be built. It is usually, but not
always, the same as TARGET.
The net effect of the above allows a single package to build a
family of architectural variants, in different build sub-direc-
tories, where each variant uses the same set of m3makefiles,
parameterized by the above variables. If this degree of flexi-
bility is insufficient, then the extra variation must be speci-
fied in a separate package, which can use include_pkg to access
the shared sources.
PKG_USE
This defines the location of the public package repository, e.g.
/proj/m3/pkg or /usr/local/lib/m3/pkg.
WDROOT This defines the standard location for a user's private package
repository, typically $HOME/m3/pkg. This is typically used in
override calls.
MISCELLANEOUS
The declarations in this section are typically only needed by spe-
cialised applications, for example the Modula-3 compiler or other quake
templates.
source(X)
declares that X contains non-compilable source.
derived_interface(X,V)
adds the derived interface X.i3 to the list of files to be com-
piled. V
must be either VISIBLE or HIDDEN to indicate whether the inter-
face should be available to importers outside this package.
derived_implementation(X)
adds the derived module X.m3 to the list of files to be com-
piled.
derived_c(X)
adds the derived C code X.c to the list of files to be compiled.
derived_h(X)
adds the derived include file X.h to the list of include files
available to the compiler.
EMACS SUPPORT
The following functions support building and installing GNU emacs lisp
code.
Gnuemacs(X)
exports source file X.el to /emacs.
CompiledGnuemacs(X)
exports the source file X.el and compiles and exports the
derived file X.elc to /emacs.
GENERICS SUPPORT
Many of the packages that export generic interfaces and modules also
define m3makefile procedures that will instantiate the generic source
and add it to the list of Modula-3 sources to be compiled. The instan-
tiated interfaces and modules are created in the derived directory, so
they won't clutter up your source directory.
array_sort(nm,elt)
instantiates the ArraySort generics to produce nmArraySort.i3
and nmArraySort.m3 which implement a sort for arrays of elt.T
values.
Array_sort(nm,elt)
like array_sort, but also makes the interface available to
importers outside the current package.
list(nm,elt)
instantiates the List generics to produce nmList.i3 and
nmList.m3 which implement linked lists of elt.T values.
List(nm,elt)
like list, but also makes the interface available to importers
outside the current package.
list_sort(nm,elt)
instantiates the ListSort generics to produce nmListSort.i3 and
nmListSort.m3 which implement a sorting procedure for lists of
elt.T
values. This procedure assumes that list(nm,elt) has been
called.
List_sort(nm,elt)
like list_sort, but also makes the interface available to
importers outside the current package.
pqueue(nm,elt)
instantiates the PQueue generics to produce nmPQ.i3 and nmPQ.m3
which implement a priority queue of elt.T values.
Pqueue(nm,elt)
like pqueue, but also makes the interface available to importers
outside the current package.
sequence(nm,elt)
instantiates the Sequence generics to produce nmSeq.i3, nmSe-
qRep.i3 and nmSeq.m3 which implement a sequence of elt.T values.
Sequence(nm,elt)
like sequence, but also makes the interfaces available to
importers outside the current package.
sorted_table(nm,key,value)
instantiates the SortedTable generics to produce nmSortedTbl.i3
and nmSortedTbl.m3
which implement a sorted table mapping from type key.T to
value.T.
Sorted_table(nm,key,value)
like sorted_table, but also makes the interface available to
importers outside the current package.
table(nm,key,value)
instantiates the Table generics to produce nmTbl.i3 and nmTbl.m3
which implement a table mapping from type key.T to value.T.
Table(nm,key,value)
like table, but also makes the interface available to importers
outside the current package.
MANUAL PAGES SUPPORT
The following calls format and install man pages.
manPage(name,sec)
formats man page name.sec.
ManPage(name,sec)
is like manPage, but also exports the man page to section sec of
/man.
ManExport(X,s)
exports source file X.s to section s
of /man without further formatting.
MandExport(X,s)
export derived file X.s to section s of /man without further
formatting.
NETWORK OBJECTS SUPPORT
The following procedures are used to build programs using network
objects.
netobj(X,T)
runs the network objects stub generator on the interface X.i3 to
produce the network object glue needed to manipulate objects of
type X.T. The resulting source files are included in the cur-
rent build.
Netobj(X,T)
Like netobj, but also exports the resulting interface.
RESOURCES
The following procedures support the inclusion of arbitrary data, known
as a resource, in a program. For example an image as a PNG file.
resource(file)
is shorthand for resource_named(file,file).
resource_named(rd,file)
declares that file is a resource file. It will be accessible via
the reader rd if a bundle is built.
bundle(m)
declares that the module m is to be built as a bundle of the
files specified by the prior calls to resource and
resource_named.
EXAMPLE
For example, here's a simple program composed of a main module, an
imported interface and its implementation.
To begin, create a fresh directory for the package and within that
directory, a directory for the source files:
> mkdir hello
> cd hello
> mkdir src
Create the following source files in the src directory:
In the file src/Main.m3:
MODULE Main;
IMPORT A;
BEGIN
A.DoIt ();
END Main.
In the file src/A.i3:
INTERFACE A;
PROCEDURE DoIt ();
END A.
In the file src/A.m3:
MODULE A;
IMPORT Wr, Stdio;
PROCEDURE DoIt () =
<*FATAL ANY*>
BEGIN
Wr.PutText (Stdio.stdout, "Hello world.0);
Wr.Close (Stdio.stdout);
END DoIt;
BEGIN
END A.
In the file src/m3makefile:
import ("libm3")
implementation ("Main")
module ("A")
program ("foo")
Finally, from the package directory, hello, run cm3. This should/will
compile the three source files and link them with the standard
libraries. The derived files will be placed in a directory that names
the architecture. On an Alpha/AXP machine running OSF, the directory is
called ALPHA_OSF. The executable program will be named foo in the
derived directory.
NOTES
The older style of m3makefiles using the capitalization convention is
depreciated, and its use is highly discouraged.
The quake interpreter is built into the CM3 Modula-3 compiler, whereas
it was a separate executable for earlier ones, such as PM3.
The Critical Mass Modula-3 compiler cm3(1), and the man pages for
quake(7).
For a full list of compiler options, please see cm3(1).
For creating network objects see the manpage for stubgen(1).
For a description of how to access resources from your running program,
see the Bundle and Rsrc interfaces, along with the developer tool
program m3bundle(1).
AUTHOR
(man page) Peter Eiserloh (eiserlohpp -at- yahoo.com)