1
0
Fork
You've already forked make-analyze
0
Extract GNU Make’s real dependency graph as structured data for Zig tools and CLIs. Uses GNU Make itself, so analysis follows real Makefile semantics.
  • Zig 83.6%
  • Nix 9%
  • C 4.7%
  • Python 1.5%
  • Makefile 1.2%
2026年07月12日 11:14:46 +02:00
.agents/skills/session-lessons Add session-lessions skill and add first such documentation 2026年05月19日 17:34:14 +02:00
.zed Add nixfmt as Nix formatter 2026年03月23日 22:55:56 +01:00
build Expand recorded recipes through GNU Make 2026年05月20日 00:29:11 +02:00
docs/agent_sessions Add latest session lessons 2026年07月12日 11:14:46 +02:00
make Remove fatalHook 2026年05月16日 18:08:21 +02:00
nix Add symlink to checkDerivation in the derivations of nix flake check. 2026年07月12日 11:14:46 +02:00
resources Add large-project golden records 2026年05月23日 01:27:55 +02:00
src Add GraphML conversion support 2026年05月30日 20:17:30 +02:00
tests/bins/integration Change node id to <source Makefile>:<target name> format 2026年05月19日 19:53:58 +02:00
.envrc Add nix flake, .gitignore and direnv 2026年02月07日 20:45:32 +01:00
.gitattributes Mark make's code as vendored 2026年02月10日 12:27:54 +01:00
.gitignore Update to Zig 0.16.0 2026年05月03日 23:24:35 +02:00
AGENTS.md Getting macli to consume make 4.4's Makefile 2026年05月19日 19:52:42 +02:00
build.zig Let integration tests be run from Nix 2026年05月17日 11:26:20 +02:00
build.zig.zon Update zig-clap 2026年05月16日 14:49:58 +02:00
flake.lock Update to Zig 0.16.0 2026年05月03日 23:24:35 +02:00
flake.nix Parameterize python packages and make more availble in devshell 2026年07月12日 10:33:27 +02:00
LICENSE Add LICENSE 2026年02月08日 01:51:27 +01:00
README.md Update README.md so that it reflects the current state 2026年05月30日 15:55:19 +02:00

make-analyze

NixCI badge

make-analyze records the dependency graph that GNU Make computes for a Makefile. It is both a command-line tool, macli, and a Zig library, make_analyze, for programs that need to inspect Make-based build graphs without reimplementing Makefile evaluation.

The project is aimed at C and C-adjacent codebases that still use Make, but where other tooling needs a structured view of the build graph.

Manual

Build from source

The project builds with Zig 0.16:

zig build
zig-out/bin/macli --help

The examples below assume macli is on PATH; otherwise use zig-out/bin/macli.

For development, the repository also provides a Nix flake with the pinned Zig toolchain and test dependencies:

nix develop
zig build test

Run without cloning

If you have Nix installed, run the current main branch as a flake directly from Codeberg:

nix run 'https://codeberg.org/Sh4pe/make-analyze/archive/main.tar.gz#default' -- --help

Record a graph

macli record evaluates a Makefile and writes the discovered graph as JSON.

macli record -m Makefile -o graph.json

Useful options:

  • -m, --makefile <path> selects the Makefile to analyze. This option is required.
  • -o, --output <path> writes JSON to a new file. Without it, JSON is printed to stdout.
  • -t, --target <name> analyzes a specific target instead of the default target.
  • --expand-recipes stores recipes after Make variable expansion.

Convert a graph

macli convert converts a recorded JSON graph to another graph format. The format is selected with a subcommand.

To produce Graphviz DOT:

macli convert dot graph.json > graph.dot
dot -Tsvg graph.dot -o graph.svg

To produce a graph-tool .gt file:

macli convert gt graph.json > graph.gt

Useful options:

  • macli convert dot --show-node-ids includes internal node IDs in DOT labels, which is useful when debugging graph merges across recursive Make invocations.

Internal recursive make mode

macli make is an implementation detail used by macli record when it follows recursive Make recipes. It is not intended to be invoked manually.

Testing and reading .gt files

The graph-tool .gt integration check has its own Python environment. To debug it manually, enter the check derivation shell:

nix develop .#checks.x86_64-linux.gt

The pytest suite in that shell expects MA_GT_FIXTURES to point at a directory containing paired JSON and .gt outputs from the macli checks.

How It Works

make-analyze vendors the GNU Make 4.4 C sources and builds them as a static library. Instead of parsing Makefiles independently, the Zig code initializes GNU Make, lets it read and evaluate the Makefile, and then uses GNU Make's own goal, target, and dependency data to traverse the build graph.

That matters because real Makefiles often depend on GNU Make semantics: implicit rules, phony targets, variable expansion, included files, target-specific state, and recursive invocations. Reusing GNU Make keeps analysis close to what make itself would do.

Recursive Make is handled by detecting recipes that GNU Make marks as recursive. When such a recipe is selected for execution, make-analyze forks a child process for that recipe by replacing $(MAKE) with the internal macli make command. The child process analyzes the nested Makefile and sends its graph back to the parent over IPC, where the subgraph is merged into the main graph.

This is intentionally faithful, but it has an important consequence: recursive recipes are executed so their subgraphs can be discovered. Any side effects in those recipes can happen during analysis.

Why?

There are already useful tools around Make graph visualization and debugging, including makefile2graph, remake, and makeppgraph. Those tools are valuable when the goal is to visualize or debug a Make build directly.

make-analyze exists for a different integration point: projects where C code is still built by Make, but higher-level orchestration is done by the Zig build system or another Zig program. In that setting, the build graph is data the host tool wants to consume, not only a picture to inspect.

For complicated Make builds, make-analyze provides the graph structure that a Zig integration can query and transform.

The CLI is the easiest way to record and render graphs, but the core output of this repository is also the make_analyze Zig module. It exposes the graph data structure and analysis entrypoints so other Zig projects can use Make-derived dependency information directly.

Contributing

make-analyze is still incomplete and likely has many bugs, especially on real Makefiles that rely on less common GNU Make behavior. One of the most useful ways to help is to run it against real projects and report bugs here when analysis fails, produces surprising output, or misses part of the build graph.