A target is specified using the target command which, in its
body, lists the operations to run for the target. smake extends Tcl
with several other commands that can be used in Smakefiles. These
commands can be replaced for project-defined extensions in the normal
Tcl way. The list of commands is:
compileCompiles a file.
dependSpecifies a list of targets that the current target depends on.
getTargetsGet a list of targets for the project.
linkLinks several files together.
setRuleDefines a pattern rule for the current module into the hierarchical pattern tree.
upTargetReturns the name of the target one step higher in the target dependency hierarchy.
targetSpecifies a target and commands to be executed for that target in the current module.
targetExistsChecks to see whether a target exists.
compile
compile file1 file2 ...
Compiles specified files.
By default the version provided by smake executes the C compiler
cc and generates object files from the compiled files. The global
variables COptions and Compiler can be used to specify compiler options
and the compiler, respectively.
The command assumes the option format used by the standard UNIX
cc. If the user wishes to compile with a comand using a different
format then they must replace this command with their own routine.
depend
depend <target-list> <Tcl-script>
Specifies that the target on which the current target depends.
Targets are specified in target-list. If any of the targets in the
list have been updated it will execute Tcl-script. If Tcl-script
is executed the variable targetUpdate in the caller's stackframe
will be set to true.
link
link <target> <object-list> <library-list>
Links the specified objects to become target using any possible
libraries specied in library-list.
By default The version provided by smake calls cc with the -o
specified to target, followed by the list of objects. The list of
libraries is specified with -l before each filename. The global variable
LOptions can be used to give a list of options and Linker specifies
the linker to be used.
getTargets
getTarget [pattern]
Get list of targets for this module (at time of calling). If
pattern is specified it returns names of targets that match a glob
pattern, otherwise it returns all targets.
setRule
setRule <pattern> <code>
A rule is a pattern which is applied when a dependency is reached
which has no explicit target defined (with the target command). smake's
rule system allows multiple patterns with the possibility to specify
general cases which have more specific special cases (f.ex. *.c for
the general case and foo*.c for more specific).
patternGlob-style pattern to match when checking rule.
codeCode to evaluate when a target matches the pattern. This will internally be formed into a Tcl proc. The code should return true from this code we declare the target to have updated and false if not.
When a pattern is then searched for the purpose of matching a target, a fairly smart system will be used to find the most specific version of a pattern that will match, and that code will be executed. If there are several equally-specific patterns (or unrelated ones) are found, the code for each will be evaluated. Mostly the pattern matching should follow intuitively but for a detailed description see the section .
Here are some basic examples of how the pattern matching works:
If pattern already matches one previously added, the old one
will be replaced with the new rule.
On startup a single pattern, *, exists. It assumes the searched target is a file (file A) and compares its modification date to the target depending on it (file B). If file A's modification date is later than file B's, or file B doesn't exist, the code returns true (ie. file A has been updated).
For the interested, here is a more detailed description of how the pattern match takes place:
Internally the rule patterns are kept as a tree. This is a tree where more specific glob patterns appear lower down in the tree and equally general patterns appear together in the same node.
To test the relationship between two patterns we compare the pattern, as a literal string, to the pattern in a tree node -- and vice versa. If the literal string glob-matches the pattern in the tree then it goes beneath the existing pattern. If the match works the other way then the pattern will appear higher up in the tree than the existing tree pattern.
If neither pattern matches the other, and the added pattern doesn't match any of the node's siblings, then it becomes a new siblings. If they match each other both ways then it means they are almost the same patterns except possibly that some *s are ?s (or vice versa) in the other pattern. We check for this by counting the amount of ?s and the pattern with more is considered the more specific (and if they have an equal amount they become siblings).
If a pattern matches exactly the one in the tree then the related code is replaced with the one passed as a parameter.
uptarget
uptarget
Returns the target further up in the dependency hierarchy. So
f.ex. if target foo depends on target bar and bar's body is being
executed when uptarget is called, it will return foo.
target
target <target name> <code>
This is used to specify a smake target. code is the code to be
executed when another target depends on target name or when a target
is given to smake as a parameter.
The return value of the target's code block is used by the depend
command to decide whether a target has been updated or not. If true,
the target has been updated. If the target's code block completes
without return being called, the variable targetUpdate is used instead.
This defaults to false, but can be altered by the code block or by
the depend command.
In the body of the code, the target variable contains the name
of the target currently being executed.
Internally the code body is used to create a procedure which is then executed when another target depends on it.
See the setRule command for information on what takes place if
a target cannot be explicitly matched.
targetExists
targetExists <target name>
Returns true if target name exists and false if not.