Update META.yml
[Math-GSL.git] / Build.PL
blob8a5c011059f0fce6fad097fcc91ed002350a5520
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;
25 BEGIN {
26 eval {
27 require Module::Build;
28 require ExtUtils::PkgConfig;
30 die "Math::GSL requires Module::Build and ExtUtils::PkgConfig, please install these first.\n" if $@;
33 my $code = <<'EOC';
34 use Config;
35 use File::Copy;
36 use File::Spec::Functions qw/:ALL/;
38 sub process_swig_files {
39 my $self = shift;
40 my $p = $self->{properties};
41 return unless $p->{swig_source};
42 my $files_ref = $p->{swig_source};
43 foreach my $file (@$files_ref) {
44 $self->process_swig($file->[0], $file->[1]);
48 # Check check dependencies for $main_swig_file. These are the
49 # %includes. If needed, arrange to run swig on $main_swig_file to
50 # produce a xxx_wrap.c C file.
52 sub process_swig {
53 my ($self, $main_swig_file, $deps_ref) = @_;
54 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
56 # File name. e.g, perlcdio.swg -> perlcdio_wrap.c
57 (my $file_base = $main_swig_file) =~ s/\.[^.]+$//;
58 my $c_file = "${file_base}_wrap.c";
60 # .swg -> .c
61 $self->add_to_cleanup($c_file);
63 # If any of the swig files that the main swig depends is newer
64 # then rebuild.
65 foreach my $depends_on ($main_swig_file, @$deps_ref) {
66 unless ($self->up_to_date($depends_on, $c_file)) {
67 $self->compile_swig($main_swig_file, $c_file);
68 # Only need to build $c_file once no matter how many
69 # includes there are.
70 last;
74 # .c -> .o
75 my $obj_file = $self->compile_c($c_file);
76 $self->add_to_cleanup($obj_file);
78 # The .so files don't go in blib/lib/, they go in blib/arch/auto/.
79 # Unfortunately we have to pre-compute the whole path.
80 my $archdir;
82 my @dirs = splitdir($file_base);
83 $archdir = catdir($self->blib,'arch', @dirs[1..$#dirs]);
86 # .o -> .so
87 $self->link_c($archdir, $file_base, $obj_file);
90 # Invoke swig with -perl -outdir and other options.
91 sub compile_swig {
92 my ($self, $file, $c_file) = @_;
93 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
95 # File name, minus the suffix
96 (my $file_base = $file) =~ s/\.[^.]+$//;
98 my @swig;
99 if (defined($p->{swig})) {
100 @swig = $self->split_like_shell($p->{swig});
101 } else {
102 @swig = ('swig');
104 if (defined($p->{swig_flags})) {
105 @swig_flags = $self->split_like_shell($p->{swig_flags});
106 } else {
107 @swig_flags = ();
110 my $blib_lib = catfile(qw/blib lib/);
112 mkdir catfile($blib_lib, qw/Math GSL/);
113 my $outdir = catfile($blib_lib, qw/Math GSL/);
114 my $pm_file = "${file_base}.pm";
115 my $from = catfile($blib_lib, qw/Math GSL/, $pm_file);
116 my $to = catfile(qw/lib Math GSL/,$pm_file);
117 chmod 0644, $from, $to;
119 $self->do_system(@swig, '-o', $c_file,
120 '-outdir', $outdir,
121 '-perl5', @swig_flags, $file)
122 or die "error building $c_file file from '$file'";
125 print "Copying from: $from, to: $to; it makes the CPAN indexer happy.\n";
126 copy($from,$to);
127 return $c_file;
130 # From Base.pm but modified for a SWIG conventions.
131 # We just pass a $obj_file parameter
132 # SWIG objects have a get created with _wrap added. For example
133 # perlcdio.swg produces perlcdio_wrap.c, and perlcdio_wrap.o.
134 # But the shared object is still perlcdio.so.
135 # Also we modified the die to report the full file name.
136 sub link_c {
137 my ($self, $to, $file_base, $obj_file) = @_;
138 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
140 my $lib_file = catfile($to, File::Basename::basename("$file_base.so"));
142 $self->add_to_cleanup($lib_file);
143 my $objects = $p->{objects} || [];
145 unless ($self->up_to_date([$obj_file, @$objects], $lib_file)) {
146 my @linker_flags = $self->split_like_shell($p->{extra_linker_flags});
147 my @lddlflags = $self->split_like_shell($cf->{lddlflags});
148 my @shrp = $self->split_like_shell($cf->{shrpenv});
149 my @ld = $self->split_like_shell($cf->{ld}) || "gcc";
150 $self->do_system(@shrp, @ld, @lddlflags, @user_libs, '-o', $lib_file,
151 $obj_file, @$objects, @linker_flags)
152 or die "error building $lib_file file from '$obj_file'";
155 return $lib_file;
158 # From Base.pm but modified to put package cflags *after*
159 # installed c flags so warning-removal will have an effect.
161 sub compile_c {
162 my ($self, $file) = @_;
163 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
165 # File name, minus the suffix
166 (my $file_base = $file) =~ s/\.[^.]+$//;
167 my $obj_file = $file_base . $Config{_o};
169 $self->add_to_cleanup($obj_file);
170 return $obj_file if $self->up_to_date($file, $obj_file);
173 $cf->{installarchlib} = $Config{archlib};
175 my @include_dirs = @{$p->{include_dirs}}
176 ? map {"-I$_"} (@{$p->{include_dirs}}, catdir($cf->{installarchlib}, 'CORE'))
177 : map {"-I$_"} ( catdir($cf->{installarchlib}, 'CORE') ) ;
179 my @extra_compiler_flags = $self->split_like_shell($p->{extra_compiler_flags});
181 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
183 my @ccflags = $self->split_like_shell($cf->{ccflags});
184 my @optimize = $self->split_like_shell($cf->{optimize});
186 # Whoah! There seems to be a bug in gcc 4.1.0 and optimization
187 # and swig. I'm not sure who's at fault. But for now the simplest
188 # thing is to turn off all optimization. For the kinds of things that
189 # SWIG does - do conversions between parameters and transfers calls
190 # I doubt optimization makes much of a difference. But if it does,
191 # it can be added back via @extra_compiler_flags.
193 my @flags = (@include_dirs, @cccdlflags, '-c', @ccflags, @extra_compiler_flags, );
195 my @cc = $self->split_like_shell($cf->{cc});
196 @cc = "gcc" unless @cc;
198 $self->do_system(@cc, @flags, '-o', $obj_file, $file)
199 or die "error building $Config{_o} file from '$file'";
201 return $obj_file;
207 sub try_compile {
208 my ($c, %args) = @_;
210 my $ok = 0;
211 my $tmp = "tmp$$";
212 local(*TMPC);
214 my $obj_ext = $Config{_o} || ".o";
215 unlink("$tmp.c", "$tmp$obj_ext");
217 if (open(TMPC, ">", "$tmp.c")) {
218 print TMPC $c;
219 close(TMPC);
221 my $cccmd = $args{cccmd};
222 my $errornull;
223 my $ccflags = $Config{'ccflags'};
224 $ccflags .= " $args{ccflags}" if $args{ccflags};
226 if ($args{silent} ) {
227 $errornull = "2>/dev/null" unless defined $errornull;
228 } else {
229 $errornull = '';
232 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c $errornull"
233 unless defined $cccmd;
235 printf "cccmd = $cccmd\n" if $args{verbose};
236 my $res = system($cccmd);
237 $ok = defined($res) && $res == 0;
239 if ( !$ok ) {
240 my $errno = $? >> 8;
241 local $! = $errno;
242 print "
244 *** The test compile of '$tmp.c' failed: status $?
245 *** (the status means: errno = $errno or '$!')
246 *** DO NOT PANIC: this just means that *some* you may get some innocuous
247 *** compiler warnings.
250 unlink("$tmp.c");
253 return $ok;
256 sub try_cflags ($) {
257 my ($ccflags) = @_;
258 my $c_prog = "int main () { return 0; }\n";
259 print "Checking if $Config{cc} supports \"$ccflags\"...";
260 my $result = try_compile($c_prog, ccflags=>$ccflags);
261 if ($result) {
262 print "yes\n";
263 return " $ccflags";
265 print "no\n";
266 return '';
270 print "Checking for GSL..";
271 my %gsl_pkgcfg = ExtUtils::PkgConfig->find ('gsl');
273 my $MIN_GSL_VERSION = "1.11";
274 my $gv = $gsl_pkgcfg{'modversion'};
276 if (defined $gv) {
277 if ($gv =~ m{\A(\d+(?:\.\d+)+)}) {
278 my @current= split /\./, $1;
279 my @min= split /\./, $MIN_GSL_VERSION;
280 unless ($current[0] >= $min[0] && $current[1] >= $min[1]) {
281 printf "
282 ***
283 *** You need to have GSL %s or greater installed. (You have $gv).
284 *** Get GSL at http://www.gnu.org/software/gsl\n", $MIN_GSL_VERSION;
285 exit 1;
286 } else {
287 print "Found GSL version $gv\n";
290 } else {
291 print "
292 ***
293 *** Can't parse GSL version $gv.
294 *** Will continue and keep my fingers crossed for luck.
297 } else {
298 print "
299 ***
300 *** Can't find GSL configuration info. Is GSL installed?
301 *** Get GSL at http://www.gnu.org/software/gsl
303 exit 1;
307 my $ccflags = $gsl_pkgcfg{cflags};
309 ## Swig produces a number of GCC warnings. Turn them off if we can.
310 $ccflags .= try_cflags("-Wno-strict-aliasing");
311 $ccflags .= try_cflags("-Wno-unused-function");
312 $ccflags .= try_cflags("-Wno-unused-value");
313 $ccflags .= try_cflags("-Wno-unused-function");
314 $ccflags .= try_cflags("-Wno-unused-variable");
316 my $ldflags = "$gsl_pkgcfg{libs} -gsl";
317 my $swig_flags='-Wall ' . $gsl_pkgcfg{cflags};
319 if ('cygwin' eq $Config{osname} &&
320 $Config{shrpenv} =~ m{\Aenv LD_RUN_PATH=(.*)\Z} ) {
321 $ldflags .= " -L$1 -lperl";
322 # Should we check the 32-ness?
323 $swig_flags = '-DNEED_LONG';
324 } elsif ('darwin' eq $Config{osname}) {
325 $ldflags .= " -bundle -flat_namespace";
328 my $class = Module::Build->subclass( code => $code );
329 my @Subsystems = sort qw/
330 BLAS Diff Machine Statistics Wavelet
331 Block Eigen Matrix Poly Wavelet2D
332 BSpline Errno PowInt
333 CBLAS FFT Min
334 CDF Fit Mode QRNG
335 Chebyshev Monte RNG
336 Heapsort Multifit Randist Sum
337 Combination Histogram Multimin Roots
338 Complex Histogram2D Multiroots SF
339 Const Siman IEEEUtils Sys
340 Integration NTuple Sort
341 DHT Interp ODEIV Vector
342 Deriv Linalg Permutation Spline
344 my $cleanup = qq{*.core Makefile Math-GSL-* tmp* pod2ht*.tmp _build blib *.so *.orig };
346 my $builder = $class->new(
347 module_name => 'Math::GSL',
348 add_to_cleanup => [ $cleanup ],
349 create_makefile_pl => 'passthrough',
350 dist_abstract => 'Interface to the GNU Scientific Library using SWIG',
351 dist_author => 'Jonathan Leto <jonathan@leto.net>',
352 dist_version_from => 'lib/Math/GSL.pm',
353 include_dirs => q{},
354 extra_linker_flags => '-shared -I./lib -I../lib ' . $ldflags,
355 extra_compiler_flags=> q{-shared -Wall -fpic -Dbool=char } . $ccflags,
356 swig_flags => $swig_flags,
357 license => 'gpl',
358 requires => {
359 'ExtUtils::PkgConfig' => '1.03',
360 'Scalar::Util' => 0,
361 'Test::More' => 0,
362 'Test::Exception' => 0.21,
363 'Test::Class' => 0.12,
364 version => 0,
365 perl => '5.8.8',
367 sign => 1,
368 swig_source => [
369 map { [ "$_.i" ] } @Subsystems
372 $builder->add_build_element('swig');
373 $builder->create_build_script();
374 print "Have a great day!\n";