NAME

Mpp::CommandParser - Base class for makepp command parsers

SYNOPSIS

use Mpp::CommandParser;
our @ISA = qw/Mpp::CommandParser/;

DESCRIPTION

Mpp::CommandParser is a base class for makepp(1) command parsers. When used directly, it does nothing except add a dependency on the executable.

The parser for a particular command should derive from this class. The parser should instantiate objects of type Mpp::Scanner for the language(s) of the files that it scans for include directives.

METHODS

new

my $parser=new Mpp::CommandParser($rule, $dir);

Returns a new Mpp::CommandParser object for rule $rule. $dir is the directory (a string) in which the command runs. The derived class may override this method and its parameters.

parse_command

$parser->parse_command($command, $setenv_hash);

Splits the command into words, prints a log message, and calls xparse_command.

add_executable_dependency

Gets called before xparse_command with the first command word as the argument. By default, it adds a dependency on the file given by the word, but only if it contains no shell metacharacters. It then adds runtime dependencies, if any, and calls add_more_executable_dependencies (which the subclass can override) with the directory name of the executable.

input_filename_regexp

$parser->input_filename_regexp($command[0], [qw(.c .C .cpp .cc .c++)]);

Returns a regular expression against which arguments will match if they look like ordinary (positional) input files. This is the common way to pick up custom file suffixes from register_input_suffix statements.

xparse_command

$parser->xparse_command($command_array, $setenv_hash);

The derived class should override this to set the default signature method, to parse the $command_array command and to add the implicit targets and dependencies to $self->rule. $setenv_hash is a hashref indicating the command-line environment settings. (Whether its values have shell variables expanded is not yet guaranteed.)

The current plan is that a new object of this class is created for each command, but that might change in the future. If it does, then this method is responsible for clearing previous command information, such as the include paths.

If the command line contains another command to be parsed, then that can be handled by calling $self->rule->scan_action recursively.

A TRUE return value indicates that some meaningful scanner was successfully employed. An undefined return value is interpretted as a failure. A failure forces the rule to propagate failure status, without attempting to build the target.

rule

my $rule=$parser->rule;

Returns the rule.

dir

my $dir=$parser->dir;

Returns the directory Mpp::File object.

add_dependency

add_optional_dependency

add_simple_dependency

add_target

add_env_dependency

$parser->add_dependency($name);
$parser->add_dependency($finfo, $tag, $src, $incname);
$parser->add_optional_dependency($name, $simple);
$parser->add_simple_dependency($name);
$parser->add_simple_dependency($finfo, $tag, $src, $incname);
$parser->add_target($name);
$parser->add_env_dependency($name);

Add a dependency or target on file $name relative to $self->dir. Returns the Mpp::File object.

The 5-arg versions add a dependency on $finfo, and record the dependency based on $tag, $src, and $incname. $finfo can be undefined, indicating that the file was sought but not found. The 1-arg versions add a dependency on $name (relative to $parser->dirinfo), and record the dependency based on undef, undef, and $name relative to $parser->rule->build_cwd. The 1-arg version of add_dependency is guaranteed either to return a sucessfully built Mpp::File object (possibly nonexistent if it was phony or marked for don't build, etc.) or to die.

add_dependency adds a "meta" dependency (a dependency on which the rule's dependencies might depend), and causes the dependency to be built before returning. If the dependency file was found but couldn't be built, then it dies with "SCAN_FAILED\n". If the dependency wasn't found, then it returns 1.

add_optional_dependency is just like add_dependency, except that no error occurs if the file does not exists and cannot be built. This is useful for adding dependencies on optional initialization files, because the target becomes outdated should the file come into existence. If you pass it a second TRUE argument, then it adds a simple optional dependency instead of a meta dependency.

add_simple_dependency adds a simple dependency, and does not attempt to build the dependency if it doesn't exist.

Even if no actual file dependency is added, calls to add_dependency and add_simple_dependency are recorded for the purposes of caching scanner info, in case the file becomes buildable in subsequent makepp runs.

add_env_dependency adds a dependency on the value of the named environment variable. If $name is of the form /(.+) in (\S+)/, then $1 is a filename to seek in directories given by the value of the environment variable named by $2, split on colons. The rule is then dependent on the name of the first directory in which the file is found or can be built. (This is useful for avoiding rebuilds when a search path changed without affecting where files are found along the search path.)

BUGS

There is no variant of the add_dependency method that doesn't add a dependency if the file doesn't exist and can't be built. (For example, an optional configuration file.) This would be easy to implement, but there aren't any scanners that would use it right now.

FUTURE WORK

Dependencies on the environment should also be captured by xparse_command. I don't know if there is a way to do this at all yet, but in principle it could be added. The $setenv_hash parameter can be used to avoid adding depedencies on variables that are set earlier in the action. For search paths picked up from the environment, it would be a lot more efficient to capture dependencies in the form "rebuild unless file X is picked up from directory Y," rather than "rebuild if the path changed." Also, if we could avoid rebuilding if the file is picked up from a different location but has the same MD5, then that would be cool.

Perhaps there should be a finfo method that just returns file_info($_[0], $self->dirinfo).