npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@isopodlabs/make

v0.5.2

Published

A package for reading and running makefiles with TypeScript.

Downloads

59

Readme

@isopodlabs/make

npm version GitHub stars License

A robust TypeScript parser and executor for GNU Makefiles.
View on npmView on GitHub

@isopodlabs/make is a small TypeScript-native library for parsing and executing Makefiles programmatically in Node.js.

  • Parses GNU Make–style syntax.
  • Executes recipes cross‑platform using your system shell.
  • Useful for IDE integrations, build tooling, or testing Makefiles in Node.js.

☕ Support My Work

If you use this package, consider buying me a cup of tea to support future updates!

Installation

npm install @isopodlabs/make

Quick start

import { Makefile } from '@isopodlabs/make';
import { readFile } from 'fs/promises';

async function main() {
  // Load and parse a Makefile
  const mf = await Makefile.parse(await readFile('Makefile', 'utf8'));

  // Run default goal or provide explicit goals
  const changed = await mf.run(['all'], {
    jobs: 4,                                  // run up to 4 jobs in parallel
    mode: 'normal',                           // 'normal' | 'dry-run' | 'question' | 'touch'
    output: s => process.stdout.write(s),     // capture stdout/stderr from recipes
  });

  console.log('did work:', changed);
}

Minimal Makefile example:

.PHONY: all build clean

all: build

build: src/app.c
    @echo compiling $<
    @echo output -> $@

clean:
    -@rm -f build

Features

  • Parser and executor:
    • Makefile parsing and execution.
  • Directives:
    • Conditionals: ifeq, ifneq, ifdef, ifndef, with else/endif.
    • include, -include, and sinclude with search over include dirs.
    • export/unexport and .EXPORT_ALL_VARIABLES.
    • undefine
    • vpath
  • Targets and rules:
    • Static, pattern, and double-colon rules; grouped targets; order-only prerequisites.
    • Legacy suffix rules are recognized and converted.
  • Variables:
    • Recursive (=), simple (:=), conditional (?=), append (+=), shell assignment (!=).
    • Target- and pattern-specific variables.
    • Automatic variables: $@, $<, $^ (deduped), $+ (with duplicates), $|, $?, $*.
    • .EXTRA_PREREQS supported (added prerequisites not reflected in automatic vars).
  • Functions:
    • String and list: subst, patsubst, strip, findstring, filter, filter-out, sort, word, words, wordlist, firstword, lastword, join.
    • Filename: dir, notdir, suffix, basename, addsuffix, addprefix, wildcard, realpath, abspath.
    • Conditionals/logic: if, or, and, intcmp.
    • Variables/meta: value, origin, flavor, call, foreach, let, file, error, warning, info.
    • Also provides shell and eval.
  • Search paths:
    • VPATH and vpath pattern-based file resolution.
  • Special targets (recognized at runtime):
    • .PHONY, .SUFFIXES, .DEFAULT, .PRECIOUS, .INTERMEDIATE, .NOTINTERMEDIATE, .SECONDARY, .SECONDEXPANSION, .DELETE_ON_ERROR, .IGNORE, .LOW_RESOLUTION_TIME, .SILENT, .EXPORT_ALL_VARIABLES, .NOTPARALLEL, .ONESHELL, .POSIX.
  • Recipe flags:
    • - ignore errors, @ silent, + force execution.
    • .ONESHELL or per-call option to run a whole recipe in a single shell.
  • Execution modes:
    • normal, dry-run (print commands), question (returns true if any rebuild is needed), touch (create missing files and update timestamps).
  • Parallelism:
    • jobs option to control concurrency.
    • .NOTPARALLEL serializes prerequisites for affected targets.
    • .WAIT is a pseudo-prerequisite that splits a prerequisite list into serial segments:
      • A: p1 p2 .WAIT p3 p4 runs p1/p2 (in parallel), then p3/p4 (in parallel).

API

Makefile

This class encapsulates a makefile. It provides direct access to these builtin variables:

  • CURDIR
  • RECIPEPREFIX
  • VARIABLES
  • FEATURES
  • INCLUDE_DIRS
  • VPATH
  • SUFFIXES
  • DEFAULT_GOAL

