EXTUTILS::MM_ANY(3perl)
๐ ExtUtils::MM_Any โ Platform-agnostic MM methods ๐
okay so bestie, you've stumbled into ExtUtils::MM_Any(3perl) and honestly? iconic of you. this whole page is the cross-platform glue of MakeMaker and she does NOT get enough credit. let's get into it ๐ซถ
๐ NAME ๐
ExtUtils::MM_Any โ Platform-agnostic MM methods. that's it. that's the name. short, powerful, main character energy โจ
๐ SYNOPSIS ๐
like, read the room first bestie:
FOR INTERNAL USE ONLY!
package ExtUtils::MM_SomeOS;
# Temporarily, you have to subclass both. Put MM_Any first.
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
@ISA = qw(ExtUtils::MM_Any ExtUtils::Unix);
FOR INTERNAL USE ONLY! like actually. this is not for you unless you're writing an MM subclass, no cap ๐
๐ธ DESCRIPTION ๐ธ
FOR INTERNAL USE ONLY! (saying it twice because it's THAT serious ๐ )
ExtUtils::MM_Any is the superclass of the whole ExtUtils::MM_* family. She holds methods that are either inherently cross-platform, or written in a way that works cross-platform. queen behaviour, honestly ๐
so the move is: you subclass off of ExtUtils::MM_Any and ExtUtils::MM_Unix. yes, both. this is a temporary solution. like, is it pretty? no. does it work? yes. moving on ๐ฆ
THIS MAY BE TEMPORARY! screaming this from the rooftops, don't build your whole life on it ๐ญ
๐ ๏ธ METHODS ๐ ๏ธ
any method that's marked Abstract has to be implemented by the subclasses, no exceptions, that's the assignment bestie ๐ช
๐ Cross-platform helper methods
these are the little helpers that make writing cross-platform code not a total nightmare โจ
๐ os_flavor โ Abstract
my @os_flavor = $mm->os_flavor;
@os_flavor is the style of operating system we're on, and it usually lines up with whichever MM_*.pm file is in play.
the first element of @os_flavor is the major family (like Unix, Windows, VMS, OS/2, etcโฆ) and everything after that is sub-families. so like, family name first, then the whole friend group ๐
some examples so you can see the vibe:
Cygwin98 ('Unix', 'Cygwin', 'Cygwin9x')
Windows ('Win32')
Win98 ('Win32', 'Win9x')
Linux ('Unix', 'Linux')
MacOS X ('Unix', 'Darwin', 'MacOS', 'MacOS X')
OS/2 ('OS/2')
this is how you write code for specific styles of OS. and for how to actually use it, see os_flavor_is(). iykyk ๐
๐ os_flavor_is
my $is_this_flavor = $mm->os_flavor_is($this_flavor);
my $is_this_flavor = $mm->os_flavor_is(@one_of_these_flavors);
checks if the current OS is one of the flavors you passed in. so basically "are we on one of these or nah?" ๐ง
it's useful for stuff like this:
if( $mm->os_flavor_is('Unix') ) {
$out = `foo 2>&1`;
}
else {
$out = `foo`;
}
๐ can_load_xs
my $can_load_xs = $self->can_load_xs;
returns true if we can actually load XS. and this matters because miniperl โ the thing used to build XS modules in the core โ cannot load XS. so yeah, this check is doing a lot of heavy lifting ๐ค
๐ can_run
use ExtUtils::MM;
my $runnable = MM->can_run($Config{make});
in scalar context: gives you the full path to the binary you asked for if it was found, or undef if it wasn't. ๐คท
in list context: gives you a list of full paths to all the instances of that binary found in PATH, or an empty list if it wasn't found at all.
she's copied from IPC::Cmd, but modified into a method (and the $INSTANCES capability got removed, rest in peace ๐๏ธ).
๐ can_redirect_error
$useredirect = MM->can_redirect_error;
true if you're on an OS where the qx operator (or backticks) can redirect STDERR onto STDOUT. โจ
๐ is_make_type
my $is_dmake = $self->is_make_type('dmake');
returns true if $self->make is the type you named. the possibilities are:
gmake GNU make
dmake
nmake
bsdmake BSD pmake-derived
๐ can_dep_space
my $can_dep_space = $self->can_dep_space;
returns true if make can handle dependencies that contain a space (probably by quoting them). currently known to be true for GNU make, and false for BSD pmake derivatives. so like, don't expect spaces to just work everywhere bestie ๐
๐ quote_dep
$text = $mm->quote_dep($text);
this method protects Makefile single-value constants (mostly filenames) so that make still treats them as single values โ even when they rudely contain spaces. if the make program being used can't pull that off and your text needs it, it throws an exception. no silent failure here, periodt ๐จ
๐ split_command
my @cmds = $MM->split_command($cmd, @args);
most OSes have a maximum command length they can execute in one go. and large modules can easily blow past that limit like it's nothing. so you gotta chop long commands into a bunch of shorter ones. ๐ฎ๐จ
split_command returns a series of @cmds, each one processing part of the args. together, they process all the arguments. and no individual line in @cmds will be longer than $self->max_exec_len, being careful to account for macro expansion. thoughtful queen โจ
$cmd should include any switches and repeated initial arguments. if it has newlines, those should already be escaped.
if no @args are given, no @cmds come back. simple math ๐
pairs of arguments will always be preserved inside a single command โ that's a heuristic for things like pm_to_blib and pod2man, which work on pairs of arguments. which makes stuff like this totally safe:
$self->split_command($cmd, %pod2man);
๐ make_type
returns a suitable string describing the type of makefile being written. that's it, that's the whole job ๐
๐ stashmeta
my @recipelines = $MM->stashmeta($text, $file);
generates a set of @recipelines that'll result in the literal $text landing in the literal $file once the recipe runs. call it once, with all the text you want in $file. heads up: make macros will not be expanded, so the locations get fixed at configure-time, not at build-time. plan accordingly ๐ฐ๏ธ
๐ echo
my @commands = $MM->echo($text);
my @commands = $MM->echo($text, $file);
my @commands = $MM->echo($text, $file, \%opts);
generates a set of @commands that print $text to a $file. ๐ข
- if
$fileisn't given, output goes toSTDOUT. - if
$opts{append}is true, the$filegets appended to instead of overwritten. default is to overwrite. - if
$opts{allow_variables}is true, make variables of the form$(...)won't be escaped. other$will be. default is to escape all$.
example of it in the wild:
my $make = join '', map "\t$_\n", $MM->echo($text, $file);
๐ wraplist
my $args = $mm->wraplist(@list);
takes an array of items and turns it into a nicely formatted list of arguments. in most cases it's just something like:
FOO \
BAR \
BAZ
clean, readable, we love a formatting queen ๐ธ
๐ maketext_filter
my $filter_make_text = $mm->maketext_filter($make_text);
the text of the Makefile gets run through this method before it hits disk. it gives systems a chance to make portability fixes to the Makefile. by default? it does absolutely nothing. ๐ค
this method is protected and not meant to be called outside of MakeMaker, so don't go poking at it ๐
๐ cd โ Abstract
my $subdir_cmd = $MM->cd($subdir, @cmds);
this generates a make fragment that runs the @cmds in the given $dir. it's the rough equivalent of this, except cross-platform:
cd $subdir && $cmd
right now $dir can only go down one level. "foo" is fine. "foo/bar"? not fine. "../foo"? right out. ๐ซ
the resulting $subdir_cmd has no leading tab and no trailing newline โ which makes it way easier to embed in a make string. for example:
my $make = sprintf <<'CODE', $subdir_cmd;
foo :
$(ECHO) what
%s
$(ECHO) mouche
CODE
๐ oneliner โ Abstract
my $oneliner = $MM->oneliner($perl_code);
my $oneliner = $MM->oneliner($perl_code, \@switches);
this generates a perl one-liner that's safe for whatever platform you're on, based on the given $perl_code and @switches (a -e is assumed), suitable for use in a make target. it handles the proper shell quoting and escapes for you. ๐งโจ
$(PERLRUN) will be used as perl.
any newlines in $perl_code get escaped. leading and trailing newlines get stripped. which makes this idiom so much easier:
my $code = $MM->oneliner(<<'CODE', [...switches...]);
some code here
another line here
CODE
usage might look something like:
# an echo emulation
$oneliner = $MM->oneliner('print "Foo\n"');
$make = '$oneliner > somefile';
dollar signs inside $perl_code get protected from make using the quote_literal method โ unless they're recognised as being a make variable, $(varname), in which case they get left for make to expand. and remember to quote make macros or it might get used as a bareword! like:
# Assign the value of the $(VERSION_FROM) make macro to $vf.
$oneliner = $MM->oneliner('$vf = "$(VERSION_FROM)"');
ngl she's currently very simple, and may get expanded sometime in the future to include more flexible code and switches. we'll see ๐
๐ quote_literal โ Abstract
my $safe_text = $MM->quote_literal($text);
my $safe_text = $MM->quote_literal($text, \%options);
this quotes $text so the shell interprets it literally. ๐
for example, on Unix this would escape any single-quotes in $text and wrap the whole thing in single-quotes.
- if
$options{allow_variables}is true, it leaves'$(FOO)'make variables untouched. - if false, they get escaped like any other
$. - defaults to true.
๐ escape_dollarsigns
my $escaped_text = $MM->escape_dollarsigns($text);
escapes stray $ so they don't get interpreted as make variables. it lets $(...) by. ๐ธ
๐ escape_all_dollarsigns
my $escaped_text = $MM->escape_all_dollarsigns($text);
escapes all $ so they don't get interpreted as make variables. all of them. every last one. ๐ค
๐ escape_newlines โ Abstract
my $escaped_text = $MM->escape_newlines($text);
shell escapes newlines in $text. โ
๐ max_exec_len โ Abstract
my $max_exec_len = $MM->max_exec_len;
calculates the maximum command size the OS can exec. effectively, it's the max size of a shell command line. ๐
๐ make
my $make = $MM->make;
returns the make variant we're generating the Makefile for. it tries to do some normalization on the info coming from %Config or from the user. tidying up, as a treat ๐
๐ฏ Targets
these are the methods that produce make targets. les get it ๐ฅ
๐ฏ all_target
generate the default target all. that's the whole thing bestie ๐
๐ฏ blibdirs_target
my $make_frag = $mm->blibdirs_target;
creates the blibdirs target, which creates all the directories we use inside blib/. ๐
theblibdirs.tstarget is deprecated. depend onblibdirsinstead.
๐ฏ clean (o)
defines the clean target. (the (o) means it lives over in another doc, go peek there ๐)
๐ฏ clean_subdirs_target
my $make_frag = $MM->clean_subdirs_target;
returns the clean_subdirs target. the clean target uses this to call clean on any subdirectories that contain Makefiles. ๐งน
๐ฏ dir_target
my $make_frag = $mm->dir_target(@directories);
generates targets to create the specified directories and set their permission to PERM_DIR.
here's the tea: depending on a directory to just ensure it exists doesn't work great, because the modified time changes way too often. so dir_target() creates a .exists file inside the created directory instead โ and that's what you should depend on. ๐ซถ
for portability, you should use the $(DIRFILESEP) macro rather than a / to separate the directory from the file:
yourdirectory$(DIRFILESEP).exists
๐ฏ distdir
defines the scratch directory target that holds the distribution before tar-ing (or shar-ing) it. ๐ฆ
๐ฏ dist_test
defines a target that produces the distribution in the scratch directory, and runs 'perl Makefile.PL; make ;make test' inside that subdirectory. ๐งช
๐ฏ xs_dlsyms_arg
(more on this one coming up next ๐)
Returns the command-line arg(s) you hand over to the linker for the file that lists dlsyms to export ๐ธ. By default she just gives you back an empty string โ but like, things such as AIX can override it, iykyk.
xs_dlsyms_ext ๐
Returns the file extension for the output file of the xs_make_dlsyms method โ and yes, any "." character is included in that, bestie, don't worry.
xs_dlsyms_extra โจ
Returns whatever extra text needs to be prepended to the $extra argument of xs_make_dlsyms.
xs_dlsyms_iterator ๐ฆ
Iterates over the necessary shared objects, calling the xs_make_dlsyms method for each one with the appropriate arguments. Very for-each core of her.
xs_make_dlsyms
$self->xs_make_dlsyms(
\%attribs, # hashref from %attribs in caller
"$self->{BASEEXT}.def", # output file for Makefile target
'Makefile.PL', # dependency
$self->{NAME}, # shared object's "name"
$self->{DLBASE}, # last ::-separated part of name
$attribs{DL_FUNCS} || $self->{DL_FUNCS} || {}, # various params
$attribs{FUNCLIST} || $self->{FUNCLIST} || [],
$attribs{IMPORTS} || $self->{IMPORTS} || {},
$attribs{DL_VARS} || $self->{DL_VARS} || [],
# optional extra param that will be added as param to Mksymlists
);
Utility method that returns a Makefile snippet to call Mksymlists. She ate that.
dynamic (o)
Defines the dynamic target. Periodt.
makemakerdflt_target
my $make_frag = $mm->makemakerdflt_target
Returns a make fragment with the makemakerdeflt_target specified. This target is the first target in the Makefile, it's the default target, and it just points off to 'all' โ purely in case some make variant gets confused or something gets snuck in before the real 'all' target. Safety-net energy ๐ซถ.
manifypods_target
my $manifypods_target = $self->manifypods_target;
Generates the manifypods target. This one generates man pages from all the POD files in MAN1PODS and MAN3PODS.
metafile_target
my $target = $mm->metafile_target;
Generate the metafile target.
Writes the file META.yml (YAML encoded meta-data) and META.json (JSON encoded meta-data) about the module in the distdir. The format follows Module::Build's as closely as possible. Copying her older sister's homework but making it fashion ๐.
metafile_data
my $metadata_hashref = $mm->metafile_data(\%meta_add, \%meta_merge);
Returns the data which MakeMaker turns into the META.yml file and the META.json file. It is always in version 2.0 of the format, no exceptions.
Values of %meta_add will overwrite any existing metadata in those keys. %meta_merge will be merged with them.
metafile_file
my $meta_yml = $mm->metafile_file(@metadata_pairs);
Turns the @metadata_pairs into YAML.
Heads up bestie ๐ โ this method does NOT implement a complete YAML dumper. It's being limited to dump a hash with values which are strings, undef's or nested hashes and arrays of strings. No quoting/escaping is done. So don't come at her with your chaotic data, she's not ready.
distmeta_target
my $make_frag = $mm->distmeta_target;
Generates the distmeta target to add META.yml and META.json to the MANIFEST in the distdir.
mymeta
my $mymeta = $mm->mymeta;
Generate MYMETA information as a hash โ either from an existing CPAN Meta file (META.json or META.yml) or from internal data. Either way, she delivers ๐.
write_mymeta
$self->write_mymeta( $mymeta );
Write MYMETA information to MYMETA.json and MYMETA.yml. Simple, clean, iconic.
realclean (o)
Defines the realclean target.
realclean_subdirs_target
my $make_frag = $MM->realclean_subdirs_target;
Returns the realclean_subdirs target. The realclean target uses it to call realclean on any subdirectories which contain Makefiles. Recursive queen ๐.
signature_target
my $target = $mm->signature_target;
Generate the signature target.
Writes the file SIGNATURE with cpansign -s.
distsignature_target
my $make_frag = $mm->distsignature_target;
Generates the distsignature target to add SIGNATURE to the MANIFEST in the distdir.
special_targets
my $make_frag = $mm->special_targets
Returns a make fragment containing any targets which have special meaning to make. For example, .SUFFIXES and .PHONY. The VIPs only ๐.
โจ Init methods โจ
Methods which help initialize the MakeMaker object and macros. Glow-up time, bestie.
init_ABSTRACT
$mm->init_ABSTRACT
init_INST
$mm->init_INST;
Called by init_main. Sets up all the INST_* variables โ except the ones related to XS code. Those get handled over in init_xs.
init_INSTALL
$mm->init_INSTALL;
Called by init_main. Sets up all the INSTALL_* variables (except INSTALLDIRS) and *PREFIX.
init_INSTALL_from_PREFIX
$mm->init_INSTALL_from_PREFIX;
init_from_INSTALL_BASE
$mm->init_from_INSTALL_BASE
init_VERSION (Abstract)
$mm->init_VERSION
Initialize macros representing versions of MakeMaker and other tools.
MAKEMAKER: path to the MakeMaker module.MM_VERSION: ExtUtils::MakeMaker VersionMM_REVISION: ExtUtils::MakeMaker version control revision (for backwards compat)VERSION: version of your moduleVERSION_MACRO: which macro represents the version (usually'VERSION')VERSION_SYM: like version but safe for use as an RCS revision numberDEFINE_VERSION:-Dline to set the module version when compilingXS_VERSION: version in your.xsfile. Defaults to$(VERSION)XS_VERSION_MACRO: which macro represents the XS version.XS_DEFINE_VERSION:-Dline to set the xs version when compiling.
Called by init_main.
init_tools
$MM->init_tools();
Initializes the simple macro definitions used by tools_other() and places them in the $MM object. These use conservative cross platform versions and should be overridden with platform specific versions for performance. (Do it for the speed, bestie โ she's asking nicely ๐
.)
Defines at least these macros:
NOOPโ Do nothingNOECHOโ Tell make not to display the command itselfSHELLโ Program used to run shell commandsECHOโ Print text adding a newline on the endRM_Fโ Remove a fileRM_RFโ Remove a directoryTOUCHโ Update a file's timestampTEST_Fโ Test for a file's existenceTEST_Sโ Test the size of a fileCPโ Copy a fileCP_NONEMPTYโ Copy a file if it is not emptyMVโ Move a fileCHMODโ Change permissions on a fileFALSEโ Exit with non-zeroTRUEโ Exit with zeroUMASK_NULLโ Nullify umaskDEV_NULLโ Suppress all command output
init_others
$MM->init_others();
Initializes the macro definitions having to do with compiling and linking used by tools_other() and places them in the $MM object.
If there is no description, its the same as the parameter to WriteMakefile() documented in ExtUtils::MakeMaker.
tools_other
my $make_frag = $MM->tools_other;
Returns a make fragment containing definitions for the macros init_others() initializes.
init_DIRFILESEP (Abstract)
$MM->init_DIRFILESEP;
my $dirfilesep = $MM->{DIRFILESEP};
Initializes the DIRFILESEP macro, which is the separator between the directory and filename in a filepath. ie. / on Unix, \ on Win32 and nothing on VMS.
For example:
# instead of $(INST_ARCHAUTODIR)/extralibs.ld
$(INST_ARCHAUTODIR)$(DIRFILESEP)extralibs.ld
Something of a hack but it prevents a lot of code duplication between MM_* variants. We love a messy shortcut that works ๐ซถ.
Do NOT use this as a separator between directories. Some operating systems use different separators between subdirectories as between directories and filenames (for example: VOLUME:[dir1.dir2]file on VMS). Read it again bestie, this one's important.
init_linker (Abstract)
$mm->init_linker;
Initialize macros which have to do with linking.
PERL_ARCHIVE: path to libperl.a equivalent to be linked to dynamic extensions.PERL_ARCHIVE_AFTER: path to a library which should be put on the linker command line after the external libraries to be linked to dynamic extensions. This may be needed if the linker is one-pass, and Perl includes some overrides for C RTL functions, such asmalloc().EXPORT_LIST: name of a file that is passed to linker to define symbols to be exported.
Some OSes do not need these, in which case leave it blank.
init_platform
$mm->init_platform
Initialize any macros which are for platform specific use only.
A typical one is the version number of your OS specific module. (ie. MM_Unix_VERSION or MM_VMS_VERSION).
init_MAKE
$mm->init_MAKE
Initialize MAKE from either a MAKE environment variable or $Config{make}.
๐ ๏ธ Tools ๐ ๏ธ
A grab bag of methods to generate specific macros and commands. Chaotic, but in a cute way.
manifypods
Defines targets and routines to translate the pods into manpages and put them into the INST_* directories.
POD2MAN_macro
my $pod2man_macro = $self->POD2MAN_macro
Returns a definition for the POD2MAN macro. This is a program which emulates the pod2man utility. You can add more switches to the command by simply appending them on the macro. Cute, right? โจ
Typical usage:
$(POD2MAN) --section=3 --perm_rw=$(PERM_RW) podfile1 man_page1 ...
test_via_harness
my $command = $mm->test_via_harness($perl, $tests);
Returns a $command line which runs the given set of $tests with Test::Harness and the given $perl.
Used on the t/*.t files.
test_via_script
my $command = $mm->test_via_script($perl, $script);
Returns a $command line which just runs a single test without Test::Harness. No checks are done on the results, they're just printed. No notes, just vibes ๐ฆ.
Used for test.pl, since they don't always follow Test::Harness formatting.
tool_autosplit
Defines a simple perl call that runs autosplit. May be deprecated by pm_to_blib soon. RIP bestie, possibly ๐.
arch_check
my $arch_ok = $mm->arch_check(
$INC{"Config.pm"},
File::Spec->catfile($Config{archlibexp}, "Config.pm")
);
A sanity check that what Perl thinks the architecture is and what Config thinks the architecture is are the same. If they're not it will return false and show a diagnostic message. ๐ฉ
When building Perl it will always return true, as nothing is installed yet.
The interface is a bit odd because this is the result of a quick refactoring. Don't rely on it. Fr.
๐ฆ File::Spec wrappers ๐ฆ
ExtUtils::MM_Any is a subclass of File::Spec. The methods noted here override File::Spec.
catfile
File::Spec <= 0.83 has a bug where the file part of catfile is not canonicalized. This override fixes that bug. In her bug-squashing era ๐๐
.
๐ฒ Misc ๐ฒ
Methods I can't really figure out where they should go yet. Respect the honesty, honestly.
find_tests
my $test = $mm->find_tests;
Returns a string suitable for feeding to the shell to return all tests in t/*.t.
find_tests_recursive
my $tests = $mm->find_tests_recursive;
Returns a string suitable for feeding to the shell to return all tests in t/ but recursively. Equivalent to
my $tests = $mm->find_tests_recursive_in('t');
๐ find_tests_recursive_in ๐
my $tests = $mm->find_tests_recursive_in($dir);
okay so bestie hands it a $dir and gets back a string you can literally feed to the shell ๐
and that string will make the shell return, like, all the tests in $dir โ recursively. every last one. she did the walking so you don't have to ๐ซถ
๐งผ extra_clean_files ๐งผ
my @files_to_clean = $MM->extra_clean_files;
gives you back a list of OS-specific files that get yeeted during the clean target โ and these are on top of the usual set, not instead of it. so it's the regular cleanup plus the platform-specific extras. no cap ๐ง
๐ installvars ๐
my @installvars = $mm->installvars;
it's a list of every single INSTALL* variable but with the INSTALL prefix chopped off โ๏ธ super handy when you're looping over them or building related variable sets. it's giving convenience ๐
๐ซ libscan ๐ซ
my $wanted = $self->libscan($path);
you give her the path to a file or a dir, and:
- if we don't want this thing in the library โ she returns an empty string (the vibe check failed, sorry babe ๐)
- otherwise โ she returns the
$pathback to you, unchanged, untouched, exactly as you gave it โจ
and what is this actually for? mainly two little jobs: excluding version control administrative directories from installation, and excluding the base-level README.pod from installation. that's it, that's the whole gig ๐
๐งฑ platform_constants ๐งฑ
my $make_frag = $mm->platform_constants
returns a make fragment that defines all the macros initialized over in init_platform() โ because instead of tossing them into constants(), we keep them here. same macros, different real estate ๐
โจ post_constants (o) โจ
returns an empty string by default, fr. it exists so that overrides from within Makefile.PL can do their thing after all the constants have been defined. it's the after-party ๐
๐ธ post_initialize (o) ๐ธ
also an empty string by default, naturally. used in Makefile.PLs to add some chunk of text to the Makefile after the object is initialized. it's the "okay now I'm awake, here's a thought" hook ๐ญ
๐ postamble (o) ๐
yep, empty string. can be used in Makefile.PLs to write some text to the Makefile right at the very end. the last word. the mic drop ๐ค
๐ AUTHOR ๐
Michael G Schwern <schwern@pobox.com> and the denizens of makemaker@perl.org, with code from ExtUtils::MM_Unix and ExtUtils::MM_Win32. legends, all of them, no notes ๐
and that's the whole page bestie!! this was ExtUtils::MM_Any(3perl) from perl v5.44.0, dated 2026-10-17 โ go forth and Makefile your little heart out ๐โญ periodt ๐
๐ฆ where this page comes from
- arch rolling: perl 5.44.0-1 ยท Artistic-1.0-Perl AND GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms