More Wavelet tests and cleanup.
[Math-GSL.git] / Build.PL
blob87bd729a81835914d8124d10730d9adb2a496cf3
1 #!/usr/bin/perl -w
2 # $Id: Build.PL,v 1.25 2006/08/05 08:48:12 rocky Exp $
3 # Copyright (C) 2006 Rocky Bernstein <rocky@cpan.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 use strict;
19 use warnings;
20 use Module::Build;
21 use ExtUtils::PkgConfig;
22 use Config;
23 use Data::Dumper;
25 my $code = <<'EOC';
26 use Config;
27 use File::Copy;
29 sub process_swig_files {
30 my $self = shift;
31 my $p = $self->{properties};
32 return unless $p->{swig_source};
33 my $files_ref = $p->{swig_source};
34 foreach my $file (@$files_ref) {
35 $self->process_swig($file->[0], $file->[1]);
39 # Check check dependencies for $main_swig_file. These are the
40 # %includes. If needed, arrange to run swig on $main_swig_file to
41 # produce a xxx_wrap.c C file.
43 sub process_swig {
44 my ($self, $main_swig_file, $deps_ref) = @_;
45 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
47 # File name. e.g, perlcdio.swg -> perlcdio_wrap.c
48 (my $file_base = $main_swig_file) =~ s/\.[^.]+$//;
49 my $c_file = "${file_base}_wrap.c";
51 if ($p->{swig_installed}) {
52 # .swg -> .c
53 $self->add_to_cleanup($c_file);
55 # print "+++ c_file: $c_file, file: $main_swig_file ", `pwd`, "\n";
56 # If any of the swig files that the main swig depends is newer
57 # then rebuild.
58 foreach my $depends_on ($main_swig_file, @$deps_ref) {
59 unless ($self->up_to_date($depends_on, $c_file)) {
60 $self->compile_swig($main_swig_file, $c_file);
61 # Only need to build $c_file once no matter how many
62 # includes there are.
63 last;
68 # .c -> .o
69 my $obj_file = $self->compile_c($c_file);
70 $self->add_to_cleanup($obj_file);
72 # The .so files don't go in blib/lib/, they go in blib/arch/auto/.
73 # Unfortunately we have to pre-compute the whole path.
74 my $archdir;
76 my @dirs = File::Spec->splitdir($file_base);
77 $archdir = File::Spec->catdir($self->blib,'arch', @dirs[1..$#dirs]);
80 # .o -> .so
81 $self->link_c($archdir, $file_base, $obj_file);
84 # Invoke swig with -perl -outdir and other options.
85 sub compile_swig {
86 my ($self, $file, $c_file) = @_;
87 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
89 # File name, minus the suffix
90 (my $file_base = $file) =~ s/\.[^.]+$//;
92 my @swig;
93 if (defined($p->{swig})) {
94 @swig = $self->split_like_shell($p->{swig});
95 } else {
96 @swig = ('swig');
98 if (defined($p->{swig_flags})) {
99 @swig_flags = $self->split_like_shell($p->{swig_flags});
100 } else {
101 @swig_flags = ();
104 push @swig_flags, $self->split_like_shell( qq{-module Math::GSL::$file_base} );
106 my $blib_lib = File::Spec->catfile('blib','lib');
107 #my $blib_lib = 'blib/lib';
109 mkdir File::Spec->catfile($blib_lib, 'Math/GSL');
111 print "+++swig -o $c_file -outdir $blib_lib -perl5 @swig_flags $file\n";
112 $self->do_system(@swig, '-o', $c_file, '-outdir', $blib_lib . '/Math/GSL/',
113 '-perl5', @swig_flags, $file)
114 or die "error building $c_file file from '$file'";
116 my $pm_file = "${file_base}.pm";
117 my $from = File::Spec->catfile($blib_lib, $pm_file);
118 my $to = File::Spec->catfile("lib", $pm_file);
120 print "Copying from: $from, to: $to; it makes the CPAN indexer happy.\n";
121 copy($from,$to);
122 return $c_file;
125 # From Base.pm but modified for a SWIG conventions.
126 # We just pass a $obj_file parameter
127 # SWIG objects have a get created with _wrap added. For example
128 # perlcdio.swg produces perlcdio_wrap.c, and perlcdio_wrap.o.
129 # But the shared object is still perlcdio.so.
130 # Also we modified the die to report the full file name.
131 sub link_c {
132 my ($self, $to, $file_base, $obj_file) = @_;
133 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
135 my $lib_file = File::Spec->catfile($to, File::Basename::basename("$file_base.so"));
137 $self->add_to_cleanup($lib_file);
138 my $objects = $p->{objects} || [];
140 unless ($self->up_to_date([$obj_file, @$objects], $lib_file)) {
141 my @linker_flags = $self->split_like_shell($p->{extra_linker_flags});
142 my @lddlflags = $self->split_like_shell($cf->{lddlflags});
143 my @shrp = $self->split_like_shell($cf->{shrpenv});
144 my @ld = $self->split_like_shell($cf->{ld}) || "gcc";
145 $self->do_system(@shrp, @ld, @lddlflags, @user_libs, '-o', $lib_file,
146 $obj_file, @$objects, @linker_flags)
147 or die "error building $lib_file file from '$obj_file'";
150 return $lib_file;
153 # From Base.pm but modified to put package cflags *after*
154 # installed c flags so warning-removal will have an effect.
156 sub compile_c {
157 my ($self, $file) = @_;
158 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
160 # File name, minus the suffix
161 (my $file_base = $file) =~ s/\.[^.]+$//;
162 my $obj_file = "$file_base.so";
163 $self->add_to_cleanup($obj_file);
164 return $obj_file if $self->up_to_date($file, $obj_file);
167 $cf->{installarchlib} = $Config{archlib};
169 my @include_dirs = @{$p->{include_dirs}}
170 ? map {"-I$_"} (@{$p->{include_dirs}}, File::Spec->catdir($cf->{installarchlib}, 'CORE'))
171 : map {"-I$_"} ( File::Spec->catdir($cf->{installarchlib}, 'CORE') ) ;
173 my @extra_compiler_flags = #split / /, q{-shared -Wall -fpic -Dbool=char -I/usr/local/include/};
174 $self->split_like_shell($p->{extra_compiler_flags});
176 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
178 my @ccflags = split / /, $self->split_like_shell($cf->{ccflags});
179 my @optimize = $self->split_like_shell($cf->{optimize});
181 # Whoah! There seems to be a bug in gcc 4.1.0 and optimization
182 # and swig. I'm not sure who's at fault. But for now the simplest
183 # thing is to turn off all optimization. For the kinds of things that
184 # SWIG does - do conversions between parameters and transfers calls
185 # I doubt optimization makes much of a difference. But if it does,
186 # it can be added back via @extra_compiler_flags.
188 my @flags = (@include_dirs, @cccdlflags, '-c', @ccflags,
189 @extra_compiler_flags,
192 my @cc = $self->split_like_shell($cf->{cc});
193 @cc = "gcc" unless @cc;
195 $self->do_system(@cc, @flags, '-o', $obj_file, $file)
196 or die "error building $cf->{obj_ext} file from '$file'";
198 return $obj_file;
204 sub try_compile {
205 my ($c, %args) = @_;
207 my $ok = 0;
208 my $tmp = "tmp$$";
209 local(*TMPC);
211 my $obj_ext = $Config{obj_ext} || ".o";
212 unlink("$tmp.c", "$tmp$obj_ext");
214 if (open(TMPC, ">", "$tmp.c")) {
215 print TMPC $c;
216 close(TMPC);
218 my $cccmd = $args{cccmd};
219 my $errornull;
220 my $ccflags = $Config{'ccflags'};
221 $ccflags .= " $args{ccflags}" if $args{ccflags};
223 if ($args{silent} ) {
224 $errornull = "2>/dev/null" unless defined $errornull;
225 } else {
226 $errornull = '';
229 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c $errornull"
230 unless defined $cccmd;
232 printf "cccmd = $cccmd\n" if $args{verbose};
233 my $res = system($cccmd);
234 $ok = defined($res) && $res == 0;
236 if ( !$ok ) {
237 my $errno = $? >> 8;
238 local $! = $errno;
239 print "
241 *** The test compile of '$tmp.c' failed: status $?
242 *** (the status means: errno = $errno or '$!')
243 *** DO NOT PANIC: this just means that *some* you may get some innocuous
244 *** compiler warnings.
247 unlink("$tmp.c");
250 return $ok;
253 sub try_cflags ($) {
254 my ($ccflags) = @_;
255 my $c_prog = "int main () { return 0; }\n";
256 print "Checking if $Config{cc} supports \"$ccflags\"...";
257 my $result = try_compile($c_prog, ccflags=>$ccflags);
258 if ($result) {
259 print "yes\n";
260 return " $ccflags";
262 print "no\n";
263 return '';
267 my %gsl_pkgcfg = ExtUtils::PkgConfig->find ('gsl');
269 use constant MIN_GSL_VERSION => "1.10";
270 my $gv = $gsl_pkgcfg{'modversion'};
272 if (defined $gv) {
273 if ($gv =~ m{\A(\d+(?:\.\d+)+)}) {
274 my @current= split /\./, $1;
275 my @min= split /\./, MIN_GSL_VERSION;
276 unless ($current[0] >= $min[0] && $current[1] >= $min[1]) {
277 printf "
278 ***
279 *** You need to have gsl %s or greater installed. (You have $gv).
280 *** Get gsl at http://www.gnu.org/software/gsl
281 ", MIN_GSL_VERSION;
282 exit 1;
283 } else {
284 print "Good, I found gsl version $gv installed.\n";
287 } else {
288 print "
289 ***
290 *** Can't parse gsl version $gv.
291 *** Will continue and keep my fingers crossed for luck.
294 } else {
295 print "
296 ***
297 *** Can't find gsl configuration info. Is gsl installed?
298 *** Get gsl at http://www.gnu.org/software/gsl
300 exit 1;
303 print "Checking for SWIG...";
304 my @swig_version = `swig -version 2>&1`;
305 my $swig_installed = 0;
306 if ($?) {
307 my $errno = $? >> 8;
308 print "
309 *** I don't see SWIG installed. I'll use the SWIG-generated file
310 *** that comes with the distribution. If you want SWIG, get it
311 *** from http://www.swig.org
313 print "*** Output was:
314 @swig_version
315 " if @swig_version;
316 } else {
317 $swig_installed = 1;
318 print "ok\n";
321 my $ccflags = $gsl_pkgcfg{cflags};
323 ## Swig produces a number of GCC warnings. Turn them off if we can.
324 $ccflags .= try_cflags("-Wno-strict-aliasing");
325 $ccflags .= try_cflags("-Wno-unused-function");
326 $ccflags .= try_cflags("-Wno-unused-value");
327 $ccflags .= try_cflags("-Wno-unused-function");
328 $ccflags .= try_cflags("-Wno-unused-variable");
330 my $ldflags = "$gsl_pkgcfg{libs} -gsl";
331 my $swig_flags='-Wall';
332 if ('cygwin' eq $Config{osname} &&
333 $Config{shrpenv} =~ m{\Aenv LD_RUN_PATH=(.*)\Z} ) {
334 $ldflags .= " -L$1 -lperl";
335 # Should we check the 32-ness?
336 $swig_flags = '-DNEED_LONG';
337 } elsif ('darwin' eq $Config{osname}) {
338 $ldflags .= " -bundle -flat_namespace";
341 my $class = Module::Build->subclass( code => $code );
343 my $builder = $class->new(
344 module_name => 'Math::GSL',
345 add_to_cleanup => [ q{*.core Math-GSL-* tmp* *_wrap.c *.pm pod2ht*.tmp _build *.so *.orig} ],
346 create_makefile_pl => 'passthrough',
347 dist_abstract => 'Interface to the GNU Scientific Library using SWIG',
348 dist_author => 'Jonathan Leto <jonathan@leto.net>',
349 dist_version_from => 'lib/Math/GSL.pm',
350 include_dirs => q{},
351 extra_linker_flags => '-shared -I./lib -I../lib -I/usr/local/include/ ' . $ldflags,
352 extra_compiler_flags=> q{-shared -Wall -fpic -Dbool=char -I/usr/local/include/ } . $ccflags,
353 swig_flags => $swig_flags,
354 swig_installed => $swig_installed,
355 license => 'gpl',
356 requires => {
357 'ExtUtils::PkgConfig' => '1.03',
358 'Scalar::Util' => 0,
359 'Test::More' => 0,
360 'Test::Class' => 0,
361 version => 0,
362 perl => '5.8.6',
364 sign => 1,
365 swig_source => [
366 map { [ "$_.i" ] }
367 qw/
368 BLAS Diff Machine Permute Statistics
369 Block Eigen Matrix Poly Sum
370 Bspline Errno PowInt Sys
371 CBLAS FFT Min
372 CDF Fit Mode QRNG Types
373 Chebyshev Function Monte RNG Vector
374 Heapsort Multifit Randist
375 Combination Histogram Multimin Roots Wavelet
376 Complex Histogram2d Multiroots SF Wavelet2D
377 Const NAN Siman
378 DFT Integration Ntuple Sort
379 DHT Interp ODEIV
380 Deriv Linalg Permutation Spline
385 $builder->add_build_element('swig');
386 $builder->create_build_script();