Credit: Aurelio A. Heckert, CC BY-SA 2.0 , via Wikimedia Commons

Go Ahead ‘make’ My Day (Part III)

This is the last in a 3 part series on Scriptlets. You can catch up by reading our introduction and dissection of Scriptlets.

In this final part, we talk about restraint - the discipline that keeps a clever trick from turning into a maintenance hazard.

That uneasy feeling…

So you are starting to write a few scriptlets and it seems pretty cool. But something doesn’t feel quite right…

You’re editing a Makefile and suddenly you feel anxious. Ah, you expected syntax highlighting, linting, proper indentation, and maybe that warm blanket of static analysis. So when we drop a 20 - line chunk of Perl or Python into our Makefile, our inner OCD alarms go off. No highlighting. No linting. Just raw text.

The discomfort isn’t a flaw - it’s feedback. It tells you when you’ve added too much salt to the soup.

A scriptlet is not a script!

A scriptlet is a small, focused snippet of code embedded inside a Makefile that performs one job quickly and deterministically. The “-let” suffix matters. It’s not a standalone program. It’s a helper function, a convenience, a single brushstroke that belongs in the same canvas as the build logic it supports.

If you ever feel the urge to bite your nails, pick at your skin, or start counting the spaces in your indentation - stop. You’ve crossed the line. What you’ve written is no longer a scriptlet; it’s a script. Give it a real file, a shebang, and a test harness. Keep the build clean.

Why we use them

Scriptlets shine where proximity and simplicity matter more than reuse (not that we can’t throw it in a separate file and include it in our Makefile).

  • Cleanliness: prevents a recipe from looking like a shell script.
  • Locality: live where they’re used. No path lookups, no installs.
  • Determinism: transform well-defined input into output. Nothing more.
  • Portability (of the idea): every CI/CD system that can run make can run a one-liner.

A Makefile that can generate its own dependency file, extract version numbers, or rewrite a cpanfile doesn’t need a constellation of helper scripts. It just needs a few lines of inline glue.

Why they’re sometimes painful

We lose the comforts that make us feel like professional developers:

  • No syntax highlighting.
  • No linting or type hints.
  • No indentation guides.
  • No “Format on Save.”

The trick is to accept that pain as a necessary check on the limits of the scriptlet. If you’re constantly wishing for linting and editor help, it’s your subconscious telling you: this doesn’t belong inline anymore. You’ve outgrown the -let.

When to promote your scriplet to a script

Promote a scriptlet to a full-blown script when:

  • It exceeds 30-50 lines.
  • It gains conditionals or error handling.
  • You need to test it independently.
  • It uses more than 1 or 2 non-core features.
  • It’s used by more than one target or project.
  • You’re debugging quoting more than logic.
  • You’re spending more time fixing indentation, than working on the build

At that point, you’re writing software, not glue. Give it a name, a shebang, and a home in your tools/ directory.

When to keep it inside your Makefile

Keep it inline when:

  • It’s short, pure, and single-use.
  • It depends primarily on the environment already assumed by your build (Perl, Python, awk, etc.).
  • It’s faster to read than to reference.

A good scriptlet reads like a make recipe: do this transformation right here, right now.

define create_cpanfile =
    while (<STDIN>) {
        s/[#].*//; s/^\s+|\s+$//g; next if $_ eq q{};
        my ($mod,$v) = split /\s+/, $_, 2;
        print qq{requires "$mod", "$v";\n};
    }
endef

export s_create_cpanfile = $(value create_cpanfile)

That’s a perfect scriptlet: small, readable, deterministic, and local.

Rule of Thumb: If it fits on one screen, keep it inline. If it scrolls, promote it.

Tools for the OCD developer

If you must relieve the OCD symptoms without promotion of your scriptlet to a script

  • Add a lint-scriptlets target: perl -c -e '$(s_create_requires)' checks syntax without running it.
  • Some editors (Emacs mmm-mode, Vim polyglot) can treat marked sections as sub-languages to enable localized language specific editing features.
  • Use include to include a scriptlet into your Makefile

…however try to resist the urge to over-optimize the tooling. Feeling the uneasiness grow helps identify the boundary between scriptlets and scripts.

You’ve been warned!

Because scriptlets are powerful, flexible, and fast, it’s easy to reach for them too often or make them the focus of your project. They start as a cure for friction - a way to express a small transformation inline - but left unchecked, they can sometimes grow arms and legs. Before long, your Makefile turns into a Frankenstein monster.

The great philosopher Basho (or at least I think it was him) once said:

A single aspirin tablet eases pain. A whole bottle sends you to the hospital.

Thanks for reading.

Learn More


Previous post: Go Ahead ‘make’ My Day (Part II)