Construction

  • new Makefile(options?:CreateOptions)

    Creates an empty makefile with only the provided variables (plus SHELL, MAKESHELL, MAKE_VERSION, MAKE_HOST) and rules.

  • Makefile.parse(text: string, options?:CreateOptions)

    As above, but also parses the text into the makefile.

  • Makefile.load(filePath: string, options?:CreateOptions)

    Creates a makefile from a file. If options.variables is undefined, the environment variables will be used. Also sets CURDIR and MAKEFILE_LIST.

Methods

  • get(name: string)

    Lookup a variable.

  • setVariable(name: string, op: string, value: string, origin: VariableOrigin)

    Set a variable.

  • setFunction(name: string, fn: Function)

    Override (or add) a function.

  • addRule(rule: RuleEntry)

    Add a rule.

  • parse(text: string, file?: string)

    Parse additional text into the makefile (file is used to improve error messages).

  • run(goals?: string[], options?: RunOptions)

    Make goals using provided options.

  • runDirect(goals: string[] = [], options: RunOptionsDirect)

    Make goals using low-level options.

Create options

See CreateOptions

  • variables: Record<string, VariableValue> initial variables.
  • functions: Record<string, Function> functions to override or augment the standard make functions
  • rules: RuleEntry[] initial ruleset; also used to generate .SUFFIXES.
  • includeDirs: string[] search paths for include.
  • envOverrides whether environment variables take precedence.
  • warnUndef warn when an undefined variable is accessed.
import { Makefile, environmentVariables } from '@isopodlabs/make';

// Parse from text
const mf = await Makefile.parse(text, {
  variables: environmentVariables(),
  includeDirs: ['.vscode', 'config/includes'],   // search paths for include
});

// Or load directly from a path (sets CURDIR/MAKEFILE_LIST appropriately)
const mf2 = await Makefile.load('path/to/Makefile');

Run options

See RunOptions:

  • mode one of normal, dry-run, question, touch
  • jobs number of simultaneous jobs (default 1)
  • output to capture stdout/stderr
  • ignoreErrors, silent, noSilent, oneshell
  • keepGoing, checkSymlink, printDirectory:
  • always, assumeOld, assumeNew: override timestamp checks
  • Special targets like .SILENT, .ONESHELL, .IGNORE, .NOTPARALLEL influence behavior per target (and globally if declared with no prerequisites).
const changed = await mf.run(['target'], {
  jobs: 2,
  mode: 'question', // returns true if any rebuild would occur
  output: s => process.stdout.write(s),
});

See RunOptionsDirect for lower-level control over execution.

Rules

See RuleEntry:

  • targets whitespace-separated list of targets
  • prerequisites whitespace-separated list of prerequisites
  • recipe optional array of strings containing the recipe
  • doubleColon true if it's a doubleColon rule
  • grouped true if the rule is a grouped rule
  • builtin true if the rule is a builtin rule
  • file, lineNo location of definition

CLI

This is an optional sub-module, which:

  • Provides a gnumake-compatible command line interface.
  • Is automatically invoked if run directly from command line.
  • Optionally supplies builtin rules and variables.
  • Can be run programmatically, but note that the first two arguments should be the node executable and the path to the make/cli module.
import { cli } from '@isopodlabs/make/cli';

await cli(process.argv);

Using the cli module's builtinRules and builtinVariables:

import { Makefile, environmentVariables } from '@isopodlabs/make';
import { builtinRules, builtinVariables } from '@isopodlabs/make/cli';

const mf = await Makefile.load('path/to/Makefile', {
	variables: {...builtinVariables(), ...environmentVariables()},
	rules: builtinRules(),
});
mf.run(['all'], {jobs: 6})

Limitations

  • No archive member support (lib.a(member.o), $%), and no jobserver.
  • All rules and variables must be passed to the Makefile constructor (or via Makefile.parse or Makefile.load). The typical rules and variables can be obtained from the CLI component. In particular, variables such as MAKE and MAKEFLAGS are only available if manually provided or when run from the CLI.
  • Special targets with lifecycle semantics are recognized but not fully implemented: .PRECIOUS, .INTERMEDIATE, .NOTINTERMEDIATE, .SECONDARY, .LOW_RESOLUTION_TIME.
  • Requires Node.js, however only index.ts (and the optional cli) rely on any external modules (specifically, path, fs, os, and child_process), so parsing and running makefiles is possible without Node.js.

Contributing

Contributions, bug reports, and feature requests are welcome!
Open an issue or pull request on GitHub.

License

MIT © Adrian Stephens