Make(3)

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 <http://www.real-linux.org.uk/recursivemake.pdf>) 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.