📄 mm_any.pm
字号:
package ExtUtils::MM_Any;use strict;use vars qw($VERSION @ISA);$VERSION = '6.42';use Carp;use File::Spec;BEGIN { @ISA = qw(File::Spec); }# We need $Verboseuse ExtUtils::MakeMaker qw($Verbose);use ExtUtils::MakeMaker::Config;# So we don't have to keep calling the methods over and over again,# we have these globals to cache the values. Faster and shrtr.my $Curdir = __PACKAGE__->curdir;my $Rootdir = __PACKAGE__->rootdir;my $Updir = __PACKAGE__->updir;=head1 NAMEExtUtils::MM_Any - Platform-agnostic MM methods=head1 SYNOPSIS 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);=head1 DESCRIPTIONB<FOR INTERNAL USE ONLY!>ExtUtils::MM_Any is a superclass for the ExtUtils::MM_* set ofmodules. It contains methods which are either inherentlycross-platform or are written in a cross-platform manner.Subclass off of ExtUtils::MM_Any I<and> ExtUtils::MM_Unix. This is atemporary solution.B<THIS MAY BE TEMPORARY!>=head1 METHODSAny methods marked I<Abstract> must be implemented by subclasses.=head2 Cross-platform helper methodsThese are methods which help writing cross-platform code.=head3 os_flavor I<Abstract> my @os_flavor = $mm->os_flavor;@os_flavor is the style of operating system this is, usuallycorresponding to the MM_*.pm file we're using. The first element of @os_flavor is the major family (ie. Unix,Windows, VMS, OS/2, etc...) and the rest are sub families.Some examples: Cygwin98 ('Unix', 'Cygwin', 'Cygwin9x') Windows NT ('Win32', 'WinNT') Win98 ('Win32', 'Win9x') Linux ('Unix', 'Linux') MacOS X ('Unix', 'Darwin', 'MacOS', 'MacOS X') OS/2 ('OS/2')This is used to write code for styles of operating system. See os_flavor_is() for use.=head3 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 to see if the current operating system is one of the given flavors.This is useful for code like: if( $mm->os_flavor_is('Unix') ) { $out = `foo 2>&1`; } else { $out = `foo`; }=cutsub os_flavor_is { my $self = shift; my %flavors = map { ($_ => 1) } $self->os_flavor; return (grep { $flavors{$_} } @_) ? 1 : 0;}=head3 split_command my @cmds = $MM->split_command($cmd, @args);Most OS have a maximum command length they can execute at once. Largemodules can easily generate commands well past that limit. Itsnecessary to split long commands up into a series of shorter commands.C<split_command> will return a series of @cmds each processing part ofthe args. Collectively they will process all the arguments. Eachindividual line in @cmds will not be longer than the$self->max_exec_len being careful to take into account macro expansion.$cmd should include any switches and repeated initial arguments.If no @args are given, no @cmds will be returned.Pairs of arguments will always be preserved in a single command, thisis a heuristic for things like pm_to_blib and pod2man which work onpairs of arguments. This makes things like this safe: $self->split_command($cmd, %pod2man);=cutsub split_command { my($self, $cmd, @args) = @_; my @cmds = (); return(@cmds) unless @args; # If the command was given as a here-doc, there's probably a trailing # newline. chomp $cmd; # set aside 20% for macro expansion. my $len_left = int($self->max_exec_len * 0.80); $len_left -= length $self->_expand_macros($cmd); do { my $arg_str = ''; my @next_args; while( @next_args = splice(@args, 0, 2) ) { # Two at a time to preserve pairs. my $next_arg_str = "\t ". join ' ', @next_args, "\n"; if( !length $arg_str ) { $arg_str .= $next_arg_str } elsif( length($arg_str) + length($next_arg_str) > $len_left ) { unshift @args, @next_args; last; } else { $arg_str .= $next_arg_str; } } chop $arg_str; push @cmds, $self->escape_newlines("$cmd \n$arg_str"); } while @args; return @cmds;}sub _expand_macros { my($self, $cmd) = @_; $cmd =~ s{\$\((\w+)\)}{ defined $self->{$1} ? $self->{$1} : "\$($1)" }e; return $cmd;}=head3 echo my @commands = $MM->echo($text); my @commands = $MM->echo($text, $file); my @commands = $MM->echo($text, $file, $appending);Generates a set of @commands which print the $text to a $file.If $file is not given, output goes to STDOUT.If $appending is true the $file will be appended to rather thanoverwritten.=cutsub echo { my($self, $text, $file, $appending) = @_; $appending ||= 0; my @cmds = map { '$(NOECHO) $(ECHO) '.$self->quote_literal($_) } split /\n/, $text; if( $file ) { my $redirect = $appending ? '>>' : '>'; $cmds[0] .= " $redirect $file"; $_ .= " >> $file" foreach @cmds[1..$#cmds]; } return @cmds;}=head3 wraplist my $args = $mm->wraplist(@list);Takes an array of items and turns them into a well-formatted list ofarguments. In most cases this is simply something like: FOO \ BAR \ BAZ=cutsub wraplist { my $self = shift; return join " \\\n\t", @_;}=head3 maketext_filter my $filter_make_text = $mm->maketext_filter($make_text);The text of the Makefile is run through this method before writing todisk. It allows systems a chance to make portability fixes to theMakefile.By default it does nothing.This method is protected and not intended to be called outside ofMakeMaker.=cutsub maketext_filter { return $_[1] }=head3 cd I<Abstract> my $subdir_cmd = $MM->cd($subdir, @cmds);This will generate a make fragment which runs the @cmds in the given$dir. The rough equivalent to this, except cross platform. cd $subdir && $cmdCurrently $dir can only go down one level. "foo" is fine. "foo/bar" isnot. "../foo" is right out.The resulting $subdir_cmd has no leading tab nor trailing newline. Thismakes it easier to embed in a make string. For example. my $make = sprintf <<'CODE', $subdir_cmd; foo : $(ECHO) what %s $(ECHO) mouche CODE=head3 oneliner I<Abstract> my $oneliner = $MM->oneliner($perl_code); my $oneliner = $MM->oneliner($perl_code, \@switches);This will generate a perl one-liner safe for the particular platformyou're on based on the given $perl_code and @switches (a -e isassumed) suitable for using in a make target. It will use the propershell quoting and escapes.$(PERLRUN) will be used as perl.Any newlines in $perl_code will be escaped. Leading and trailingnewlines will be stripped. Makes this idiom much easier: my $code = $MM->oneliner(<<'CODE', [...switches...]);some code hereanother line hereCODEUsage might be something like: # an echo emulation $oneliner = $MM->oneliner('print "Foo\n"'); $make = '$oneliner > somefile';All dollar signs must be doubled in the $perl_code if you expect themto be interpreted normally, otherwise it will be considered a makemacro. Also remember to quote make macros else it might be used as abareword. For example: # Assign the value of the $(VERSION_FROM) make macro to $vf. $oneliner = $MM->oneliner('$$vf = "$(VERSION_FROM)"');Its currently very simple and may be expanded sometime in the figureto include more flexible code and switches.=head3 quote_literal I<Abstract> my $safe_text = $MM->quote_literal($text);This will quote $text so it is interpreted literally in the shell.For example, on Unix this would escape any single-quotes in $text andput single-quotes around the whole thing.=head3 escape_newlines I<Abstract> my $escaped_text = $MM->escape_newlines($text);Shell escapes newlines in $text.=head3 max_exec_len I<Abstract> my $max_exec_len = $MM->max_exec_len;Calculates the maximum command size the OS can exec. Effectively,this is the max size of a shell command line.=for _private$self->{_MAX_EXEC_LEN} is set by this method, but only for testing purposes.=head3 make my $make = $MM->make;Returns the make variant we're generating the Makefile for. This attemptsto do some normalization on the information from %Config or the user.=cutsub make { my $self = shift; my $make = lc $self->{MAKE}; # Truncate anything like foomake6 to just foomake. $make =~ s/^(\w+make).*/$1/; # Turn gnumake into gmake. $make =~ s/^gnu/g/; return $make;}=head2 TargetsThese are methods which produce make targets.=head3 all_targetGenerate the default target 'all'.=cutsub all_target { my $self = shift; return <<'MAKE_EXT';all :: pure_all $(NOECHO) $(NOOP)MAKE_EXT}=head3 blibdirs_target my $make_frag = $mm->blibdirs_target;Creates the blibdirs target which creates all the directories we usein blib/.The blibdirs.ts target is deprecated. Depend on blibdirs instead.=cutsub blibdirs_target { my $self = shift; my @dirs = map { uc "\$(INST_$_)" } qw(libdir archlib autodir archautodir bin script man1dir man3dir ); my @exists = map { $_.'$(DFSEP).exists' } @dirs; my $make = sprintf <<'MAKE', join(' ', @exists);blibdirs : %s $(NOECHO) $(NOOP)# Backwards compat with 6.18 through 6.25blibdirs.ts : blibdirs $(NOECHO) $(NOOP)MAKE $make .= $self->dir_target(@dirs); return $make;}=head3 clean (o)Defines the clean target.=cutsub clean {# --- Cleanup and Distribution Sections --- my($self, %attribs) = @_; my @m; push(@m, '# Delete temporary files but do not touch installed files. We don\'t delete# the Makefile here so a later make realclean still has a makefile to use.clean :: clean_subdirs'); my @files = values %{$self->{XS}}; # .c files from *.xs files my @dirs = qw(blib); # Normally these are all under blib but they might have been # redefined. # XXX normally this would be a good idea, but the Perl core sets # INST_LIB = ../../lib rather than actually installing the files. # So a "make clean" in an ext/ directory would blow away lib. # Until the core is adjusted let's leave this out.# push @dirs, qw($(INST_ARCHLIB) $(INST_LIB)# $(INST_BIN) $(INST_SCRIPT)# $(INST_MAN1DIR) $(INST_MAN3DIR)# $(INST_LIBDIR) $(INST_ARCHLIBDIR) $(INST_AUTODIR) # $(INST_STATIC) $(INST_DYNAMIC) $(INST_BOOT)# ); if( $attribs{FILES} ) { # Use @dirs because we don't know what's in here. push @dirs, ref $attribs{FILES} ? @{$attribs{FILES}} : split /\s+/, $attribs{FILES} ; } push(@files, qw[$(MAKE_APERL_FILE) perlmain.c tmon.out mon.out so_locations blibdirs.ts pm_to_blib pm_to_blib.ts *$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT) $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def lib$(BASEEXT).def $(BASEEXT).exp $(BASEEXT).x ]); push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.all')); push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.ld')); # core files push(@files, qw[core core.*perl.*.? *perl.core]); push(@files, map { "core." . "[0-9]"x$_ } (1..5)); # OS specific things to clean up. Use @dirs since we don't know # what might be in here. push @dirs, $self->extra_clean_files; # Occasionally files are repeated several times from different sources { my(%f) = map { ($_ => 1) } @files; @files = keys %f; } { my(%d) = map { ($_ => 1) } @dirs; @dirs = keys %d; } push @m, map "\t$_\n", $self->split_command('- $(RM_F)', @files); push @m, map "\t$_\n", $self->split_command('- $(RM_RF)', @dirs); # Leave Makefile.old around for realclean push @m, <<'MAKE'; - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)MAKE push(@m, "\t$attribs{POSTOP}\n") if $attribs{POSTOP}; join("", @m);}=head3 clean_subdirs_target my $make_frag = $MM->clean_subdirs_target;Returns the clean_subdirs target. This is used by the clean target tocall clean on any subdirectories which contain Makefiles.=cutsub clean_subdirs_target { my($self) = shift; # No subdirectories, no cleaning. return <<'NOOP_FRAG' unless @{$self->{DIR}};clean_subdirs : $(NOECHO) $(NOOP)NOOP_FRAG my $clean = "clean_subdirs :\n"; for my $dir (@{$self->{DIR}}) { my $subclean = $self->oneliner(sprintf <<'CODE', $dir);chdir '%s'; system '$(MAKE) clean' if -f '$(FIRST_MAKEFILE)';CODE $clean .= "\t$subclean\n"; } return $clean;}=head3 dir_target my $make_frag = $mm->dir_target(@directories);Generates targets to create the specified directories and set itspermission to 0755.Because depending on a directory to just ensure it exists doesn't worktoo well (the modified time changes too often) dir_target() creates a.exists file in the created directory. It is this you should depend on.For portability purposes you should use the $(DIRFILESEP) macro ratherthan a '/' to seperate the directory from the file. yourdirectory$(DIRFILESEP).exists=cutsub dir_target { my($self, @dirs) = @_; my $make = ''; foreach my $dir (@dirs) { $make .= sprintf <<'MAKE', ($dir) x 7;%s$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) %s $(NOECHO) $(CHMOD) 755 %s $(NOECHO) $(TOUCH) %s$(DFSEP).existsMAKE } return $make;}=head3 distdirDefines the scratch directory target that will hold the distributionbefore tar-ing (or shar-ing).=cut# For backwards compatibility.*dist_dir = *distdir;sub distdir { my($self) = shift; my $meta_target = $self->{NO_META} ? '' : 'distmeta'; my $sign_target = !$self->{SIGN} ? '' : 'distsignature';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -