Maintain a group files in a consistent state
jmk [ options ] [ target ]*
[Rules] [File Names] [Assignments] [Functions] [Commands] [Rule Patterns] [Special Targets] [File Inclusion] [Conditionals] [Example] [Grammar]jmk is an application which is used to ensure that a set of files is in a consistent state. If jmk detects an inconsistency, it executes commands that correct the inconsistency. The rules used to detect and correct inconsistencies are given in a makefile.
A makefile contains a sequence of statements that are used to build a database of rules. The elements of a makefile rule are targets, prerequisites, and commands. Typically, targets and prerequisites are names of files. A makefile rule is a non-null list of targets terminated by a colon, a list of prerequisites terminated by a semicolon, and optionally, a sequence of commands delimited by curly braces. A rule that keeps file A.class consistent with A.java follows.This rule runs the Java compiler when A.class is older than A.java or nonexistent."A.class": "A.java"; { exec "javac" "-g" "A.java"; }A makefile rule without commands adds prerequisites to the end of a target's list of prerequisites. For each target, only one makefile rule can contain commands.
Internally, there is one rule for each target. The interpretation of a makefile rule depends on whether its target exists. When the target does not exist, each prerequisite is checked for consistency in textual order, and then the rule's commands are executed sequentially. The rule fails if an error is detected while running a command or if the rule has no prerequisites and no commands. A target with no rule implied by the makefile behaves as if it is the target of a rule with no prerequisites and no commands.
When the target exists, the rule's commands are executed only if the target is in an inconsistent state. Its state is consistent if each prerequisite exists and no prerequisite is younger than the target. When the target is in an inconsistent state, each prerequisite that does not exist or is younger is checked for consistency in textual order, and then the rule's commands are executed sequentially. The rule fails if an error is detected while running a command.
File names are given by strings, which are sequences of characters delimited by double quotes. The backslash and double quote character may be included in a string by preceding each character with a backslash.The slash character separates the directory and file components in a file name. When running commands and testing for the existence of files, the slash character is replaced by the character appropriate for the host, which is the first character of the system property
file.separator
.The colon character separates file names in a path list. When running commands and testing for the existence of files, the colon character is replaced by the character appropriate for the host, which is the first character of the system property
path.separator
.To enhance portability, file names should contain only the alphanumeric, the period, the underscore, and the separator characters described above. jmk treats the asterisk and the percent sign characters specially in some contexts, so these should be avoided in file names.
An assignment is used to name a list of strings. An assignment is a identifier and an equal sign, followed by a semicolon terminated expression that denotes a list of strings.After the assignment, a reference to the identifier is replaced by its value. A reference to an unassigned identifier produces the empty list. In the following example, javac is replaced by two strings.javac = "javac" "-g";The replacement of an identifier by its value occurs while reading the makefile and before any rules are interpreted.exec javac "A.java";
A list of strings is transformed by a string function. A string function call is delimited by parenthesis. The first element of the call is the name of the string function. The parameters to the call are comma separated expressions that denote lists of strings. A description of the string functions follow.String function application occurs while reading the makefile and before any rules are interpreted.
- (subst pattern, replacement, list)
- The string function subst produces a list of the same length as list. Each string in the list is the result of replacing every non-overlapping occurrence of pattern by replacement in the corresponding element of list.
For example,
produces the value "jAvA" "clAss".(subst "a", "A", "java" "class")
- (patsubst pattern, replacement, list)
- The string function patsubst produces a list of the same length as list. Each string in list that matches pattern is replaced with replacement. The pattern may contain a percent sign which acts as a wild card, matching any number of any characters within a string. A pattern without the percent sign behaves as if it starts with a percent sign.
If replacement contains any number of percent signs, each is replaced by the text that matched the percent sign in pattern. A replacement without the percent sign behaves as if it starts with a percent sign.
For example,
produces the value "a.o" "b.o".(patsubst ".c", ".o", "a.c" "b.c")
- (cat list)
- The cat string function concatenates all the strings in list. When there are no strings in list, it returns a list with a single null string.
For example,
produces the value "a/b:c/d:e/f".(cat "a/b" ":" "c/d" ":" "e/f")
- (glob list)
- The glob string function expands file names that contain the wild card character asterisk. Each string in list is translated into a file name which uses the host's separators. The file name may contain no more than one wild card, and all file separators in the file name must precede any wild card. A file name with a wild card is expanded into a list of file names from the given directory that match the pattern. A file name is added to the output after replacing the host's separator characters by the generic ones.
For example, if the directory pkg contains two files, "A.java" and "B.java",
produces the value "pkg/A.java" "pkg/B.java".(glob "pkg/*.java")
- (getprop list)
- The string function getprop uses each string in list as a key into the system properties. If the system has a property associated with the key, that string is added to the output after replacing the host's separator characters with the generic ones.
For example,
produces the user's current directory using the generic separators.(getprop "user.dir")
- (join prefixes, suffixes)
- The string function join concatenates each string in prefixes with every string in suffixes.
For example,
produces "A.java" "A.class" "B.java" "B.class".(join "A" "B", ".java" ".class")
- (equal list1, list2)
- The string function equal returns a list containing the string "true" if list1 and list2 are the same, otherwise, it returns the empty list. This function is most often used in the test of a conditional.
For example,
produces "true".(equal "A" "B", "A" "B")
Commands are executed when a target is inconsistent. A command is an operator followed by a semicolon terminated list of operands. An operand is either an expression that denotes a list of strings constructed while reading the makefile, or one of four command variables. The value associated with a command variable is constructed when a rule is interpreted as follows.The generic separators in each operand are replaced by the host's separators before they are given to the operator.
- @
- The @ command variable is replaced by the target of the current rule.
- <
- The < command variable is replaced by the first prerequisite of the rule if there is one, otherwise, it is replaced by the null list.
- ?
- The ? command variable is replaced by the list of prerequisites that are out of date with respect to current target.
- %
- In rules that receive their commands from a rule pattern, the % command variable is replaced by the characters in the target that match the wild card in the rule pattern's target. Otherwise, the % command variable is replaced by the null list.
The operator determines the method invoked on the operands used to implement a command.
The five file operators expand an asterisk in a file name into a list of file names from the given directory that match the pattern. The restrictions on the pattern are the same as the ones for the glob string function. The expansion occurs when the command executes.
- exec
- The exec operator executes a command in a separate process using a Java runtime exec method.
- delete
- The delete file operator deletes the named files.
- mkdir
- The mkdir file operator creates the named directories.
- mkdirs
- The mkdirs file operator creates the named directories, including any necessary parent directories.
- copy
- The copy file operator copies a file.
- rename
- The rename file operator renames a file.
- create
- The create operator creates a file given by its first operand and than writes any remaining operands into the file as separate lines of text.
- note
- The note operator does nothing. It is used to print notes during a make run.
- forname
- The forname operator dynamically loads and executes a Java object provided with the makefile. The first operand must name a class that implements the Operator interface given below.
package edu.neu.ccs.jmk; public interface Operator { String getName(); /** * Execute the operation specified by the operator. * @param args parameters to the operation * @param out place to write messages * @exception CommandFailedException if operation failed */ void exec(String[] args, java.io.PrintWriter out) throws CommandFailedException; }
A target with no commands explicitly given in the makefile may infer commands from rule patterns. Syntactically, a rule pattern is the same as a rule except that the target contains one occurrence of the wild card character, the percent sign. Prerequisites may also contain a wild card character. A rule pattern for Java classes follows.The list of rule patterns are searched in reverse textual order after a makefile has been read. A rule pattern is applicable to a target if the pattern's target is equal to the target after a matching string is substituted for the wild card character. The match is substituted for the wild card characters in the pattern's prerequisites and the prerequisites are added to the front of the target's list of prerequisites. The match is also the value of the percent sign command variable in commands inferred by the pattern."%.class": "%.java"; { exec "javac" "-g" <; }
A makefile rule with the target ".PHONY" declares that its prerequisites are not the names of files. When one of the prerequisites appears as a target, the interpretation of its associated rule always assumes the target does not exist.
The include statement tells jmk to suspend reading the current makefile and read one or more other makefiles before continuing. The statement is a line in the makefile that looks like this:include List ;where List is a list of strings, each is used as a file name.
A conditional causes part of a makefile to be obeyed or ignored depending on the value of a list of strings. An empty list counts as false, and all other values count as true. The syntax is the traditional if-then-else-end syntax, where the else part is optional:if List then Statements endorif List then Statements else Statements endFor example,includes the file "sun.jmk" when running on a Solaris machine.if (equal "Solaris", (getprop "os.name")) then include "sun.jmk"; end
# A makefile file for jmk -- Make in Java javaflags = "-O"; # jmk is in one package. pkg = "edu.neu.ccs.jmk"; srcdir = (subst ".", "/", pkg); # srcs contains all the Java source files. srcs = (glob (join srcdir, "/*.java")); jar = "jmk.jar"; "all": jar; # all is the default target. # The following rule only compiles out of date # source files. Sometimes the clean target # must be used to force the compilation of the # entire system, such as when an inherited class # is changed. jar: srcs; { exec "javac" javaflags ?; exec "jar" "cf" @ "edu"; } # doc is the target for running javadoc. "doc": "docs" "docs/packages.html"; "docs":; { mkdir @; } "docs/packages.html": srcs; { exec "javadoc" "-package" "-d" "docs" pkg; } "clean":; { delete (join srcdir, "/*.class") jar; } ".PHONY": "clean" "doc" "all";
The makefile loader expects input to conform to the grammar given below. Comments start with the sharp sign character (#) and continue to the end of the line. In the grammar, syntactic categories begin with an uppercase letter. The pattern Thing... indicates zero or more Things, and vertical bar indicates alternatives.Makefile -> Statement Statement...
Statement -> Assignment | Rule | Inclusion | Conditional
Assignment -> Identifier = List ;
List -> Item...
Item -> String | Identifier | (Function Arguments
Function -> subst | patsubst | cat | glob | getprop | join | equal
Arguments -> List ) | List , Arguments
Rule -> Item List : List ; Commands
Commands -> | { Command... }
Command -> Operator Operand... ;
Operator -> exec | delete | mkdir | mkdirs | copy | rename | create | note | forname
Operand -> Item | @ | < | ? | %
Inclusion -> include List ;
Conditional -> if List then Statement... Alternative end
Alternative -> | else Statement...
String -> " Characters... "
Identifier -> JavaIdentifier
- -f filename
- Use filename for the makefile. The default is makefile.jmk.
- -d
- Print additional information during a jmk run.
- -n
- Print but do not run commands during a jmk run.
- -w
- Use a window for jmk output.
- -v
- Print the version number.
Window properties are set by placing the file jmk.properties in the class path. The following properties can be set in the properties file.
- jmk.columns: columns
- Create a transcript window that displays columns characters on a line of text.
- jmk.rows: rows
- Create a transcript window that displays rows lines of text.
- jmk.font: font
- Use font as the default font.
Make in Java was inspired by and is loosely based on the Unix make utility. Thanks go to Richard Stallman and Roland McGrath for making the sources and documentation for GNU make available to all.
- [POSIX92]
- IEEE Computer Society. IEEE Standard for Information Technology--Portable Operating System Interface (POSIX)--Part 2: Shell and Utilities, volume 1. Institute of Electrical and Electronics Engineers, Inc., New York, NY, USA, 1992. Std 1003.2-1992. pp. 666-679.
- [StallmanMcGrath96]
- Richard M. Stallman and Roland McGrath. GNU Make. Free Software Foundation, 0.51 edition, 1996.
The jmk program including its sources and documentation is covered by the GNU General Public License.
John D. Ramsdell[Top]