Merge branch 'bleed' of ssh://leto.net/git/Math-GSL into bleed
[Math-GSL.git] / Build.PL
blob08a11b12c739d5211beb5ead4ec3cc133e905dc0
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;
25 use ExtUtils::PkgConfig;
27 my $code = <<'EOC';
28 use Config;
29 use File::Copy;
30 use File::Spec::Functions qw/:ALL/;
32 sub process_swig_files {
33 my $self = shift;
34 my $p = $self->{properties};
35 return unless $p->{swig_source};
36 my $files_ref = $p->{swig_source};
37 foreach my $file (@$files_ref) {
38 $self->process_swig($file->[0], $file->[1]);
42 # Check check dependencies for $main_swig_file. These are the
43 # %includes. If needed, arrange to run swig on $main_swig_file to
44 # produce a xxx_wrap.c C file.
46 sub process_swig {
47 my ($self, $main_swig_file, $deps_ref) = @_;
48 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
50 # File name. e.g, perlcdio.swg -> perlcdio_wrap.c
51 (my $file_base = $main_swig_file) =~ s/\.[^.]+$//;
52 my $c_file = "${file_base}_wrap.c";
54 # .swg -> .c
55 $self->add_to_cleanup($c_file);
57 # If any of the swig files that the main swig depends is newer
58 # then rebuild.
59 foreach my $depends_on ($main_swig_file, @$deps_ref) {
60 unless ($self->up_to_date($depends_on, $c_file)) {
61 $self->compile_swig($main_swig_file, $c_file);
62 # Only need to build $c_file once no matter how many
63 # includes there are.
64 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 = splitdir($file_base);
77 $archdir = 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 my $blib_lib = catfile(qw/blib lib/);
106 mkdir catfile($blib_lib, qw/Math GSL/);
107 my $outdir = catfile($blib_lib, qw/Math GSL/);
108 my $pm_file = "${file_base}.pm";
109 my $from = catfile($blib_lib, qw/Math GSL/, $pm_file);
110 my $to = catfile(qw/lib Math GSL/,$pm_file);
111 chmod 0644, $from, $to;
113 $self->do_system(@swig, '-o', $c_file,
114 '-outdir', $outdir,
115 '-perl5', @swig_flags, $file)
116 or die "error building $c_file file from '$file'";
119 print "Copying from: $from, to: $to; it makes the CPAN indexer happy.\n";
120 copy($from,$to);
121 return $c_file;
124 # From Base.pm but modified for a SWIG conventions.
125 # We just pass a $obj_file parameter
126 # SWIG objects have a get created with _wrap added. For example
127 # perlcdio.swg produces perlcdio_wrap.c, and perlcdio_wrap.o.
128 # But the shared object is still perlcdio.so.
129 # Also we modified the die to report the full file name.
130 sub link_c {
131 my ($self, $to, $file_base, $obj_file) = @_;
132 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
134 my $lib_file = catfile($to, File::Basename::basename("$file_base.so"));
136 $self->add_to_cleanup($lib_file);
137 my $objects = $p->{objects} || [];
139 unless ($self->up_to_date([$obj_file, @$objects], $lib_file)) {
140 my @linker_flags = $self->split_like_shell($p->{extra_linker_flags});
141 my @lddlflags = $self->split_like_shell($cf->{lddlflags});
142 my @shrp = $self->split_like_shell($cf->{shrpenv});
143 my @ld = $self->split_like_shell($cf->{ld}) || "gcc";
144 $self->do_system(@shrp, @ld, @lddlflags, @user_libs, '-o', $lib_file,
145 $obj_file, @$objects, @linker_flags)
146 or die "error building $lib_file file from '$obj_file'";
149 return $lib_file;
152 # From Base.pm but modified to put package cflags *after*
153 # installed c flags so warning-removal will have an effect.
155 sub compile_c {
156 my ($self, $file) = @_;
157 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
159 # File name, minus the suffix
160 (my $file_base = $file) =~ s/\.[^.]+$//;
161 my $obj_file = $file_base . $Config{_o};
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}}, catdir($cf->{installarchlib}, 'CORE'))
171 : map {"-I$_"} ( catdir($cf->{installarchlib}, 'CORE') ) ;
173 my @extra_compiler_flags = $self->split_like_shell($p->{extra_compiler_flags});
175 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
177 my @ccflags = $self->split_like_shell($cf->{ccflags});
178 my @optimize = $self->split_like_shell($cf->{optimize});
180 # Whoah! There seems to be a bug in gcc 4.1.0 and optimization
181 # and swig. I'm not sure who's at fault. But for now the simplest
182 # thing is to turn off all optimization. For the kinds of things that
183 # SWIG does - do conversions between parameters and transfers calls
184 # I doubt optimization makes much of a difference. But if it does,
185 # it can be added back via @extra_compiler_flags.
187 my @flags = (@include_dirs, @cccdlflags, '-c', @ccflags, @extra_compiler_flags, );
189 my @cc = $self->split_like_shell($cf->{cc});
190 @cc = "gcc" unless @cc;
192 $self->do_system(@cc, @flags, '-o', $obj_file, $file)
193 or die "error building $Config{_o} file from '$file'";
195 return $obj_file;
201 sub try_compile {
202 my ($c, %args) = @_;
204 my $ok = 0;
205 my $tmp = "tmp$$";
206 local(*TMPC);
208 my $obj_ext = $Config{_o} || ".o";
209 unlink("$tmp.c", "$tmp$obj_ext");
211 if (open(TMPC, ">", "$tmp.c")) {
212 print TMPC $c;
213 close(TMPC);
215 my $cccmd = $args{cccmd};
216 my $errornull;
217 my $ccflags = $Config{'ccflags'};
218 $ccflags .= " $args{ccflags}" if $args{ccflags};
220 if ($args{silent} ) {
221 $errornull = "2>/dev/null" unless defined $errornull;
222 } else {
223 $errornull = '';
226 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c $errornull"
227 unless defined $cccmd;
229 printf "cccmd = $cccmd\n" if $args{verbose};
230 my $res = system($cccmd);
231 $ok = defined($res) && $res == 0;
233 if ( !$ok ) {
234 my $errno = $? >> 8;
235 local $! = $errno;
236 print "
238 *** The test compile of '$tmp.c' failed: status $?
239 *** (the status means: errno = $errno or '$!')
240 *** DO NOT PANIC: this just means that *some* you may get some innocuous
241 *** compiler warnings.
244 unlink("$tmp.c");
247 return $ok;
250 sub try_cflags ($) {
251 my ($ccflags) = @_;
252 my $c_prog = "int main () { return 0; }\n";
253 print "Checking if $Config{cc} supports \"$ccflags\"...";
254 my $result = try_compile($c_prog, ccflags=>$ccflags);
255 if ($result) {
256 print "yes\n";
257 return " $ccflags";
259 print "no\n";
260 return '';
264 print "Checking for GSL..";
265 my %gsl_pkgcfg = ExtUtils::PkgConfig->find ('gsl');
267 my $MIN_GSL_VERSION = "1.11";
268 my $gv = $gsl_pkgcfg{'modversion'};
270 if (defined $gv) {
271 if ($gv =~ m{\A(\d+(?:\.\d+)+)}) {
272 my @current= split /\./, $1;
273 my @min= split /\./, $MIN_GSL_VERSION;
274 unless ($current[0] >= $min[0] && $current[1] >= $min[1]) {
275 printf "
276 ***
277 *** You need to have GSL %s or greater installed. (You have $gv).
278 *** Get GSL at http://www.gnu.org/software/gsl\n", $MIN_GSL_VERSION;
279 exit 1;
280 } else {
281 print "Found GSL version $gv\n";
284 } else {
285 print "
286 ***
287 *** Can't parse GSL version $gv.
288 *** Will continue and keep my fingers crossed for luck.
291 } else {
292 print "
293 ***
294 *** Can't find GSL configuration info. Is GSL installed?
295 *** Get GSL at http://www.gnu.org/software/gsl
297 exit 1;
301 my $ccflags = $gsl_pkgcfg{cflags};
303 ## Swig produces a number of GCC warnings. Turn them off if we can.
304 $ccflags .= try_cflags("-Wno-strict-aliasing");
305 $ccflags .= try_cflags("-Wno-unused-function");
306 $ccflags .= try_cflags("-Wno-unused-value");
307 $ccflags .= try_cflags("-Wno-unused-function");
308 $ccflags .= try_cflags("-Wno-unused-variable");
310 my $ldflags = "$gsl_pkgcfg{libs} -gsl";
311 my $swig_flags='-Wall ' . $gsl_pkgcfg{cflags};
313 if ('cygwin' eq $Config{osname} &&
314 $Config{shrpenv} =~ m{\Aenv LD_RUN_PATH=(.*)\Z} ) {
315 $ldflags .= " -L$1 -lperl";
316 # Should we check the 32-ness?
317 $swig_flags = '-DNEED_LONG';
318 } elsif ('darwin' eq $Config{osname}) {
319 $ldflags .= " -bundle -flat_namespace";
322 my $class = Module::Build->subclass( code => $code );
323 my @Subsystems = sort qw/
324 BLAS Diff Machine Statistics Wavelet
325 Block Eigen Matrix Poly Wavelet2D
326 BSpline Errno PowInt
327 CBLAS FFT Min
328 CDF Fit Mode QRNG
329 Chebyshev Monte RNG
330 Heapsort Multifit Randist Sum
331 Combination Histogram Multimin Roots
332 Complex Histogram2D Multiroots SF
333 Const Siman IEEEUtils Sys
334 Integration NTuple Sort
335 DHT Interp ODEIV Vector
336 Deriv Linalg Permutation Spline
338 my $cleanup = qq{core *.core Makefile Math-GSL-* tmp* pod2ht*.tmp _build blib *.so *.orig };
340 my $builder = $class->new(
341 module_name => 'Math::GSL',
342 add_to_cleanup => [ $cleanup ],
343 create_makefile_pl => 'passthrough',
344 dist_abstract => 'Interface to the GNU Scientific Library using SWIG',
345 dist_author => 'Jonathan Leto <jonathan@leto.net>',
346 dist_version_from => 'lib/Math/GSL.pm',
347 include_dirs => q{},
348 extra_linker_flags => '-shared -I./lib -I../lib ' . $ldflags,
349 extra_compiler_flags=> q{-shared -Wall -fpic -Dbool=char } . $ccflags,
350 swig_flags => $swig_flags,
351 license => 'gpl',
352 requires => {
353 'ExtUtils::PkgConfig' => '1.03',
354 'Scalar::Util' => 0,
355 'Test::More' => 0,
356 'Test::Exception' => 0.21,
357 'Test::Class' => 0.12,
358 version => 0,
359 perl => '5.8.8',
361 sign => 0,
362 swig_source => [
363 map { [ "$_.i" ] } @Subsystems
366 $builder->add_build_element('swig');
367 $builder->create_build_script();
368 print "Have a great day!\n";