Add .gitignore so that "git status" isn't noisy.
[Math-GSL.git] / Build.PL
blob4a6671eca3157d1068a07f66d89472ede730326f
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} ],
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 Block CDF Complex
369 Const Deriv Errno
370 Fit Function Machine Matrix
371 Min ODEIV Poly
372 PowInt Randist RNG
373 Roots SF Types
374 Vector Wavelet2D
379 $builder->add_build_element('swig');
380 $builder->create_build_script();