NAME

Make - Pure-Perl implementation of a somewhat GNU-like make.

SYNOPSIS

require Make;
my $make = Make->new;
$make->parse($file)->Make(@ARGV);

# to see what it would have done
print $make->Script(@ARGV);

# to see an expanded version of the makefile
$make->Print(@ARGV);

my $targ = $make->target($name);
my $rule = Make::Rule->new(':', \@prereqs, \@recipe, \@recipe_raw);
$targ->add_rule($rule);
my @rules = @{ $targ->rules };

my @prereqs  = @{ $rule->prereqs };
my @commands = @{ $rule->recipe };

DESCRIPTION

Implements in pure Perl a somewhat GNU-like make, intended to be highly customisable.

Via pure-perl-make Make has built perl/Tk from the MakeMaker generated Makefiles...

MAKEFILE SYNTAX

Broadly, there are macros, directives, and rules (including recipes).

Macros:

varname = value

Directives:

vpath %.c src/%.c
[-]include otherfile.mk # - means no warn on failure to include

Please note the vpath does not have the GNU-make behaviour of discarding the found path if an inferred target must be rebuilt, since this is too non-deterministic / confusing behaviour for this author.

Rules:

target : prerequisite1 prerequisite2[; immediate recipe]
(tab character)follow-on recipe...

Recipe lines can start with @ (do not echo), - (continue on failure).

In addition to traditional

.c.o :
	$(CC) -c ...

GNU make's 'pattern' rules e.g.

%.o : %.c
	$(CC) -c ...

The former gets internally translated to the latter.

METHODS

There are other methods (used by parse) which can be used to add and manipulate targets and their prerequites.

new

Class method, takes pairs of arguments in name/value form. Arguments:

Vars

A hash-ref of values that sets variables, overridable by the makefile.

Jobs

Number of concurrent jobs to run while building. Not implemented.

GNU

If true, then GNUmakefile is looked for first.

FunctionPackages

Array-ref of package names to search for GNU-make style functions. Defaults to Make::Functions.

FSFunctionMap

Hash-ref of file-system functions by which to access the file-system. Created to help testing, but might be more widely useful. Defaults to code accessing the actual local filesystem. The various functions are expected to return real Perl filehandles. Relevant keys: glob, fh_open, fh_write, mtime, file_readable, is_abs.

InDir

Optional. If supplied, will be treated as the current directory instead of the default which is the real current directory.

RecursiveMakeFinders

Array-ref of functions to be called in order, searching an expanded recipe line for a recursive make invocation (cf Recursive Make Considered Harmful) that would run a make in a subdirectory. Each returns either an empty list, or

($dir, $makefile, $vars, $targets)

The $makefile might be <undef>, in which case the default will be searched for. $vars and $targets are array-refs of pairs and strings, respectively. The $targets can be empty.

Defaults to a single, somewhat-suitable, function.

parse

Parses the given makefile. If none or undef, these files will be tried, in order: GNUmakefile if "GNU", makefile, Makefile.

If a scalar-ref, will be makefile text.

Returns the make object for chaining.

Make

Given a target-name, builds the target(s) specified, or the first 'real' target in the makefile.

Print

Print to current select'ed stream a form of the makefile with all variables expanded.

Script

Print to current select'ed stream the equivalent bourne shell script that a make would perform i.e. the output of make -n.

set_var

Given a name and value, sets the variable to that.

May gain a "type" parameter to distinguish immediately-expanded from recursively-expanded (the default).

expand

Uses "subsvars" to return its only arg with any macros expanded.

target

Find or create Make::Target for given target-name.

has_target

Returns boolean on whether the given target-name is known to this object.

targets

List all "real" (non-dot, non-inference) target-names known to this object at the time called, unsorted. Note this might change when Make is called, as targets will be added as part of the dependency-search process.

patrule

Search registered pattern-rules for one matching given target-name. Returns a Make::Rule for that of the given kind, or false.

Uses GNU make's "exists or can be made" algorithm on each rule's proposed requisite to see if that rule matches.

find_recursive_makes

my @found = $make->find_recursive_makes;

Iterate over all the rules, expanding them for their targets, and find any recursive make invocations using the "RecursiveMakeFinders".

Returns a list of array-refs with:

[ $from_target, $rule_index, $line_index, $dir, $makefile, $vars, $targets ]

ATTRIBUTES

These are read-only.

vars

Returns a hash-ref of the current set of variables.

function_packages

Returns an array-ref of the packages to search for macro functions.

fsmap

Returns a hash-ref of the "FSFunctionMap".

as_graph

Returns a Graph::Directed object representing the makefile. Takes options as a hash:

recursive_make

If true (default false), uses "RecursiveMakeFinders" to find recursive make invocations in the current makefile, parses those, then includes them, with an edge created to the relevant target.

no_rules

If true, the graph will only have target vertices, but will be "multiedged". The edges will have an ID of the zero-based index of the rule on the predecessor target, and will have attributes recipe and recipe_raw. Rules with no prerequisites will be indicated with an edge back to the same target.

If false (the default), the vertices are named either target:name (representing Make::Targets) or rule:name:rule_index (representing Make::Rules). The names encoded with "name_encode". Rules are named according to the first (alphabetically) target they are attached to.

The rule vertices have attributes with the same values as the Make::Rule attributes:

recipe
recipe_raw

FUNCTIONS

name_encode

name_decode

my $encoded = Make::name_encode([ 'target', 'all' ]);
my $tuple = Make::name_decode($encoded); # [ 'target', 'all' ]

Uses %-encoding and -decoding to allow % and : characters in components without problems.

parse_makefile

Given a file-handle, returns array-ref of Abstract Syntax-Tree (AST) fragments, representing the contents of that file. Each is an array-ref whose first element is the node-type (comment, include, vpath, var, rule), followed by relevant data.

tokenize

Given a line, returns array-ref of the space-separated "tokens". Also splits on any further args.

subsvars

my $expanded = Make::subsvars(
    'hi $(shell echo there)',
    \@function_packages,
    [ \%vars ],
    $fsmap,
);
# "hi there"

Given a piece of text, will substitute any macros in it, either a single-character macro, or surrounded by either {} or (). These can be nested. Uses the array-ref as a list of hashes to search for values.

If the macro is of form $(varname:a=b), then this will be a GNU (and others) make-style "substitution reference". First "varname" will be expanded. Then all occurrences of "a" at the end of words within the expanded text will be replaced with "b". This is intended for file suffixes.

For GNU-make style functions, see Make::Functions.

DEBUGGING

To see debugging messages on STDERR, set environment variable MAKE_DEBUG to a true value;

BUGS

More attention needs to be given to using the package to write makefiles.

The rules for matching 'dot rules' e.g. .c.o and/or pattern rules e.g. %.o : %.c are suspect. For example give a choice of .xs.o vs .xs.c + .c.o behaviour seems a little odd.

SEE ALSO

pure-perl-make

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html POSIX standard for make

https://www.gnu.org/software/make/manual/make.html GNU make docs

AUTHOR

Nick Ing-Simmons

COPYRIGHT AND LICENSE

Copyright (c) 1996-1999 Nick Ing-Simmons.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.