3 # This script has been heavily modified from the Device::Cdio Build.PL
4 # Jonathan Leto <jonathan@leto.net>
6 # Copyright (C) 2006 Rocky Bernstein <rocky@cpan.org>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 require Module
::Build
;
29 require ExtUtils
::PkgConfig
;
31 die "Math::GSL requires Module::Build and ExtUtils::PkgConfig, please install these first.\n" if $@
;
37 use File::Spec::Functions qw/:ALL/;
39 sub process_swig_files {
41 my $p = $self->{properties};
42 return unless $p->{swig_source};
43 my $files_ref = $p->{swig_source};
44 foreach my $file (@$files_ref) {
45 $self->process_swig($file->[0], $file->[1]);
49 # Check check dependencies for $main_swig_file. These are the
50 # %includes. If needed, arrange to run swig on $main_swig_file to
51 # produce a xxx_wrap.c C file.
54 my ($self, $main_swig_file, $deps_ref) = @_;
55 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
57 # File name. e.g, perlcdio.swg -> perlcdio_wrap.c
58 (my $file_base = $main_swig_file) =~ s/\.[^.]+$//;
59 my $c_file = "${file_base}_wrap.c";
61 if ($p->{swig_installed}) {
63 $self->add_to_cleanup($c_file);
65 # If any of the swig files that the main swig depends is newer
67 foreach my $depends_on ($main_swig_file, @$deps_ref) {
68 unless ($self->up_to_date($depends_on, $c_file)) {
69 $self->compile_swig($main_swig_file, $c_file);
70 # Only need to build $c_file once no matter how many
78 my $obj_file = $self->compile_c($c_file);
79 $self->add_to_cleanup($obj_file);
81 # The .so files don't go in blib/lib/, they go in blib/arch/auto/.
82 # Unfortunately we have to pre-compute the whole path.
85 my @dirs = splitdir($file_base);
86 $archdir = catdir($self->blib,'arch', @dirs[1..$#dirs]);
90 $self->link_c($archdir, $file_base, $obj_file);
93 # Invoke swig with -perl -outdir and other options.
95 my ($self, $file, $c_file) = @_;
96 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
98 # File name, minus the suffix
99 (my $file_base = $file) =~ s/\.[^.]+$//;
102 if (defined($p->{swig})) {
103 @swig = $self->split_like_shell($p->{swig});
107 if (defined($p->{swig_flags})) {
108 @swig_flags = $self->split_like_shell($p->{swig_flags});
113 push @swig_flags, $self->split_like_shell( qq{-module Math::GSL::$file_base} );
115 my $blib_lib = catfile(qw/blib lib/);
117 mkdir catfile($blib_lib, qw/Math GSL/);
118 my $outdir = catfile($blib_lib, qw/Math GSL/);
120 $self->do_system(@swig, '-o', $c_file,
122 '-perl5', @swig_flags, $file)
123 or die "error building $c_file file from '$file'";
125 my $pm_file = "${file_base}.pm";
126 my $from = catfile($blib_lib, qw/Math GSL/, $pm_file);
127 my $to = catfile(qw/lib Math GSL/,$pm_file);
129 print "Copying from: $from, to: $to; it makes the CPAN indexer happy.\n";
134 # From Base.pm but modified for a SWIG conventions.
135 # We just pass a $obj_file parameter
136 # SWIG objects have a get created with _wrap added. For example
137 # perlcdio.swg produces perlcdio_wrap.c, and perlcdio_wrap.o.
138 # But the shared object is still perlcdio.so.
139 # Also we modified the die to report the full file name.
141 my ($self, $to, $file_base, $obj_file) = @_;
142 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
144 my $lib_file = catfile($to, File::Basename::basename("$file_base.so"));
146 $self->add_to_cleanup($lib_file);
147 my $objects = $p->{objects} || [];
149 unless ($self->up_to_date([$obj_file, @$objects], $lib_file)) {
150 my @linker_flags = $self->split_like_shell($p->{extra_linker_flags});
151 my @lddlflags = $self->split_like_shell($cf->{lddlflags});
152 my @shrp = $self->split_like_shell($cf->{shrpenv});
153 my @ld = $self->split_like_shell($cf->{ld}) || "gcc";
154 $self->do_system(@shrp, @ld, @lddlflags, @user_libs, '-o', $lib_file,
155 $obj_file, @$objects, @linker_flags)
156 or die "error building $lib_file file from '$obj_file'";
162 # From Base.pm but modified to put package cflags *after*
163 # installed c flags so warning-removal will have an effect.
166 my ($self, $file) = @_;
167 my ($cf, $p) = ($self->{config}, $self->{properties}); # For convenience
169 # File name, minus the suffix
170 (my $file_base = $file) =~ s/\.[^.]+$//;
171 my $obj_file = "$file_base.so";
172 $self->add_to_cleanup($obj_file);
173 return $obj_file if $self->up_to_date($file, $obj_file);
176 $cf->{installarchlib} = $Config{archlib};
178 my @include_dirs = @{$p->{include_dirs}}
179 ? map {"-I$_"} (@{$p->{include_dirs}}, catdir($cf->{installarchlib}, 'CORE'))
180 : map {"-I$_"} ( catdir($cf->{installarchlib}, 'CORE') ) ;
182 my @extra_compiler_flags = #split / /, q{-shared -Wall -fpic -Dbool=char -I/usr/local/include/};
183 $self->split_like_shell($p->{extra_compiler_flags
});
185 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags
});
187 my @ccflags = $self->split_like_shell($cf->{ccflags
});
188 my @optimize = $self->split_like_shell($cf->{optimize
});
190 # Whoah! There seems to be a bug in gcc 4.1.0 and optimization
191 # and swig. I'm not sure who's at fault. But for now the simplest
192 # thing is to turn off all optimization. For the kinds of things that
193 # SWIG does - do conversions between parameters and transfers calls
194 # I doubt optimization makes much of a difference. But if it does,
195 # it can be added back via @extra_compiler_flags.
197 my @flags = (@include_dirs, @cccdlflags, '-c', @ccflags,
198 @extra_compiler_flags,
201 my @cc = $self->split_like_shell($cf->{cc
});
202 @cc = "gcc" unless @cc;
204 $self->do_system(@cc, @flags, '-o', $obj_file, $file)
205 or die "error building $cf->{obj_ext} file from '$file'";
220 my $obj_ext = $Config{obj_ext
} || ".o";
221 unlink("$tmp.c", "$tmp$obj_ext");
223 if (open(TMPC
, ">", "$tmp.c")) {
227 my $cccmd = $args{cccmd
};
229 my $ccflags = $Config{'ccflags'};
230 $ccflags .= " $args{ccflags}" if $args{ccflags
};
232 if ($args{silent
} ) {
233 $errornull = "2>/dev/null" unless defined $errornull;
238 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c $errornull"
239 unless defined $cccmd;
241 printf "cccmd = $cccmd\n" if $args{verbose
};
242 my $res = system($cccmd);
243 $ok = defined($res) && $res == 0;
250 *** The test compile of '$tmp.c' failed: status $?
251 *** (the status means: errno = $errno or '$!')
252 *** DO NOT PANIC: this just means that *some* you may get some innocuous
253 *** compiler warnings.
264 my $c_prog = "int main () { return 0; }\n";
265 print "Checking if $Config{cc} supports \"$ccflags\"...";
266 my $result = try_compile
($c_prog, ccflags
=>$ccflags);
276 print "Checking for GSL..";
277 my %gsl_pkgcfg = ExtUtils
::PkgConfig
->find ('gsl');
279 use constant MIN_GSL_VERSION
=> "1.11";
280 my $gv = $gsl_pkgcfg{'modversion'};
283 if ($gv =~ m{\A(\d+(?:\.\d+)+)}) {
284 my @current= split /\./, $1;
285 my @min= split /\./, MIN_GSL_VERSION
;
286 unless ($current[0] >= $min[0] && $current[1] >= $min[1]) {
289 *** You need to have GSL %s or greater installed. (You have $gv).
290 *** Get GSL at http://www.gnu.org/software/gsl
294 print "Found GSL version $gv\n";
300 *** Can't parse GSL version $gv.
301 *** Will continue and keep my fingers crossed for luck.
307 *** Can't find GSL configuration info. Is GSL installed?
308 *** Get GSL at http://www.gnu.org/software/gsl
313 print "Checking for SWIG...";
314 my @swig_version = `swig -version 2>&1`;
315 my $swig_installed = 0;
319 *** I don't see SWIG installed. I'll use the SWIG-generated file
320 *** that comes with the distribution. If you want SWIG, get it
321 *** from http://www.swig.org
323 print "*** Output was:
328 print qq{Found
$swig_version[1]};
331 my $ccflags = $gsl_pkgcfg{cflags
};
333 ## Swig produces a number of GCC warnings. Turn them off if we can.
334 $ccflags .= try_cflags
("-Wno-strict-aliasing");
335 $ccflags .= try_cflags
("-Wno-unused-function");
336 $ccflags .= try_cflags
("-Wno-unused-value");
337 $ccflags .= try_cflags
("-Wno-unused-function");
338 $ccflags .= try_cflags
("-Wno-unused-variable");
340 my $ldflags = "$gsl_pkgcfg{libs} -gsl";
341 my $swig_flags='-Wall';
342 if ('cygwin' eq $Config{osname
} &&
343 $Config{shrpenv
} =~ m{\Aenv LD_RUN_PATH=(.*)\Z} ) {
344 $ldflags .= " -L$1 -lperl";
345 # Should we check the 32-ness?
346 $swig_flags = '-DNEED_LONG';
347 } elsif ('darwin' eq $Config{osname
}) {
348 $ldflags .= " -bundle -flat_namespace";
351 my $class = Module
::Build
->subclass( code
=> $code );
352 my @Subsystems = sort qw
/
353 BLAS Diff Machine Statistics Wavelet
354 Block Eigen Matrix Poly Wavelet2D
355 BSpline Errno PowInt Sys
359 Heapsort Multifit Randist Sum
360 Combination Histogram Multimin Roots
361 Complex Histogram2D Multiroots SF
362 Const Siman IEEEUtils Types
363 DFT Integration NTuple Sort
364 DHT Interp ODEIV Vector
365 Deriv Linalg Permutation Spline
367 my $cleanup = qq{*.core Makefile Math
-GSL
-* tmp
* *_wrap
.c
*.pm pod2ht
*.tmp _build blib
*.so
*.orig
} .
368 join (" ", map { qq{lib
/Math/GSL
/$_.pm
} } @Subsystems);
370 my $builder = $class->new(
371 module_name
=> 'Math::GSL',
372 add_to_cleanup
=> [ $cleanup ],
373 create_makefile_pl
=> 'passthrough',
374 dist_abstract
=> 'Interface to the GNU Scientific Library using SWIG',
375 dist_author
=> 'Jonathan Leto <jonathan@leto.net>',
376 dist_version_from
=> 'lib/Math/GSL.pm',
378 extra_linker_flags
=> '-shared -I./lib -I../lib -I/usr/local/include/ ' . $ldflags,
379 extra_compiler_flags
=> q{-shared -Wall -fpic -Dbool=char -I/usr/local/include/ } . $ccflags,
380 swig_flags
=> $swig_flags,
381 swig_installed
=> $swig_installed,
384 'ExtUtils::PkgConfig' => '1.03',
387 'Test::Exception' => 0.21,
388 'Test::Class' => 0.12,
394 map { [ "$_.i" ] } @Subsystems
397 $builder->add_build_element('swig');
398 $builder->create_build_script();
399 print "Have a great day!\n";