1# Makefile.PL for Perl module WWW::Curl
2# Check out the README file for more information.
3
4use inc::Module::Install;
5
6name			'WWW-Curl';
7abstract		'Perl extension interface for libcurl';
8author			'Cris Bailiff <c.bailiff+curl at devsecure.com>';
9license			'mit';
10perl_version		'5.006001';
11no_index		directory => 'template';
12repository		'http://github.com/szbalint/WWW--Curl';
13# This is a hack. If you have libcurl installed, just specify curl.h below
14# and comment out this line.
15if ($^O ne 'MSWin32') {
16    if (!$ENV{CURL_CONFIG}) {
17	    requires_external_bin	'curl-config';
18    }
19} else {
20	print	"Sorry, no automated install is available on Windows,\n".
21		"please see the README.Win32 file on instructions for a manual install.\n";
22	exit(0);
23}
24
25my $curl_config = $ENV{CURL_CONFIG} || 'curl-config';
26
27my $vernum = `${curl_config} --vernum`; chomp $vernum;
28my $version = `${curl_config} --version`; chomp $version;
29
30my $minimum_ver = hex("070a08");
31
32if ($vernum && hex($vernum) <= $minimum_ver) {
33	print	"Your currently installed libcurl version - $version - is too old.\n".
34		"This module doesn't seek compatibility with versions older than 7.10.8\n".
35		"Proceed manually if you know what you're doing.\n";
36	exit(0);
37}
38
39print "The version is $version\n";
40
41my @includes = qw();
42my ($cflags,$lflags, $ldflags) = ('','','');
43
44# You may need to specify where to find curl.h on your platform
45# These are guesses only, in case curl-config is not telling us.
46
47if ($^O ne 'MSWin32') {
48	push @includes, qw(
49		/usr/include
50		/usr/local/curl/include
51		/usr/local/include/curl
52		../../include
53		../curl/include
54	);
55}
56
57#
58# Get curl to tell us where it is, if we can.
59#
60
61if ($^O ne 'MSWin32') {
62	$cflags = `${curl_config} --cflags`;
63	$lflags = `${curl_config} --libs`;
64}
65
66# can't find link flags, make some guesses
67if (!defined($lflags)) {
68    $lflags="-lcurl";
69    print "Guessing your linker flags as: $lflags\n";
70}
71
72my ($flag) = ($cflags =~ m/-I(\S+)/);
73
74if (defined $flag) {
75    unshift @includes, $flag;    # first guess
76}
77
78# try the path given on the command line, if any
79if (defined($ARGV[0])) {
80    unshift @includes, $ARGV[0];
81};
82
83my $curl_d = "";
84my $curl_h;
85
86# otherwise try a list of common locations
87foreach my $try (@includes) {
88    if (-f $try . "/curl/curl.h") {
89        $curl_d = $try;
90        $curl_h = $try . "/curl/curl.h";
91        last;
92    }
93}
94
95if (!defined($curl_h)) {
96     die "Cannot find curl.h - cannot build constants files  - see Makefile.PL";
97} else {
98     my %constants;
99     $curl_d = "-I" . $curl_d;
100     print "Found curl.h in $curl_h\n";
101     my @syms;
102     my $has_cpp = 0;
103     my @skiplist = qw/
104        CURL_DID_MEMORY_FUNC_TYPEDEFS
105        CURL_STRICTER
106        CURLINC_CURL_H
107        CURL_WIN32
108        CURLOPT
109     /;
110     open(H_IN, "-|", "cpp", $curl_h) and $has_cpp++;
111     unless ($has_cpp) {
112         warn "No working cpp ($!).  Parsing curl.h in Perl";
113         open(H_IN, "<", $curl_h) or die("Can't open curl.h at path $curl_h, because: ".$!);
114     }
115     while ( <H_IN> ) {
116         if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {
117             s/^\s+//;
118             next unless /^CURL/;
119             chomp;
120             s/^(CURL[A-Za-z0-9_]*_) ([A-Za-z0-9_])/$1$2/;  # Strip intervening space from ISO CPP macro
121             s/[,\s].*//;
122             s/=.*$//;
123             next unless /^\w+$/;
124             push @syms, $_;
125         }
126    }
127    close H_IN;
128    open (H, "<", $curl_h) or die ("Cannot open $curl_h: ".$!);
129    while(<H>) {
130        if (/^#define (CURL[A-Za-z0-9_]*)/) {
131            next if $1 ~~ @skiplist;
132            push @syms, $1;
133        }
134    }
135    close H;
136
137    for my $e (sort @syms) {
138       if($e =~ /(OBSOLETE|^CURL_EXTERN|_LAST\z|_LASTENTRY\z)/) {
139          next;
140       }
141       my ($group) = $e =~ m/^([^_]+_)/;
142       $constants{$group}->{$e} = $e;
143    }
144    unless ($has_cpp) {
145    open(CURL_H, "<" . $curl_h) or die "Can't open curl.h\n";
146    while (<CURL_H>) {
147        if ($_ =~ m/CINIT\(/ and $_ !~ m/#/) {
148            my ($option, $type, $code) = m/.*CINIT\((\w*)\s*,\s*(\w+)\s*,\s*(\d+).*/;
149	    $constants{"CURLOPT_"}->{"CURLOPT_".$option} = "CURLOPT_".$option;
150	} elsif ($_ =~ m/^#define CURLOPT_\w+\s+CURLOPT_\w+/) {
151            my ($option, $value) =
152                m/^#define CURLOPT_(\w+)\s+CURLOPT_(\w+)/;
153	    $constants{"CURLOPT_"}->{"CURLOPT_".$option} = "CURLOPT_".$value;
154        } elsif ($_ =~ m/^\s*((CURLINFO_|CURLSHOPT_|CURLE_)\w+)/) {
155	    $constants{$2}->{$1}= $1;
156        } elsif ($_ =~ m/^\s*((CURL_)(?:\w+))(?:[,\s]*)(?:\/\*.*)?$/) {
157	    $constants{$2}->{$1} = $1;
158        } elsif ($_ =~ m/^\s*((CURLPROXY_)(?:\w+))\s*=\s*\d+/) {
159            $constants{$2}->{$1} = $1;
160        } elsif ($_ =~ m/CFINIT\(/ and $_ !~ m/#/) {
161            my ($option) = m/.*CFINIT\((\w*)\s*.*/;
162	    $constants{"CURLFORM_"}->{"CURLFORM_".$option} = "CURLFORM_".$option;
163        }
164    }
165    close(CURL_H);
166    }
167    print "Building curlopt-constants.c for your libcurl version\n";
168
169    open(CURL_XS, ">curlopt-constants.c")
170        or die "Can't write curlopt-constants.c\n";
171
172    # boilerplate xs constant function here
173    print CURL_XS <<HERE
174static int
175constant(const char *name)
176{
177    errno = 0;
178HERE
179        ;
180for my $group (reverse sort keys %constants) {
181	my $grouplength = length($group);
182	my $groupref = $constants{$group};
183	my @constants = keys %{$constants{$group}};
184	print CURL_XS <<HERE2
185
186    if (strncmp(name, "$group", $grouplength) == 0) {
187        name += $grouplength;
188        switch (*name) {
189HERE2
190        ;
191
192    for my $next_initial ('A' .. 'Z') {
193        print CURL_XS "        case '$next_initial':\n";
194        my $count = 0;
195        foreach my $option (sort @constants) {
196            my $remainder = substr($option, length($group), length($option));
197            my $initial = substr($remainder, 0, 1);
198            if ($next_initial eq $initial) {
199
200                print CURL_XS
201"            if (strEQ(name, \"$remainder\")) return "."$groupref->{$option};\n";
202
203                $count++;
204            }
205        }
206        if ($count or $next_initial eq 'Z') {
207            print CURL_XS "            break;\n";
208        }
209    }
210
211    print CURL_XS "    };\n";
212    print CURL_XS "    }\n";
213}
214
215    print CURL_XS <<HERE
216
217    errno = EINVAL;
218    return 0;
219}
220HERE
221        ;
222
223    close(CURL_XS);
224
225    print "Building Easy.pm constants for your libcurl version\n";
226
227    open(EASY_PM,    ">lib/WWW/Curl/Easy.pm")    or die "Can't create lib/WWW/Curl/Easy.pm\n";
228    open(EASY_PM_IN, "template/Easy.pm.tmpl") or die "Can't read template/Easy.pm.tmpl\n";
229    while (my $line = <EASY_PM_IN>) {
230        if ($line !~ m/^\@CURLOPT_INCLUDE\@/) {
231			print EASY_PM $line;
232        } else {
233	for my $group (reverse sort keys %constants) {
234            for my $option (sort keys %{$constants{$group}}) {
235                next unless $option;
236                print EASY_PM $option."\n";
237            }
238        }
239	}
240    }
241    close(EASY_PM);
242    close(EASY_PM_IN);
243
244	print "Building Share.pm constants for your libcurl version\n";
245
246    open(SHARE_PM,   ">lib/WWW/Curl/Share.pm")    or die "Can't create lib/WWW/Curl/Share.pm\n";
247    open(SHARE_PM_IN, "template/Share.pm.tmpl") or die "Can't read template/Share.pm.tmpl\n";
248    while (my $line = <SHARE_PM_IN>) {
249        if ($line !~ m/^(.*?)\@CURLSHOPT_INCLUDE\@/) {
250            print SHARE_PM $line;
251        } else {
252            foreach my $option (sort keys %{$constants{CURLSHOPT_}}) {
253                print SHARE_PM $1 . $option . "\n";
254            }
255            foreach my $option (sort keys %{$constants{CURL_LOCK_}}) {
256                print SHARE_PM $1 . $option . "\n";
257            }
258        }
259    }
260    close(SHARE_PM);
261    close(SHARE_PM_IN);
262}
263
264# Let Module::Install generate META.yml and other necessary files.
265WriteMakefile(
266    'NAME'         => 'WWW::Curl',
267    'VERSION_FROM' => 'lib/WWW/Curl.pm',      # finds $VERSION
268    'LIBS'         => "$ldflags $lflags",        # e.g., '-lm'
269    'INC'          => $curl_d,        # e.g., '-I/usr/include/other'
270    'clean' => { FILES => "curlopt-constants.c head.out body.out" }
271);
272
273