Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
max-parallel: 4
matrix:
platform: [ubuntu-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
env:
PLATFORM: ${{ matrix.platform }}
steps:
Expand Down
23 changes: 15 additions & 8 deletions pymake/pargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ def usage():
Write the Rules' dependency graph as a GraphViz dot file. (Work in progress.)
--html FILE
Write the Rules' dependency graph as an HTML file. (Work in progress.)
--explain Give a verbose error message for common GNU Make errors.
--output FILE
Rewrite the parsed makefile to FILE.
-S Print the makefile as an S-Expression. (Useful for debugging pymake itself.)
Rewrite the parsed makefile to FILE. Do not execute.
--print-rule
Print the rule and recipes for the target. Do not execute.
-S Print the makefile as an S-Expression. (Useful for debugging pymake itself.) Do not execute.
""")

class Args:
Expand Down Expand Up @@ -108,6 +109,9 @@ def __init__(self):
# -s
self.silent = False

# --print-rule
self.print_rule = False

self.warn_undefined_variables = False
self.detailed_error_explain = False

Expand Down Expand Up @@ -143,17 +147,18 @@ def parse_args(argv):
"help",
"always-make",
"debug=",
"directory=",
"dotfile=",
"html=",
"explain",
"file=", "makefile=",
"output=",
"html=",
"just-print", "dry-run", "recon",
"no-builtin-rules",
"output=",
"print-rule",
"silent", "quiet"
"version",
"warn-undefined-variables",
"directory=",
"just-print", "dry-run", "recon",
"silent", "quiet"
]
)
for opt in optlist:
Expand Down Expand Up @@ -194,6 +199,8 @@ def parse_args(argv):
args.silent = True
elif opt[0] == '--debug':
args.debug_flags = _parse_debug_flags(opt[1])
elif opt[0] == '--print-rule':
args.print_rule = True
else:
# wtf?
assert 0, opt
Expand Down
32 changes: 29 additions & 3 deletions pymake/pymake.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ def get_basename( filename ) :
def _view(token_list):
return "".join([str(t) for t in token_list])

def print_rule_chain(rulesdb, target):

try:
rule = rulesdb.get(target)
except KeyError:
error_message(None, "No rule to make target '%s'" % target)
return -1

print("# {}\n{}".format(rule.get_pos(), rule))
print("{}".format(rule.recipe_list.makefile()))

for t in rule.prereq_list:
try:
print_rule_chain(rulesdb, t)
except KeyError:
error_message(rule.get_pos(), "No rule to make prerequisite target '%s'" % t)

return 0

def _parse_one_vline(virt_line, vline_iter, rules):
logger.debug("parse_vline() rules=%d", rules[0])

Expand Down Expand Up @@ -617,6 +636,7 @@ def execute(makefile, args):
title = get_basename(makefile.get_pos()[0])
rulesdb.html_graph(title + "_makefile", args.htmlfile)
print("wrote %s for html" % args.htmlfile)
return 0

try:
if not target_list:
Expand All @@ -625,6 +645,12 @@ def execute(makefile, args):
error_message(makefile.get_pos(), "No targets" )
return exit_status["error"]

if args.print_rule:
for target in target_list:
print_rule_chain(rulesdb, target)

return exit_status["success"]

#
# At this point, we start executing the makefile Rules.
#
Expand All @@ -651,9 +677,9 @@ def execute(makefile, args):

# walk a dependency tree
for rule in rulesdb.walk_tree(target):
if not rule.recipe_list:
# this warning catches where I fail to find an implicit rule
logger.warning("I didn't find a recipe to build target=\"%s\"", target)
# if not rule.recipe_list:
# # this warning catches where I fail to find an implicit rule
# logger.warning("I didn't find a recipe to build target=\"%s\"", target)

# target specific variables
if rule.assignment_list:
Expand Down
8 changes: 5 additions & 3 deletions pymake/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def __init__(self, target, prereq_list, recipe_list, assignment, pos):

logger.debug("create rule target=%r at %r", target, pos)
self.target = target
self.prereq_list = prereq_list
self.recipe_list = recipe_list
self.prereq_list = list(prereq_list)
self.recipe_list = list(recipe_list)
self.assignment_list = [assignment] if assignment else []

_rule_sanity(pos, prereq_list, assignment)
Expand All @@ -49,7 +49,7 @@ def __init__(self, target, prereq_list, recipe_list, assignment, pos):

def __str__(self):
target = "" if self.target is None else self.target
return "%s <- %s" % (target, ",".join(self.prereq_list))
return "%s : %s" % (target, " ".join(self.prereq_list))

def makefile(self):
s = "".join([ "%s:%s\n" % (self.target,a.makefile()) for a in self.assignment_list])
Expand Down Expand Up @@ -105,6 +105,8 @@ def add(self, target, prereq_list, recipe_list, assignment, pos):

if target == ".PHONY":
raise NotImplementedError(target)
elif target == ".PRECIOUS":
raise NotImplementedError(target)

_rule_sanity(pos, prereq_list, assignment)

Expand Down
2 changes: 1 addition & 1 deletion pymake/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ def save_prereq(token_list):
# found a : on the Rule's right hand side
# static pattern rule, e.g.
# $(objects): %.o: %.c
raise NotImplementedError("static pattern rule")
raise NotImplementedError("static pattern rule at pos=%r" % (vchar.get_pos(),))

elif state==state_backslash :
if not c in eol :
Expand Down
Loading