Jon Trulson 97ef0077f0 Squashed 'cde/programs/dtksh/ksh93/' content from commit b16c91f01 | há 2 anos atrás | |
---|---|---|
.. | ||
C+probe | há 2 anos atrás | |
Mamfile | há 2 anos atrás | |
README-mamake.md | há 2 anos atrás | |
RELEASE | há 2 anos atrás | |
ar.ibm.risc | há 2 anos atrás | |
ar.ibm.risc-64 | há 2 anos atrás | |
cc.hp.ia64 | há 2 anos atrás | |
cc.hp.pa | há 2 anos atrás | |
cc.hp.pa64 | há 2 anos atrás | |
cc.ibm.risc | há 2 anos atrás | |
cc.ibm.risc.gcc | há 2 anos atrás | |
cc.lynxos.i386 | há 2 anos atrás | |
cc.lynxos.ppc | há 2 anos atrás | |
cc.mvs.390 | há 2 anos atrás | |
cc.next.i386 | há 2 anos atrás | |
cc.next.m68k | há 2 anos atrás | |
cc.osf.alpha | há 2 anos atrás | |
cc.pentium4 | há 2 anos atrás | |
cc.sco.i386 | há 2 anos atrás | |
cc.sgi.mips2 | há 2 anos atrás | |
cc.sgi.mips3 | há 2 anos atrás | |
cc.sgi.mips3-o32 | há 2 anos atrás | |
cc.sgi.mips4 | há 2 anos atrás | |
cc.sgi.mips4-n32 | há 2 anos atrás | |
cc.specialize | há 2 anos atrás | |
cc.unix.mc68k | há 2 anos atrás | |
cc.unixware.i386 | há 2 anos atrás | |
crossexec.sh | há 2 anos atrás | |
db.c | há 2 anos atrás | |
dl.c | há 2 anos atrás | |
execrate.sh | há 2 anos atrás | |
filter.sh | há 2 anos atrás | |
gdbm.c | há 2 anos atrás | |
gdbm1.c | há 2 anos atrás | |
gdbm2.c | há 2 anos atrás | |
hello.c | há 2 anos atrás | |
hosttype.tst | há 2 anos atrás | |
iconv.c | há 2 anos atrás | |
iffe.sh | há 2 anos atrás | |
iffe.tst | há 2 anos atrás | |
ignore.sh | há 2 anos atrás | |
intl.c | há 2 anos atrás | |
ld.hp.pa | há 2 anos atrás | |
ldd.cygwin.i386 | há 2 anos atrás | |
ldd.darwin | há 2 anos atrás | |
ldd.hp.pa | há 2 anos atrás | |
ldd.ibm.risc | há 2 anos atrás | |
ldd.lynxos | há 2 anos atrás | |
ldd.mvs.390 | há 2 anos atrás | |
ldd.sgi | há 2 anos atrás | |
m.c | há 2 anos atrás | |
m2.c | há 2 anos atrás | |
m3.c | há 2 anos atrás | |
m4.c | há 2 anos atrás | |
m5.c | há 2 anos atrás | |
m6.c | há 2 anos atrás | |
make.probe | há 2 anos atrás | |
mamake.c | há 2 anos atrás | |
mamake.rt | há 2 anos atrás | |
mamake.tst | há 2 anos atrás | |
mamprobe.sh | há 2 anos atrás | |
mkdir.sh | há 2 anos atrás | |
mktest.sh | há 2 anos atrás | |
mprobe.sh | há 2 anos atrás | |
nsl.c | há 2 anos atrás | |
p.c | há 2 anos atrás | |
package.sh | há 2 anos atrás | |
probe.win32 | há 2 anos atrás | |
proto.sh | há 2 anos atrás | |
regress.sh | há 2 anos atrás | |
silent.sh | há 2 anos atrás | |
socket.c | há 2 anos atrás | |
w.c | há 2 anos atrás | |
w2.c | há 2 anos atrás |
MAM (Make Abstract Machine) is a simple rule-based make language
that is implemented in just six four-letter commands and five attributes,
yet allows unlimited flexibility as it can execute arbitrary shell code.
The program implementing MAM, mamake
,
is a portable C90 program written in a single file, mamake.c
.
This allows ksh 93u+m,
or other programs using this build system,
to be built using only a standard C compiler and utilities installation
without any other dependencies or complications.
MAM was designed by Glenn Fowler at AT&T.
The original documentation
for MAM specified a more extensive language than was actually implemented in mamake.c
,
while the ignore
attribute is not documented there.
This file documents the MAM implementation that we are actually using.
mamake
processes make files called Mamfile
.
These were originally generated by a complex AT&T make system called nmake
.
The intention was for mamake
to process generated Mamfiles only
and not for it to replace make
.
Yet, we are using it as our make
in the ksh 93u+m distribution.
nmake
was slow, brittle, and did not work on some modern systems, e.g. macOS.
It was not worth fixing because it is about as complex as ksh itself --
whereas mamake
is simple and portable, and offers all the same flexibility.
Compared to the 2012-08-01 AT&T distribution,
ksh 93u+m made a few minor changes to mamake
that make it easier to maintain Mamfiles by hand:
bin/Mamfile_indent
in the distribution.)MAM commands have the following basic form:
command [ argument [ operand string ] ]
The command name consists of four lower-case letters. Unrecognized commands or attributes are an error. The argument is a single word. The operand string is any arbitrary text until the end of the line.
note
is the comment command and is ignored.
For historical reasons, info
and meta
are also ignored.
make
rule [ attribute ... ]
done
rule [ attribute ... ]
A make
...done
block defines the target rule named rule using the other commands described here.
Unless the virtual
attribute is used, rule names the pathname of the file generated or referenced by the rule.
Dependencies may be defined in two ways:
make
...done
blocks:
the enclosing rule is the parent
and the enclosed *rule*s are the prerequisites.prev
command (see Referencing previously defined rules below)
to reference a previous make
...done
block.
The dependency is defined as if that block were repeated at the prev
command's location.If the block contains one or more exec
commands (see Shell actions below),
the done
command executes the shell script defined by them.
One or more of the following *attribute*s may be specified
by appending them to the make
or done
command:
archive
: Ignored.
Historically used to mark the generation of an ar
(1) archive.dontcare
: Marks files that do not need to exist.
If the file exists then its last-modified timestamp is checked and propagated,
otherwise it is silently ignored.generated
: Marks rules that produce output files generated by a shell action.
The exec
command implicitly assigns this attribute, but it is customary to specify it regardless.ignore
: The timestamp associated with rule is ignored in dependency resolution.implicit
: Marks the current rule as an implicit prerequisite of the enclosing parent rule.
An implicit prerequisite can make the parent rule out of date without triggering the parent action.
Implicit prerequisites usually correspond to #include
prerequisites.
For example, if foo.o
is generated from foo.c
and foo.c
includes foo.h
,
then foo.h
should be marked as an implicit prerequisite of foo.c
so that touching foo.h
does not make foo.c
out of date while making foo.o
out of date.joint
: Ignored.
Historically used to mark one of a group of rules that are built by a single shell action.virtual
: Marks a rule that is not associated with any file.
The commands within are executed every time the Mamfile is processed.
By convention, a virtual rule named all
makes everything,
and a virtual rule named install
performs installation.prev
rule [ attribute ... ]
This command references a rule that has previously been defined by make
...done
,
regardless of block nesting level.
It can be used to make a rule a prerequisite of multiple make
...done
blocks without repeating the rule.
By convention, the *attribute*s of the referenced block are repeated in the prev
command.
However, mamake
ignores anything after rule.
setv
variable [ defaultvalue ]
Defines a new MAM variable, optionally assigning the initial defaultvalue.
If the defaultvalue begins and ends with double quotes ("
), those are discarded.
If the variable already has a value, the setv
command is ignored; assigning a new value is not possible.
When mamake
starts, it imports all environment variables as MAM variables,
so any variable's default value can be overridden by exporting an environment variable by its name.
MAM variables are referenced using the sh-style ${
...}
syntax, though the braces are not optional.
Any reference to an undefined variable is silently left unexpanded (and not replaced by the empty string).
Expansion of MAM variable references is recursive, i.e., the value may itself contain other variable references.
Beware: there is no reference loop detection.
[TODO
: figure out and document advanced expansion syntax supported by substitute()
in mamake.c
]
exec
-
code
One or more exec
commands within a make
...done
block
define a shell script that is executed for rule.
The word following exec
is ignored; by convention it is -
.
Each exec
command appends a line of code to the shell script for the current rule.
It is customary for a rule's exec
commands to be contiguous, but not necessary.
Before adding each line of code to the script,
MAM variable references (see MAM variables above)
are expanded; their literal values are inserted into the code line
(beware: no quoting is applied!).
When mamake
encounters the done
command,
the script is executed by the shell whose path is in the SHELL
environment variable
or, absent that, by /bin/sh
.
The exec
command assigns the generated
attribute to the current rule, even if it was not specified.
bind
-l
libraryname [ dontcare
]
An argument of -l
libraryname (or +l
libraryname)
causes a MAM variable mam_lib
libraryname to be defined (see MAM variables above).
The variable will contain either the compiler argument for linking to the library libraryname
(either the -l
libraryname flag, or the full path in case of a static library)
or, if the dontcare
attribute is specified, possibly the empty string.
This can be used both for AST libraries shipped with the distribution and for system libraries.
If the library file is found in the distribution,
its time stamp is checked and the current target is marked as outdated if it is newer.
There is also a mechanism to communicate library dependency information across Mamfiles and mamake
invocations.
If a file named libraryname in the current directory
or an ${INSTALLROOT}/lib/lib/
libraryname.req
file
exists, mamake
processes each of the words in the form -l
libraryname in its contents
as if they were arguments to bind
commands
and the resulting values are appended to the value of mam_lib
libraryname
as dependencies separated by spaces.
mamake
does not create these dependency files;
they are expected to be generated by Mamfile shell actions (see Shell actions above).
If no such dependency file exists, and the dontcare
attribute is added,
then mamake
compiles a small test program on the fly to check if the library exists;
if this fails, the mam_lib
libraryname variable will be emptied.
Any bind
command whose argument does not start with -l
or +l
is ignored.
[TODO
: bind
is not yet fully understood; more mamake.c
code analysis is required.
In require()
in mamake.c
there is some special handling for dynamic libraries.
Note that the bind
functionality implemented in mamake.c
is completely different from that described in the original documentation.]