version bump
[Math-GSL.git] / Build.PL
bloba948186ad2ee64950b1e83ea3d0575a82f4e97e2
1 #!/usr/bin/perl -w
3 # This script has been heavily modified from the Device::Cdio Build.PL
4 # Jonathan Leto <jonathan@leto.net>
5 # Copyright (C) 2006 Rocky Bernstein <rocky@cpan.org>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 use strict;
21 use warnings;
22 use Config;
23 use Data::Dumper;
24 use Module::Build;
26 BEGIN {
27 eval { require ExtUtils::PkgConfig };
28 if ($@) {
29 print "\nI see that you are a CPANTester, you really should install ExtUtils::PkgConfig !\n"
30 if $ENV{AUTOMATED_TESTING};
31 print <<EXIT;
32 ExtUtils::PkgConfig is currently needed to find GSL for the compilation of this module.
33 It may be bundled with Math::GSL in the future.
34 EXIT
35 exit 0;
39 my $code = <<'EOC';
40 use Config;
41 use File::Copy;
42 use File::Spec::Functions qw/:ALL/;
44 sub process_swig_files {
45 my $self = shift;
46 my $p = $self->{properties};
47 return unless $p->{swig_source};
48 my $files_ref = $p->{swig_source};
49 foreach my $file (@$files_ref) {
50 $self->process_swig($file->[0], $file->[1]);
54 # Check check dependencies for $main_swig_file. These are the
55 # %includes. If needed, arrange to run swig on $main_swig_file to
56 # produce a xxx_wrap.c C file.
58 sub process_swig {
59 my ($self, $main_swig_file, $deps_ref) = @_;
60 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
62 # File name. e.g, perlcdio.swg -> perlcdio_wrap.c
63 (my $file_base = $main_swig_file) =~ s/\.[^.]+$//;
64 my $c_file = "${file_base}_wrap.c";
66 # .swg -> .c
67 $self->add_to_cleanup($c_file);
69 # If any of the swig files that the main swig depends is newer
70 # then rebuild.
71 foreach my $depends_on ($main_swig_file, @$deps_ref) {
72 unless ($self->up_to_date($depends_on, $c_file)) {
73 $self->compile_swig($main_swig_file, $c_file);
74 # Only need to build $c_file once no matter how many
75 # includes there are.
76 last;
80 # .c -> .o
81 my $obj_file = $self->compile_c($c_file);
82 $self->add_to_cleanup($obj_file);
84 # The .so files don't go in blib/lib/, they go in blib/arch/auto/.
85 # Unfortunately we have to pre-compute the whole path.
86 my $archdir;
88 my @dirs = splitdir($file_base);
89 $archdir = catdir($self->blib,'arch', @dirs[1..$#dirs]);
92 # .o -> .so
93 $self->link_c($archdir, $file_base, $obj_file);
96 # Invoke swig with -perl -outdir and other options.
97 sub compile_swig {
98 my ($self, $file, $c_file) = @_;
99 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
101 # File name, minus the suffix
102 (my $file_base = $file) =~ s/\.[^.]+$//;
104 my @swig;
105 if (defined($p->{swig})) {
106 @swig = $self->split_like_shell($p->{swig});
107 } else {
108 @swig = ('swig');
110 if (defined($p->{swig_flags})) {
111 @swig_flags = $self->split_like_shell($p->{swig_flags});
112 } else {
113 @swig_flags = ();
116 my $blib_lib = catfile(qw/blib lib/);
118 mkdir catfile($blib_lib, qw/Math GSL/);
119 my $outdir = catfile($blib_lib, qw/Math GSL/);
120 my $pm_file = "${file_base}.pm";
121 my $from = catfile($blib_lib, qw/Math GSL/, $pm_file);
122 my $to = catfile(qw/lib Math GSL/,$pm_file);
123 chmod 0644, $from, $to;
125 $self->do_system(@swig, '-o', $c_file,
126 '-outdir', $outdir,
127 '-perl5', @swig_flags, $file)
128 or die "error building $c_file file from '$file'";
131 print "Copying from: $from, to: $to; it makes the CPAN indexer happy.\n";
132 copy($from,$to);
133 return $c_file;
135 sub is_windows { $^O =~ /MSWin32/i }
137 # Windows fixes courtesy of <sisyphus@cpan.org>
138 sub link_c {
139 my ($self, $to, $file_base, $obj_file) = @_;
140 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
142 my $lib_file = catfile($to, File::Basename::basename("$file_base.$Config{dlext}"));
144 $self->add_to_cleanup($lib_file);
145 my $objects = $p->{objects} || [];
147 unless ($self->up_to_date([$obj_file, @$objects], $lib_file)) {
148 my @linker_flags = $self->split_like_shell($p->{extra_linker_flags});
150 push @linker_flags, $Config{archlib} . '/CORE/' . $Config{libperl} if is_windows();
152 my @lddlflags = $self->split_like_shell($cf->{lddlflags});
153 my @shrp = $self->split_like_shell($cf->{shrpenv});
154 my @ld = $self->split_like_shell($cf->{ld}) || "gcc";
155 $self->do_system(@shrp, @ld, @lddlflags, @user_libs, '-o', $lib_file,
156 $obj_file, @$objects, @linker_flags)
157 or die "error building $lib_file file from '$obj_file'";
160 return $lib_file;
163 # From Base.pm but modified to put package cflags *after*
164 # installed c flags so warning-removal will have an effect.
166 sub compile_c {
167 my ($self, $file) = @_;
168 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
170 # File name, minus the suffix
171 (my $file_base = $file) =~ s/\.[^.]+$//;
172 my $obj_file = $file_base . $Config{_o};
174 $self->add_to_cleanup($obj_file);
175 return $obj_file if $self->up_to_date($file, $obj_file);
178 $cf->{installarchlib} = $Config{archlib};
180 my @include_dirs = @{$p->{include_dirs}}
181 ? map {"-I$_"} (@{$p->{include_dirs}}, catdir($cf->{installarchlib}, 'CORE'))
182 : map {"-I$_"} ( catdir($cf->{installarchlib}, 'CORE') ) ;
184 my @extra_compiler_flags = $self->split_like_shell($p->{extra_compiler_flags});
186 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
188 my @ccflags = $self->split_like_shell($cf->{ccflags});
189 my @optimize = $self->split_like_shell($cf->{optimize});
191 # Whoah! There seems to be a bug in gcc 4.1.0 and optimization
192 # and swig. I'm not sure who's at fault. But for now the simplest
193 # thing is to turn off all optimization. For the kinds of things that
194 # SWIG does - do conversions between parameters and transfers calls
195 # I doubt optimization makes much of a difference. But if it does,
196 # it can be added back via @extra_compiler_flags.
198 my @flags = (@include_dirs, @cccdlflags, '-c', @ccflags, @extra_compiler_flags, );
200 my @cc = $self->split_like_shell($cf->{cc});
201 @cc = "gcc" unless @cc;
203 $self->do_system(@cc, @flags, '-o', $obj_file, $file)
204 or die "error building $Config{_o} file from '$file'";
206 return $obj_file;
212 sub try_compile {
213 my ($c, %args) = @_;
215 my $ok = 0;
216 my $tmp = "tmp$$";
217 local(*TMPC);
219 my $obj_ext = $Config{_o} || ".o";
220 unlink("$tmp.c", "$tmp$obj_ext");
222 if (open(TMPC, ">", "$tmp.c")) {
223 print TMPC $c;
224 close(TMPC);
226 my $cccmd = $args{cccmd};
227 my $errornull;
228 my $ccflags = $Config{'ccflags'};
229 $ccflags .= " $args{ccflags}" if $args{ccflags};
231 if ($args{silent} ) {
232 $errornull = "2>/dev/null" unless defined $errornull;
233 } else {
234 $errornull = '';
237 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c $errornull"
238 unless defined $cccmd;
240 printf "cccmd = $cccmd\n" if $args{verbose};
241 my $res = system($cccmd);
242 $ok = defined($res) && $res == 0;
244 if ( !$ok ) {
245 my $errno = $? >> 8;
246 local $! = $errno;
247 print "
249 *** The test compile of '$tmp.c' failed: status $?
250 *** (the status means: errno = $errno or '$!')
251 *** DO NOT PANIC: this just means that *some* you may get some innocuous
252 *** compiler warnings.
255 unlink("$tmp.c");
258 return $ok;
261 sub try_cflags ($) {
262 my ($ccflags) = @_;
263 my $c_prog = "int main () { return 0; }\n";
264 print "Checking if $Config{cc} supports \"$ccflags\"...";
265 my $result = try_compile($c_prog, ccflags=>$ccflags);
266 if ($result) {
267 print "yes\n";
268 return " $ccflags";
270 print "no\n";
271 return '';
275 print "Checking for GSL..";
276 my %gsl_pkgcfg = ExtUtils::PkgConfig->find ('gsl');
278 my $MIN_GSL_VERSION = "1.11";
279 my $gv = $gsl_pkgcfg{'modversion'};
281 if (defined $gv) {
282 if ($gv =~ m{\A(\d+(?:\.\d+)+)}) {
283 my @current= split /\./, $1;
284 my @min= split /\./, $MIN_GSL_VERSION;
285 unless ($current[0] >= $min[0] && $current[1] >= $min[1]) {
286 printf "
287 ***
288 *** You need to have GSL %s or greater installed. (You have $gv).
289 *** Get GSL at http://www.gnu.org/software/gsl\n", $MIN_GSL_VERSION;
290 exit 1;
291 } else {
292 print "Found GSL version $gv\n";
295 } else {
296 print "
297 ***
298 *** Can't parse GSL version $gv.
299 *** Will continue and keep my fingers crossed for luck.
302 } else {
303 print "
304 ***
305 *** Can't find GSL configuration info. Is GSL installed?
306 *** Get GSL at http://www.gnu.org/software/gsl
308 exit 1;
312 my $ccflags = $gsl_pkgcfg{cflags};
314 ## Swig produces a number of GCC warnings. Turn them off if we can.
315 $ccflags .= try_cflags("-Wno-strict-aliasing");
316 $ccflags .= try_cflags("-Wno-unused-function");
317 $ccflags .= try_cflags("-Wno-unused-value");
318 $ccflags .= try_cflags("-Wno-unused-function");
319 $ccflags .= try_cflags("-Wno-unused-variable");
321 my $ldflags = "$gsl_pkgcfg{libs} -gsl";
322 my $swig_flags='-Wall ' . $gsl_pkgcfg{cflags};
324 if ('cygwin' eq $Config{osname} &&
325 $Config{shrpenv} =~ m{\Aenv LD_RUN_PATH=(.*)\Z} ) {
326 $ldflags .= " -L$1 -lperl";
327 # Should we check the 32-ness?
328 $swig_flags = '-DNEED_LONG';
329 } elsif ('darwin' eq $Config{osname}) {
330 $ldflags .= " -bundle -flat_namespace";
333 my $class = Module::Build->subclass( code => $code );
334 my @Subsystems = sort qw/
335 BLAS Diff Machine Statistics
336 Eigen Matrix Poly Wavelet2D
337 BSpline Errno PowInt Wavelet
338 CBLAS FFT Min
339 CDF Fit QRNG
340 Chebyshev Monte RNG
341 Heapsort Multifit Randist Sum
342 Combination Histogram Multimin Roots
343 Complex Histogram2D Multiroots SF
344 Const Siman IEEEUtils Sys
345 Integration NTuple Sort
346 DHT Interp ODEIV Vector
347 Deriv Linalg Permutation Spline
349 my $cleanup = qq{core *.core Makefile Math-GSL-* tmp* pod2ht*.tmp _build blib *.so *.orig };
351 my $builder = $class->new(
352 module_name => 'Math::GSL',
353 add_to_cleanup => [ $cleanup ],
354 create_makefile_pl => 'passthrough',
355 dist_abstract => 'Interface to the GNU Scientific Library using SWIG',
356 dist_author => 'Jonathan Leto <jonathan@leto.net>',
357 dist_version_from => 'lib/Math/GSL.pm',
358 include_dirs => q{},
359 extra_linker_flags => '-shared -I./lib -I../lib ' . $ldflags,
360 extra_compiler_flags=> q{-shared -fpic } . $ccflags,
361 swig_flags => $swig_flags,
362 license => 'gpl',
363 requires => {
364 'ExtUtils::PkgConfig' => '1.03',
365 'Scalar::Util' => 0,
366 'Test::More' => 0,
367 'Test::Exception' => 0.21,
368 'Test::Class' => 0.12,
369 version => 0,
370 perl => '5.8.8',
372 sign => 0,
373 swig_source => [
374 map { [ "$_.i" ] } @Subsystems
377 $builder->add_build_element('swig');
378 $builder->create_build_script();
379 print "Have a great day!\n";