Skip to content

Instantly share code, notes, and snippets.

@conundrumer
Created October 3, 2025 15:28
Show Gist options
  • Select an option

  • Save conundrumer/758eaf7ee26f2d1b177377895cda5a74 to your computer and use it in GitHub Desktop.

Select an option

Save conundrumer/758eaf7ee26f2d1b177377895cda5a74 to your computer and use it in GitHub Desktop.
vibemake.py
"""Minimal Make-like build system"""
import os
from pathlib import Path
from typing import Callable, List
class Rule:
def __init__(self, target: str, deps: List[str], recipe: Callable):
self.target = target
self.deps = deps
self.recipe = recipe
def needs_update(self) -> bool:
"""Check if target needs rebuilding"""
if not os.path.exists(self.target):
return True
target_time = os.path.getmtime(self.target)
for dep in self.deps:
if not os.path.exists(dep):
raise FileNotFoundError(f"Dependency not found: {dep}")
if os.path.getmtime(dep) > target_time:
return True
return False
class Make:
def __init__(self):
self.rules = {}
def rule(self, target: str, deps: List[str] = None):
"""Decorator to define a rule"""
deps = deps or []
def decorator(func: Callable):
self.rules[target] = Rule(target, deps, func)
return func
return decorator
def build(self, target: str):
"""Build a target and its dependencies"""
if target not in self.rules:
# Assume it's a source file
if not os.path.exists(target):
raise FileNotFoundError(f"No rule for target: {target}")
return
rule = self.rules[target]
# Build dependencies first
for dep in rule.deps:
self.build(dep)
# Build target if needed
if rule.needs_update():
print(f"Building: {target}")
rule.recipe()
else:
print(f"Up to date: {target}")
"""
Example usage:
mk = Make()
# Simple rule with dependencies
@mk.rule("output.txt", ["input.txt"])
def build_output():
with open("input.txt") as f:
data = f.read().upper()
with open("output.txt", "w") as f:
f.write(data)
# Pattern-like behavior using Python
for src in Path(".").glob("*.c"):
obj = str(src.with_suffix(".o"))
@mk.rule(obj, [str(src)])
def build_obj(s=src, o=obj): # Capture loop vars
print(f"Compiling {s} -> {o}")
# compile(s, o)
# Collect all objects for linking
objs = [str(p.with_suffix(".o")) for p in Path(".").glob("*.c")]
@mk.rule("program", objs)
def link():
print(f"Linking {objs} -> program")
# link(objs, "program")
mk.build("program")
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment