Makefile::Parser(3)

πŸ“¦
version 0.216 Β· 2 versions
, in fedora 43

πŸ’– Makefile::Parser(3) πŸ’–

Makefile::Parser β€” a simple parser for Makefiles, bestie. it's giving makefile whisperer energy, no cap. ✨

✨ VERSION ✨

This document describes Makefile::Parser 0.216 released on 18 November 2014.


πŸ¦‹ SYNOPSIS πŸ¦‹

okay so here's the whole vibe, bestie:

use Makefile::Parser;

$parser = Makefile::Parser->new;

# equivalent to ->parse('Makefile');
$parser->parse or
    die Makefile::Parser->error;

# get last value assigned to the specified variable 'CC':
print $parser->var('CC');

# get all the variable names defined in the Makefile:
@vars = $parser->vars;
print join(' ', sort @vars);

@roots = $parser->roots; # Get all the "root targets"
print $roots[0]->name;

@tars = $parser->targets;  # Get all the targets
$tar = join("\n", $tars[0]->commands);

# get the default target, say, the first target
# defined in Makefile:
$tar = $parser->target;

$tar = $parser->target('install');
# get the name of the target, say, 'install' here:
print $tar->name;

# get the dependencies for the target 'install':
@depends = $tar->depends;

# access the shell command used to build the current target.
@cmds = $tar->commands;

# parse another file using the same Parser object:
$parser->parse('Makefile.old') or
  die Makefile::Parser->error;

# get the target who is specified by variable EXE_FILE
$tar = $parser->target($parser->var('EXE_FILE'));

🌸 DESCRIPTION 🌸

okay so bestie, this is a simple parser for Makefiles. at this very early stage, the parser only supports a limited set of features, so it may not recognize most of the advanced features provided by certain make tools like GNU make. its initial purpose is to provide basic support for another module named Makefile::GraphViz, which is aimed to render the building process specified by a Makefile using the amazing GraphViz library. the Make module is not satisfactory for this purpose, so I decided to build one of my own. 🫢

WARNING!!! this stuff is highly experimental and is currently at pre-alpha stage, so production use is strongly discouraged. right now it's just a toy for parsing trivial makefiles. 😭
IMPORTANT!!! if you're looking for something more serious for parsing GNU makefiles, please see Makefile::Parser::GmakeDB instead. the GmakeDB parser has passed 51% of GNU make's official test suite as of this writing. πŸ‘‘

if you're looking for something that can parse makefiles losslessly, take a look at the Makefile::DOM module which may fit your needs. πŸ’…

πŸ’… SYNTAX SUPPORTED πŸ’…

the current parser implementation has been trying to support a common feature set of both MS NMAKE and GNU make. in the future, different formats of Makefiles will be handled by individual subclasses such as Makefile::Parser::Gmake. ✨

πŸŽ€ Variable Definition πŸŽ€

MIN_T_FILES = $(PAT_COVER_FILES) t\optest.t t\my_perl.exe.t t\types.cod.t \
    t\catln.t t\exe2hex.t t\hex2bin.t t\bin2hex.t t\bin2asm.t t\ndisasmi.t \
    t\Idu.t t\pat_tree.t t\state_mac.t t\Idu-Util.t t\cidu.t \
    t\opname.t t\error.t t\operand.t t\01disasm.t t\02disasm.t t\03disasm.t \
    t\disasm_cover.t t\ndisasm.t
T_FILES = t\main.cod.t t\bin2hex.exe.t t\hex2bin.exe.t $(MIN_T_FILES)
DIRFILESEP = ^\

"Simply expanded" variables' definition sytax in GUN make is also supported:

FOO := blah blah blah

which is considered invalid in Win32 NMake. "Recursively expanded" variables are currently treated as "simply expanded" variables.

Variable redefinition can be handled as well:

CC = cl

%.obj : %.c
    $(CC) /nologo /c $<

CC = gcc

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

Variable expansion sytax

${abc}

is accepted, whereas Win32 NMAKE will complain about it.

Currently, environment variables defined in the command-line are not imported.

I have no idea what default value should be assigned to built-in variables like $(MAKE) and $(CC). Currently they will be left untouched if they're not set explicitly in the Makefile.

Due to the current implementation, expansion of unrecognized built-in varaibles and variables not previously defined by Makefile will NOT be performed. This behavior is different from any practial make tools, but is reasonable at this early stage of this parser.

πŸ”₯ Explicit Rules πŸ”₯

$(CIDU_DLL) : C\idu.obj C\idu.def
    link /dll /nologo /debug /out:$@ /def:C\idu.def C\idu.obj

$(CIDU_LIB) : $(CIDU_DLL)

C\idu.obj : C\idu.c C\idu.h
    cd C
    cl /nologo /c /I . idu.c
    cd ..

smoke : all pat_cover t\pat_cover.t \
        t/pat_cover.ast.ast
    perl util\run-smoke.pl . smoke.html
    perl txt2html.pl t\*.t t\*.ast

