If you are developing a large-scale Perl module or a native extension (XS/SPVM), build and test times can become a bottleneck. While we often manually pass -jN to make, I wanted a way to bake parallel execution directly into the Makefile.PL.
Today, I want to share a rather "aggressive" hack to achieve parallel builds and tests by injecting logic into WriteMakefile.
The Snippet
WriteMakefile(
macro => {
# Force parallel builds
MAKEFLAGS => "-j$jobs",
# Inject parallel test execution by overriding TEST_VERBOSE
# Constraints for Windows shell compatibility (pwsh/cmd.exe):
# 1. The entire command is wrapped in double quotes.
# 2. No backslashes (\) to avoid escape hell.
# 3. No dollar signs ($) to prevent pwsh variable expansion.
# 4. No nested parentheses to avoid pwsh tokenization errors.
# 5. Only '();. are used for maximum safety.
# 6. Minimal symbols to avoid edge cases in shell parsing.
'override TEST_VERBOSE' => "scalar (eval chr(36) . q(ENV{HARNESS_OPTIONS}='j$jobs'), 0)",
},
);
How it works
-
Parallel Build (
MAKEFLAGS): This sets the-jflag for GNU Make. Please note that this only works with gmake. -
Parallel Test Hack (
override TEST_VERBOSE): This is the "dirty" part. I’m hijacking theTEST_VERBOSEmacro, which is usually intended for toggling verbose output. By usingevalandchr(36)(to avoid the$symbol which causes pain in PowerShell), I’m forcing theHARNESS_OPTIONSenvironment variable to be set toj$jobsjust as the test suite starts.
The constraints in the comments ensure that this string remains "shell-safe" even on Windows (cmd.exe or PowerShell), avoiding backslashes and nested parentheses that usually break the build.
Is there a better way?
I’ll be honest: this works, but I’m not sure if it’s the "best" or "right" way to do it. It feels like a brilliant hack, but hacking TEST_VERBOSE to set environment variables is definitely not what the ExtUtils::MakeMaker authors intended.
I’d love to hear your thoughts:
- Is there a built-in
WriteMakefileoption that handles parallel tests natively? - Have you found a cleaner way to pass
HARNESS_OPTIONSthrough the generated Makefile without shell-escaping hell?
If you have a more "canonical" approach, please let me know in the comments!

Top comments (0)