This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Module-Build to CPAN version 0.4204
[perl5.git] / cpan / Module-Build / lib / Module / Build / PPMMaker.pm
1 package Module::Build::PPMMaker;
2
3 use strict;
4 use Config;
5 use vars qw($VERSION);
6
7 $VERSION = '0.4204';
8 $VERSION = eval $VERSION;
9
10 # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a
11 # few tweaks based on the PPD spec at
12 # http://www.xav.com/perl/site/lib/XML/PPD.html
13
14 # The PPD spec is based on <http://www.w3.org/TR/NOTE-OSD>
15
16 sub new {
17   my $package = shift;
18   return bless {@_}, $package;
19 }
20
21 sub make_ppd {
22   my ($self, %args) = @_;
23   my $build = delete $args{build};
24
25   my @codebase;
26   if (exists $args{codebase}) {
27     @codebase = ref $args{codebase} ? @{$args{codebase}} : ($args{codebase});
28   } else {
29     my $distfile = $build->ppm_name . '.tar.gz';
30     print "Using default codebase '$distfile'\n";
31     @codebase = ($distfile);
32   }
33
34   my %dist;
35   foreach my $info (qw(name author abstract version)) {
36     my $method = "dist_$info";
37     $dist{$info} = $build->$method() or die "Can't determine distribution's $info\n";
38   }
39
40   $self->_simple_xml_escape($_) foreach $dist{abstract}, @{$dist{author}};
41
42   # TODO: could add <LICENSE HREF=...> tag if we knew what the URLs were for
43   # various licenses
44   my $ppd = <<"PPD";
45 <SOFTPKG NAME=\"$dist{name}\" VERSION=\"$dist{version}\">
46     <ABSTRACT>$dist{abstract}</ABSTRACT>
47 @{[ join "\n", map "    <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
48     <IMPLEMENTATION>
49 PPD
50
51   # We don't include recommended dependencies because PPD has no way
52   # to distinguish them from normal dependencies.  We don't include
53   # build_requires dependencies because the PPM installer doesn't
54   # build or test before installing.  And obviously we don't include
55   # conflicts either.
56
57   foreach my $type (qw(requires)) {
58     my $prereq = $build->$type();
59     while (my ($modname, $spec) = each %$prereq) {
60       next if $modname eq 'perl';
61
62       my $min_version = '0.0';
63       foreach my $c ($build->_parse_conditions($spec)) {
64         my ($op, $version) = $c =~ /^\s*  (<=?|>=?|==|!=)  \s*  ([\w.]+)  \s*$/x;
65
66         # This is a nasty hack because it fails if there is no >= op
67         if ($op eq '>=') {
68           $min_version = $version;
69           last;
70         }
71       }
72
73       # PPM4 spec requires a '::' for top level modules
74       $modname .= '::' unless $modname =~ /::/;
75
76       $ppd .= qq!        <REQUIRE NAME="$modname" VERSION="$min_version" />\n!;
77     }
78   }
79
80   # We only include these tags if this module involves XS, on the
81   # assumption that pure Perl modules will work on any OS.
82   if (keys %{$build->find_xs_files}) {
83     my $perl_version = $self->_ppd_version($build->perl_version);
84     $ppd .= sprintf(<<'EOF', $self->_varchname($build->config) );
85         <ARCHITECTURE NAME="%s" />
86 EOF
87   }
88
89   foreach my $codebase (@codebase) {
90     $self->_simple_xml_escape($codebase);
91     $ppd .= sprintf(<<'EOF', $codebase);
92         <CODEBASE HREF="%s" />
93 EOF
94   }
95
96   $ppd .= <<'EOF';
97     </IMPLEMENTATION>
98 </SOFTPKG>
99 EOF
100
101   my $ppd_file = "$dist{name}.ppd";
102   open(my $fh, '>', $ppd_file)
103     or die "Cannot write to $ppd_file: $!";
104
105   binmode($fh, ":utf8")
106     if $] >= 5.008 && $Config{useperlio};
107   print $fh $ppd;
108   close $fh;
109
110   return $ppd_file;
111 }
112
113 sub _ppd_version {
114   my ($self, $version) = @_;
115
116   # generates something like "0,18,0,0"
117   return join ',', (split(/\./, $version), (0)x4)[0..3];
118 }
119
120 sub _varchname {  # Copied from PPM.pm
121   my ($self, $config) = @_;
122   my $varchname = $config->{archname};
123   # Append "-5.8" to architecture name for Perl 5.8 and later
124   if ($] >= 5.008) {
125       my $vstring = sprintf "%vd", $^V;
126       $vstring =~ s/\.\d+$//;
127       $varchname .= "-$vstring";
128   }
129   return $varchname;
130 }
131
132 {
133   my %escapes = (
134                  "\n" => "\\n",
135                  '"' => '&quot;',
136                  '&' => '&amp;',
137                  '>' => '&gt;',
138                  '<' => '&lt;',
139                 );
140   my $rx = join '|', keys %escapes;
141
142   sub _simple_xml_escape {
143     $_[1] =~ s/($rx)/$escapes{$1}/go;
144   }
145 }
146
147 1;
148 __END__
149
150
151 =head1 NAME
152
153 Module::Build::PPMMaker - Perl Package Manager file creation
154
155 =head1 SYNOPSIS
156
157   On the command line, builds a .ppd file:
158   ./Build ppd
159
160
161 =head1 DESCRIPTION
162
163 This package contains the code that builds F<.ppd> "Perl Package
164 Description" files, in support of ActiveState's "Perl Package
165 Manager".  Details are here:
166 L<http://aspn.activestate.com/ASPN/Downloads/ActivePerl/PPM/>
167
168
169 =head1 AUTHOR
170
171 Dave Rolsky <autarch@urth.org>, Ken Williams <kwilliams@cpan.org>
172
173
174 =head1 COPYRIGHT
175
176 Copyright (c) 2001-2006 Ken Williams.  All rights reserved.
177
178 This library is free software; you can redistribute it and/or
179 modify it under the same terms as Perl itself.
180
181
182 =head1 SEE ALSO
183
184 perl(1), Module::Build(3)
185
186 =cut