ExtUtils::MM_Any - 平台无关的 MM 方法
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);
仅供内部使用!
ExtUtils::MM_Any 是 ExtUtils::MM_* 模块集的超类。它包含一些方法,这些方法要么本质上是跨平台的,要么是以跨平台的方式编写的。
从 ExtUtils::MM_Any 和 ExtUtils::MM_Unix 继承。这是一个临时的解决方案。
这可能是临时的!
任何标记为抽象的方法都必须由子类实现。
这些方法有助于编写跨平台代码。
my @os_flavor = $mm->os_flavor;
@os_flavor 是操作系统类型,通常对应于我们正在使用的 MM_*.pm 文件。
@os_flavor 的第一个元素是主要系列(例如 Unix、Windows、VMS、OS/2 等),其余是子系列。
一些例子
Cygwin98 ('Unix', 'Cygwin', 'Cygwin9x')
Windows ('Win32')
Win98 ('Win32', 'Win9x')
Linux ('Unix', 'Linux')
MacOS X ('Unix', 'Darwin', 'MacOS', 'MacOS X')
OS/2 ('OS/2')
这用于为操作系统类型编写代码。有关使用,请参阅 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);
检查当前操作系统是否属于给定的类型之一。
这对于像这样的代码很有用
if( $mm->os_flavor_is('Unix') ) {
$out = `foo 2>&1`;
}
else {
$out = `foo`;
}
my $can_load_xs = $self->can_load_xs;
如果我们有能力加载 XS,则返回 true。
这很重要,因为用于在核心代码中构建 XS 模块的 miniperl 无法加载 XS。
use ExtUtils::MM;
my $runnable = MM->can_run($Config{make});
如果在标量上下文中调用,它将返回找到的二进制文件的完整路径,如果未找到,则返回 undef
。
如果在列表上下文中调用,它将返回在 PATH
中找到的二进制文件实例的完整路径列表,如果未找到,则返回空列表。
从 IPC::Cmd 复制而来,但修改为方法(并删除了 $INSTANCES
功能)。
$useredirect = MM->can_redirect_error;
如果在 qx 运算符(或反引号)可以将 STDERR
重定向到 STDOUT
的操作系统上,则为真。
my $is_dmake = $self->is_make_type('dmake');
如果 $self->make
是给定的类型,则返回真;可能性是
gmake GNU make
dmake
nmake
bsdmake BSD pmake-derived
my $can_dep_space = $self->can_dep_space;
如果 make
可以处理(可能通过引用)包含空格的依赖项,则返回真。目前已知 GNU make 为真,BSD pmake 衍生版本为假。
$text = $mm->quote_dep($text);
保护 Makefile 单值常量(主要是文件名)的方法,以便 make 即使它们不方便地包含空格,仍然将它们视为单值。如果正在使用的 make 程序无法实现这种保护,并且给定的文本需要它,则会抛出异常。
my @cmds = $MM->split_command($cmd, @args);
大多数操作系统都有一个最大命令长度,它们可以一次执行。大型模块可以轻松地生成远远超过该限制的命令。有必要将长命令拆分为一系列较短的命令。
split_command
将返回一系列 @cmds,每个 @cmds 处理 args 的一部分。它们将共同处理所有参数。@cmds 中的每条单独行都不会超过 $self->max_exec_len,同时注意宏扩展。
$cmd 应包含任何开关和重复的初始参数。
如果没有给出 @args,则不会返回 @cmds。
参数对将始终保存在单个命令中,这是一种针对 pm_to_blib 和 pod2man 之类对参数对起作用的启发式方法。这使得以下内容安全
$self->split_command($cmd, %pod2man);
返回一个合适的字符串,描述正在编写的 Makefile 的类型。
my @recipelines = $MM->stashmeta($text, $file);
生成一组 @recipelines
,这些 @recipelines
将导致字面量 $text
在执行配方时最终出现在字面量 $file
中。调用它一次,使用您想要在 $file
中的所有文本。Make 宏不会扩展,因此位置将在配置时固定,而不是在构建时固定。
my @commands = $MM->echo($text);
my @commands = $MM->echo($text, $file);
my @commands = $MM->echo($text, $file, \%opts);
生成一组 @commands,这些 @commands 将 $text 打印到 $file。
如果没有给出 $file,则输出将转到 STDOUT。
如果 $opts{append} 为真,则 $file 将被追加而不是覆盖。默认情况下是覆盖。
如果 $opts{allow_variables} 为真,则形式为 $(...)
的 make 变量将不会被转义。其他 $
将被转义。默认情况下是转义所有 $
。
使用示例
my $make = join '', map "\t$_\n", $MM->echo($text, $file);
my $args = $mm->wraplist(@list);
将项目数组转换为格式良好的参数列表。 在大多数情况下,这仅仅是类似于
FOO \
BAR \
BAZ
my $filter_make_text = $mm->maketext_filter($make_text);
在写入磁盘之前,Makefile 的文本将通过此方法运行。 它允许系统有机会对 Makefile 进行可移植性修复。
默认情况下,它什么也不做。
此方法受保护,不打算在 MakeMaker 之外调用。
my $subdir_cmd = $MM->cd($subdir, @cmds);
这将生成一个 make 片段,它在给定的 $dir 中运行 @cmds。 粗略等效于此,但跨平台。
cd $subdir && $cmd
目前 $dir 只能向下移动一级。 "foo" 很好。 "foo/bar" 不行。 "../foo" 就更不行了。
生成的 $subdir_cmd 没有前导制表符或尾随换行符。 这使得它更容易嵌入到 make 字符串中。 例如。
my $make = sprintf <<'CODE', $subdir_cmd;
foo :
$(ECHO) what
%s
$(ECHO) mouche
CODE
my $oneliner = $MM->oneliner($perl_code);
my $oneliner = $MM->oneliner($perl_code, \@switches);
这将根据给定的 $perl_code 和 @switches(假设为 -e)生成一个适合在 make 目标中使用的 perl 单行命令,该命令对您所在的特定平台安全。 它将使用正确的 shell 引号和转义符。
$(PERLRUN) 将用作 perl。
$perl_code 中的任何换行符都将被转义。 前导和尾随换行符将被剥离。 使这个习语更容易
my $code = $MM->oneliner(<<'CODE', [...switches...]);
some code here
another line here
CODE
用法可能是这样的
# an echo emulation
$oneliner = $MM->oneliner('print "Foo\n"');
$make = '$oneliner > somefile';
$perl_code 中的美元符号将使用 quote_literal
方法来保护免受 make 的影响,除非它们被识别为 make 变量 $(varname)
,在这种情况下,它们将保留下来供 make 展开。 请记住引用 make 宏,否则它可能会被用作裸词。 例如
# Assign the value of the $(VERSION_FROM) make macro to $vf.
$oneliner = $MM->oneliner('$vf = "$(VERSION_FROM)"');
它目前非常简单,可能会在图中扩展以包含更灵活的代码和开关。
my $safe_text = $MM->quote_literal($text);
my $safe_text = $MM->quote_literal($text, \%options);
这将引用 $text,以便它在 shell 中被逐字解释。
例如,在 Unix 上,这将转义 $text 中的任何单引号,并在整个内容周围加上单引号。
如果 $options{allow_variables} 为真,它将保留 '$(FOO)'
make 变量不变。 如果为假,它们将像其他 $
一样被转义。 默认值为真。
my $escaped_text = $MM->escape_dollarsigns($text);
转义多余的 $
,以便它们不被解释为 make 变量。
它允许通过 $(...)
。
my $escaped_text = $MM->escape_all_dollarsigns($text);
转义所有 $
,以防止它们被解释为 make 变量。
my $escaped_text = $MM->escape_newlines($text);
在 $text 中转义换行符。
my $max_exec_len = $MM->max_exec_len;
计算操作系统可以执行的最大命令大小。实际上,这是 shell 命令行的最大大小。
my $make = $MM->make;
返回我们为其生成 Makefile 的 make 变体。这尝试对来自 %Config 或用户的信息进行一些规范化。
这些是生成 make 目标的方法。
生成默认目标 'all'。
my $make_frag = $mm->blibdirs_target;
创建 blibdirs 目标,该目标创建我们在 blib/ 中使用的所有目录。
blibdirs.ts 目标已弃用。依赖 blibdirs 而不是它。
定义 clean 目标。
my $make_frag = $MM->clean_subdirs_target;
返回 clean_subdirs 目标。clean 目标使用它来对包含 Makefile 的任何子目录调用 clean。
my $make_frag = $mm->dir_target(@directories);
生成目标以创建指定的目录并将它的权限设置为 PERM_DIR。
因为依赖于目录只是为了确保它存在并不太好(修改时间变化太频繁),所以 dir_target() 在创建的目录中创建了一个 .exists 文件。你应该依赖于它。为了可移植性,你应该使用 $(DIRFILESEP) 宏而不是 '/' 来分隔目录和文件。
yourdirectory$(DIRFILESEP).exists
定义一个临时目录目标,该目标将在 tar(或 shar)之前保存分发。
定义一个目标,该目标在临时目录中生成分发,并在该子目录中运行 'perl Makefile.PL; make ;make test'。
返回用于文件列表 dlsyms 导出到链接器的命令行参数。默认返回空字符串,可以被例如 AIX 覆盖。
返回 xs_make_dlsyms
方法的输出文件的扩展名,包括任何 "." 字符。
返回要附加到 xs_make_dlsyms
的 $extra
参数的任何额外文本。
迭代必要的共享对象,为每个对象调用 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
);
实用程序方法,返回调用 Mksymlists
的 Makefile 代码段。
定义动态目标。
my $make_frag = $mm->makemakerdflt_target
返回包含 makemakerdeflt_target 的 make 片段。此目标是 Makefile 中的第一个目标,是默认目标,仅在任何 make 变体出现混淆或在实际 'all' 目标之前插入任何内容时指向 'all'。
my $manifypods_target = $self->manifypods_target;
生成 manifypods 目标。此目标从 MAN1PODS 和 MAN3PODS 中的所有 POD 文件生成手册页。
my $target = $mm->metafile_target;
生成 metafile 目标。
在 distdir 中写入关于模块的 META.yml(YAML 编码元数据)和 META.json(JSON 编码元数据)文件。格式尽可能遵循 Module::Build 的格式。
my $metadata_hashref = $mm->metafile_data(\%meta_add, \%meta_merge);
返回 MakeMaker 转换为 META.yml 文件和 META.json 文件的数据。它始终是格式的 2.0 版。
%meta_add 的值将覆盖这些键中任何现有的元数据。%meta_merge 将与它们合并。
my $meta_yml = $mm->metafile_file(@metadata_pairs);
将 @metadata_pairs 转换为 YAML。
此方法没有实现完整的 YAML 转储器,仅限于转储一个哈希,其值是字符串、undef 或嵌套的哈希和字符串数组。没有进行任何引用/转义。
my $make_frag = $mm->distmeta_target;
生成 distmeta 目标,将 META.yml 和 META.json 添加到 distdir 中的 MANIFEST 中。
my $mymeta = $mm->mymeta;
从现有的 CPAN 元数据文件 (META.json 或 META.yml) 或内部数据生成 MYMETA 信息作为哈希。
$self->write_mymeta( $mymeta );
将 MYMETA 信息写入 MYMETA.json 和 MYMETA.yml。
定义 realclean 目标。
my $make_frag = $MM->realclean_subdirs_target;
返回 realclean_subdirs 目标。这由 realclean 目标用于对包含 Makefile 的任何子目录调用 realclean。
my $target = $mm->signature_target;
生成签名目标。
使用 "cpansign -s" 写入文件 SIGNATURE。
my $make_frag = $mm->distsignature_target;
生成 distsignature 目标,将 SIGNATURE 添加到 distdir 中的 MANIFEST。
my $make_frag = $mm->special_targets
返回包含对 make 具有特殊意义的任何目标的 make 片段。例如,.SUFFIXES 和 .PHONY。
帮助初始化 MakeMaker 对象和宏的方法。
$mm->init_ABSTRACT
$mm->init_INST;
由 init_main 调用。设置所有 INST_* 变量,除了与 XS 代码相关的变量。这些在 init_xs 中处理。
$mm->init_INSTALL;
由 init_main 调用。设置所有 INSTALL_* 变量(除了 INSTALLDIRS)和 *PREFIX。
$mm->init_INSTALL_from_PREFIX;
$mm->init_from_INSTALL_BASE
$mm->init_VERSION
初始化表示 MakeMaker 和其他工具版本的宏
MAKEMAKER:MakeMaker 模块的路径。
MM_VERSION:ExtUtils::MakeMaker 版本
MM_REVISION:ExtUtils::MakeMaker 版本控制修订版(用于向后兼容)
VERSION:模块的版本
VERSION_MACRO:哪个宏表示版本(通常是 'VERSION')
VERSION_SYM:与版本类似,但可以安全地用作 RCS 修订版号
DEFINE_VERSION:-D 行,用于在编译时设置模块版本
XS_VERSION:.xs 文件中的版本。默认为 $(VERSION)
XS_VERSION_MACRO:哪个宏表示 XS 版本。
XS_DEFINE_VERSION:-D 行,用于在编译时设置 xs 版本。
由 init_main 调用。
$MM->init_tools();
初始化 tools_other() 使用的简单宏定义,并将它们放置在 $MM 对象中。这些使用保守的跨平台版本,应使用特定于平台的版本来覆盖以提高性能。
至少定义以下宏。
Macro Description
NOOP Do nothing
NOECHO Tell make not to display the command itself
SHELL Program used to run shell commands
ECHO Print text adding a newline on the end
RM_F Remove a file
RM_RF Remove a directory
TOUCH Update a file's timestamp
TEST_F Test for a file's existence
TEST_S Test the size of a file
CP Copy a file
CP_NONEMPTY Copy a file if it is not empty
MV Move a file
CHMOD Change permissions on a file
FALSE Exit with non-zero
TRUE Exit with zero
UMASK_NULL Nullify umask
DEV_NULL Suppress all command output
$MM->init_others();
初始化与工具_other()使用的编译和链接相关的宏定义,并将它们放置在$MM对象中。
如果没有描述,则与ExtUtils::MakeMaker中记录的WriteMakefile()的参数相同。
my $make_frag = $MM->tools_other;
返回一个包含init_others()初始化的宏定义的make片段。
$MM->init_DIRFILESEP;
my $dirfilesep = $MM->{DIRFILESEP};
初始化DIRFILESEP宏,它是文件路径中目录和文件名之间的分隔符。例如,在Unix上为/,在Win32上为\,在VMS上为空。
例如
# instead of $(INST_ARCHAUTODIR)/extralibs.ld
$(INST_ARCHAUTODIR)$(DIRFILESEP)extralibs.ld
这有点像黑客,但它避免了MM_*变体之间的大量代码重复。
不要将此用作目录之间的分隔符。一些操作系统在子目录之间使用不同的分隔符,以及在目录和文件名之间(例如:VMS上的VOLUME:[dir1.dir2]file)。
$mm->init_linker;
初始化与链接相关的宏。
PERL_ARCHIVE: 与动态扩展链接的libperl.a等效路径。
PERL_ARCHIVE_AFTER: 与动态扩展链接的外部库之后应放在链接器命令行上的库路径。如果链接器是一次性链接器,并且Perl包含一些对C RTL函数的覆盖,例如malloc(),则可能需要这样做。
EXPORT_LIST: 传递给链接器以定义要导出的符号的文件名。
某些操作系统不需要这些,在这种情况下将其留空。
$mm->init_platform
初始化任何仅供平台特定使用的宏。
一个典型的例子是您特定于操作系统的模块的版本号。(例如,MM_Unix_VERSION或MM_VMS_VERSION)。
$mm->init_MAKE
从MAKE环境变量或$Config{make}初始化MAKE。
一个用于生成特定宏和命令的方法集合。
定义目标和例程,将pod转换为手册页并将它们放入INST_*目录。
my $pod2man_macro = $self->POD2MAN_macro
返回POD2MAN宏的定义。这是一个模拟pod2man实用程序的程序。您可以通过简单地在宏上追加来添加更多开关到命令。
典型用法
$(POD2MAN) --section=3 --perm_rw=$(PERM_RW) podfile1 man_page1 ...
my $command = $mm->test_via_harness($perl, $tests);
返回一个 $command 行,该行使用 Test::Harness 和给定的 $perl 运行给定的 $tests 集。
用于 t/*.t 文件。
my $command = $mm->test_via_script($perl, $script);
返回一个 $command 行,该行只运行单个测试,不使用 Test::Harness。不会对结果进行检查,只会打印结果。
用于 test.pl,因为它们并不总是遵循 Test::Harness 格式。
定义一个简单的 perl 调用,运行 autosplit。可能很快就会被 pm_to_blib 弃用。
my $arch_ok = $mm->arch_check(
$INC{"Config.pm"},
File::Spec->catfile($Config{archlibexp}, "Config.pm")
);
一个健全性检查,检查 Perl 认为的体系结构和 Config 认为的体系结构是否相同。如果不相同,它将返回 false 并显示诊断消息。
在构建 Perl 时,它将始终返回 true,因为还没有安装任何东西。
接口有点奇怪,因为这是快速重构的结果。不要依赖它。
ExtUtils::MM_Any 是 File::Spec 的子类。这里提到的方法覆盖了 File::Spec。
File::Spec <= 0.83 存在一个 bug,即 catfile 的文件部分没有规范化。此覆盖修复了该 bug。
我无法确定这些方法应该放在哪里。
my $test = $mm->find_tests;
返回一个适合馈送到 shell 的字符串,以返回 t/*.t 中的所有测试。
my $tests = $mm->find_tests_recursive;
返回一个适合馈送到 shell 的字符串,以返回 t/ 中的所有测试,但递归地。等同于
my $tests = $mm->find_tests_recursive_in('t');
my $tests = $mm->find_tests_recursive_in($dir);
返回一个适合馈送到 shell 的字符串,以返回 $dir 中的所有测试,递归地。
my @files_to_clean = $MM->extra_clean_files;
返回一个列表,其中包含在 clean 目标中要删除的特定于操作系统的文件,除了通常的集合之外。
my @installvars = $mm->installvars;
所有 INSTALL* 变量的列表,不带 INSTALL 前缀。对于迭代或构建相关变量集很有用。
my $wanted = $self->libscan($path);
接受一个文件或目录的路径,如果我们不想将此文件包含在库中,则返回一个空字符串。否则,它将返回未更改的 $path。
主要用于从安装中排除版本控制管理目录和基本级别的 README.pod。
my $make_frag = $mm->platform_constants
返回一个 make 片段,定义了在 init_platform() 中初始化的所有宏,而不是将它们放在 constants() 中。
默认情况下返回一个空字符串。专门用于在 Makefile.PL 中定义所有常量后进行覆盖。
默认情况下返回一个空字符串。在 Makefile.PL 中用于在对象初始化后向 Makefile 添加一些文本块。
返回一个空字符串。可以在 Makefile.PL 中用于在 Makefile 末尾写入一些文本。
Michael G Schwern <[email protected]> 和 [email protected] 的居民,代码来自 ExtUtils::MM_Unix 和 ExtUtils::MM_Win32。