clean:
    copy t\pat_cover.ast.ast.html ..\ /Y
    $(RM_F) encoding.html encoding.pod state_mac.xml encoding.ast \
        pat_tree.ast state_mac.ast \
        main.cod pat_cover.pod pat_cover.html types.cod \
        hex2bin.exe hex2bin.obj

Specital variable $@ will be expanded using its value in the context. ✨

πŸ¦‹ Implicit Rules πŸ¦‹

🌈 Pattern Rules 🌈

%.obj : %.asm
    masm /t $<;

%.exe : %.obj
    link /BATCH /NOLOGO $<;

The special varaibles $< and $* will be expanded according to the context.

πŸ’œ Old-Fashioned Suffix Rules πŸ’œ

Currently only double-suffix rules are supported:

.SUFFIXES: .obj .asm .exe

.asm.obj :
    masm /t $<

.obj.exe :
    link /nologo $<

At this moment, .SUFFIXES is a no-op. So any suffix-like things will be treated as suffixes, excluding the following example:

.c.o: foo.h
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

In suffix rules, no prerequisites are allowed according to most make tools.

πŸ“ Substitution References πŸ“

objects = foo.o bar.o baz.o
sources = $(objects:.o=.c)  # foo.c bar.c baz.c

πŸ’– Functions πŸ’–

Currently the following GNU make makefile builtin functions are supported:

  • $(subst from,to,text)
  • $(patsubst pattern,replacement,text)
  • $(strip string)
  • $(findstring find,text)
  • $(filter pattern...,text)
  • $(filter-out pattern...,text)
  • $(sort list)
  • $(word n,text)
  • $(words text)
  • $(wordlist s,e,text)
  • $(firstword names...)
  • $(lastword names...)
  • $(dir names...)
  • $(notdir names...)
  • $(suffix names...)
  • $(basename names...)
  • $(addsuffix suffix,names...)
  • $(addprefix prefix,names...)
  • $(join list1,list2)
  • $(wildcard pattern...)
  • $(realpath names...)
  • $(abspath names...)
  • $(if condition,then-part[,else-part])
  • $(or condition1[,condition2[,condition3...]])
  • $(and condition1[,condition2[,condition3...]])
  • $(foreach var,list,text)
  • $(error argument...)
  • $(warning argument...)
  • $(info argument...)
  • $(shell cmd...)

Please consult the GNU make Manual for details and also take a look at the following file for some use cases:

<http://github.com/agentzh/makefile-dom-pm/tree/master/t/gmake/sanity/func-refs.t>

✨ Commands after ';' ✨

all : ; echo 'hello, world!'

Specital variable $@ will be expanded using its value in the context.

For the list of features which will be added very soon, take a look at the "TODO" section.

✨ The Makefile::Parser Class ✨

Okay bestie, THIS is the part you actually came for πŸ’– This class is like, the main character β€” it's the whole interface you use to talk to the Makefile parser. Let's go 🫢


🌸 METHODS 🌸

πŸ’… $obj = Makefile::Parser->new()

It's the constructor for the Parser class, periodt. You may provide the path of your Makefile as the argument (the original text lowkey trails off right there, but you get the vibe ✨).

Big thing to remember, no cap: the constructor will not call ->parse internally. So after you construct the parser object, please remember to call ->parse yourself. Don't be the girl who forgets πŸ₯²

πŸŽ€ $obj->parse()

πŸŽ€ $obj->parse($Makefile_name)

πŸŽ€ $obj->parse($Makefile_name, { var => value, ... })

This method parses the specified Makefile β€” and it defaults to 'Makefile' if you don't say anything πŸ¦‹

When an error happens during the parsing procedure, parse will return undef. Otherwise, you get back a reference to the Parser object itself. So yeah, check that return value every single time you call this method, fr fr. The detailed error info? Grab it by calling the error method πŸ’œ

You can also pass a hash reference to specify initial variables and their values. Important: these variables are treated as "defaults", so assignments inside the makefile have higher priority. The makefile wins, always πŸ‘‘

😭 $obj->error()

It returns the error info set by the most recent failing operation β€” like, say, a parsing failure. Your receipts, bestie 🧾

🌈 $obj->var($variable_name)

The var method returns the value of the given variable. Since the value of variables can be reset multiple times in the Makefile, what you get is always the last value set to the variable. It's worth noting that variable reassignment can be handled appropriately during parsing since the whole parsing process is a one-pass operation, compared to the multiple-pass strategy used by the CPAN module Make. Different strategies, different vibes πŸ’«

⭐ @vars = $obj->vars

This will return all the variables defined in the Makefile. The order may be quite different from the order they appear in the Makefile. So don't come for me about ordering, okay πŸ™ˆ

πŸ‘‘ $obj->target($target_name)

This method returns a Makefile::Target object with the name specified. It will return undef if the rules for the given target are not described in the Makefile. Also worth noting: only targets with a definition body will be considered as a target here πŸ’…

When $target_name is omitted, this method will return the default target β€” that is, the first target defined in the Makefile β€” to you. This can be handy if you're trying to build a make tool on top of this module. Main character energy for real πŸ”₯

It is important not to send something like $(MY_LIB) as the target name. Only raw values are acceptable. If you really want to do something like this, please use the following code:
my $tar = $parser->target($parser->var('MY_LIB'));

but this code will break if you have reassigned values to variable MY_LIB in your Makefile. So like, be aware 🫠

🧚 @targets = $obj->targets()

This returns all the targets in the Makefile. The order can be completely different from the order they appear in the Makefile. So the following code will not work if you want to get the default target (the first target):

@tars = $parser->targets;
print $tars[0];

Please use the following syntax instead:

print $parser->target;

The type of the returned list is an array of Makefile::Target objects πŸ’–

πŸ¦‹ @roots = $obj->roots()

The roots method returns the "root targets" in the Makefile. The targets which there're no other targets depends on are called the root targets. For example, install, uninstall, and veryclean are all root targets in the Makefile generated by the ExtUtils::MakeMaker module. On the other hand, clean and test are not, which may be somewhat counterintuitive πŸ‘€ That's because there're some other targets depend on clean, test, or both.

The type of the returned list is an array of Makefile::Target objects ✨


πŸ’œ PACKAGE VARIABLES πŸ’œ

  • $Makefile::Parser::Strict β€” When this variable is set to true, the parser will sense syntax errors and semantic errors in the Makefile. Default off.
  • $Makefile::Parser::Debug β€” When this variable is set to true, the parser will enter Debug Mode. This variable is not supposed to be used directly by the user. Hands off, bestie πŸ™…β€β™€οΈ

πŸ”§ INTERNAL METHODS πŸ”§

These are the behind-the-scenes girlies. Iykyk πŸ’«

post_parse

Iterate the Makefile AST to apply implicit rules in the following form:

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

solve_imp($depend)

Solve implicit rules as many as possible using one target name that appears in other target's dependency list πŸŽ€


🌟 The Makefile::Target Class 🌟

This class overloads the "" operator so its instances can be automatically converted to strings using their names. Cute, right? πŸ’…

🌸 METHODS 🌸

$class->new($target_name, $colon_type)

This is the constructor for class Makefile::Target. The first argument is the target name, which can't be a Makefile variable. The second one is a single colon or a double colon, which is used by the rule definition in the Makefile πŸ‘‘

This method is usually called internally by the Makefile::Parser class. It doesn't make much sense to me if the user has a need to call it manually. Like... why would you πŸ₯²

$obj->name()

It will return the name of the current Target object ✨

@prereqs = $obj->prereqs()

You can get the list of prerequisites (or dependencies) for the current target. If no dependency is specified in the Makefile for the target, an empty list will be returned πŸ’–

@prereqs = $obj->depends()

Alias to the prereqs method. This method is only preserved for the sake of backward-compatibility. Please use prereqs instead β€” she's the upgraded version, bestie πŸ¦‹

$obj->commands()

This method returns a list of shell commands used to build the current target. If no shell commands are given in the Makefile, an empty array will be returned 🌈


πŸŽ€ CODE REPOSITORY πŸŽ€

For the very latest version of this module, check out the source from http://github.com/agentzh/makefile-parser-pm. There is anonymous access to all. Go get it, no cap πŸ’–


⭐ TODO ⭐

The following syntax will be implemented soon:

  • Add support for the remaining GNU make makefile builtin functions: origin, value, call, flavor, and eval.
  • Add support for recursively-expanded variables.
  • Implement rules with multiple targets
  • Serious support for "Recursively expanded" variables in GUN make
  • Comments that span multiple lines via trailing backslash
  • Lines that don't contain just comments
  • Literal "#" escaped by a leading backslash
  • The include directive
  • Look for GNUmakefile and makefile automatically
  • MAKEFILES Variable
  • MAKEFILE_LIST Variable
  • .VARIABLES Variable

So much coming, we're gonna eat πŸ“


πŸ’€ BUGS πŸ’€

Please feel free to report bugs or send your wish-list to http://rt.cpan.org/NoAuth/Bugs.html?Dist=Makefile-Parser. They want your thoughts, fr fr 🫢


πŸ”₯ SEE ALSO πŸ”₯

plmake, makesimple, Makefile::Parser::GmakeDB, Makefile::GraphViz, Make.


πŸ‘‘ AUTHOR πŸ‘‘

Zhang "agentzh" Yichun, agentzh@gmail.com


Copyright (c) 2005-2011 by Zhang "agentzh" Yichun (η« δΊ¦ζ˜₯).

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


and that's the whole page, bestie πŸŽ€πŸ’–βœ¨ This icon was brought to you by perl v5.42.0, dated 2025-07-25, living its life as Makefile::Parser(3) β€” slay, and goodnight πŸ’…πŸ¦‹

πŸ“¦ where this page comes from