| ExtUtils-Autoconf documentation | Contained in the ExtUtils-Autoconf distribution. |
ExtUtils::Autoconf - Perl interface to GNU autoconf
Version 0.02
use ExtUtils::Autoconf;
my $ac = ExtUtils::Autoconf->new;
$ac->autogen;
$ac->configure;
$ac->clean;
$ac->realclean;
ExtUtils::Autoconf is a thin wrapper around GNU autoconf/autoheader which allows to run those tools easily from perl. This allows using autoconf for configuring perl modules and especially extensions in a portable way without messing around with the compilation of C code from perl.
Typically ExtUtils::Autoconf is being used from Makefile.PLs in Perl module distributions.
To use it in your module you first need to create a directory called
autoconf (or call it something else and set wd accordingly. This is the
working directory for ExtUtils::Autoconf and the programs it invokes.
Create a configure.ac or configure.in file in this directory. This file
contains invocations of autoconf macros that test the system features
your package needs or can use. Autoconf macros already exist to check for many
features; see Existing Tests,
for heir descriptions. For most other features, you can use Autoconf template
macros to produce custom checks; see Writing Tests,
for information about them.
A typical configure.ac might look like this:
AC_PREREQ(2.50)
AC_INIT
AC_CONFIG_HEADERS([config.h])
AC_DEFINE_UNQUOTED(PERL_OSNAME, "$osname", [The operating system perl was ocnfigured for])
AC_OUTPUT
In this script we first require autoconf version 2.50, then initialize the
system and tell it to create a config header file called config.h with the
results it gathered while running the configure script.
In this script we only have one result called PERL_OSNAME. This is simply
set to the value of the environment variable $osname, which corresponds to
perls $Config{osname}.
After our tests we do AC_OUTPUT to write our results to config.h.
That's it for the configure.ac part. Now include the autoconf/config.h
file in your C or C++ code of the module and use the defines in there.
Execute the configure script which will be generated from the above
configure.ac when someone tries to build your module you'll need to modify
your Makefile.PL script.
It's better to assume that the user of your module doesn't have autoconf and
autoheader installed so you need to generate configure and config.h
before rolling your distribution together.
This is easily done by using the dist target of your generated Makefile:
WriteMakefile(
# usual arguments to WriteMakefile()..
dist => {
PREOP => q{$(PERLRUN) -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_autogen'},
},
);
autogen() and configure() automatically generate some files. To clean
those up automatically when doing make clean or make realclean you can
use MakeMakers postamble feature. We also add some additional Makefile targets
for the ease of use:
sub postamble {
return <<"EOM";
autogen :
\t\$(PERLRUN) -MExtUtils::Autoconf -e 'ExtUtils::Autoconf->run_autogen'
configure :
\t\$(PERLRUN) -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_configure'
autoclean :
\t\$(PERLRUN) -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_realclean'
realclean purge ::
\t\$(PERLRUN) -MExtUtils::Autoconf -e 'ExtUtils::Autoconf->run_realclean'
clean ::
\t\$(PERLRUN) -MExtUtils::Autoconf -e 'ExtUtils::Autoconf->run_clean'
EOM
}
Now everything will work, except for the actual execution of the configure
script during perl Makefile.PL. To make it work do something like this in
Makefile.PL:
use strict;
use warnings;
use ExtUtils::MakeMaker;
if (!eval 'use ExtUtils::Autoconf;') {
print STDERR $@, "\n";
WriteMakefile(
PREREQ_FATAL => 1,
PREREQ_PM => {
'ExtUtils::Autoconf' => 0,
},
);
exit 1; # not reached
}
my $ac = ExtUtils::Autoconf->new;
$ac->configure;
# rest of the usual Makefile.PL here..
The if condition covers those cases where ExtUtils::Autoconf isn't installed
yet. I'll raise a fatal error which will hopefully tell CPAN to install it and
rerun Makefile.PL.
If you're using Module::Install for your Makefile.PL, you can simply install Module::Install::Autoconf and do configure() in it.
my $ac = ExtUtils::Autoconf->new($arguments);
This is the constructor.. Takes an optional hashref with additional
$arguments. Returns a new ExtUtils::Autoconf instance.
The following arguments are supported:
wdThe working directory for autoconf. All commands issued by ExtUtils::Autoconf will be executed in this directory.
autoconfThe name of the autoconf executable.
autoheaderThe name of the autoheader executable.
envA hash reference with the environment variables which will be set for each program execution issued by ExtUtils::Autoconf.
The default looks like this:
{
MAKE => $Config{ make },
SHELL => $Config{ sh },
CC => $Config{ cc },
CPPFLAGS => $Config{ cppflags },
CFLAGS => $Config{ ccflags },
LDFLAGS => $Config{ ldflags },
LINKER => $Config{ ld },
LIBS => '',
%Config,
}
Where %Config is the local perl configuration from Config.pm. To add
additional environment variables or to override existing ones do:
my $ac = ExtUtils::Autoconf->new({
env => {
key1 => 'val1',
key2 => 'val2',
},
});
$ac->configure;
Runs the configure script. If the configure script doesn't exist yet it'll run autogen(). Returns 1 on success or croaks on failure.
$ac->autogen;
Runs autoheader and autoconf to generate config.h.in and configure from configure.ac or configure.in. Returns 1 on success or croaks on failure.
$ac->clean;
Cleans up files which were generated during configure(). Always returns something true.
my $success = $ac->realclean;
Cleans up files which were generated during autogen() and configure(). Always returns something true.
my $wd = $ac->wd;
$ac->wd($new_wd);
Accessor for the wd (working directory) option. When called without any
argument it returns the current working directory. When called with one
argument the working directory is set to $new_wd and the new working
directory is returned.
my $autoconf = $ac->autoconf;
$ac->autoconf($new_autoconf);
Accessor for the name of the autoconf executable.
my $autoheader = $ac->autoheader;
$ac->autoheader($new_autoheader);
Accessor for the name of the autoheader executable.
my $env = $ac->env;
my $value = $ac->env($key);
$ac->env($key => $value);
Accessor for the environment option. When called without any option it returns a hash reference with all the environment variables that will be set when running any command.
When called with one argument it'll return the value of the environment
variable corresponding to a given $key.
When called with two arguments the environment variable $key will be set to
$value.
perl -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_configure' $wd
This class method is intended to be used from Makefiles and similar things and
reads its arguments from @ARGV. It constructs a new ExtUtils::Autoconf
instance with the given $wd and runs configure().
perl -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_autogen' $wd, $autoconf, $autoheader
This class method is intended to be used from Makefiles and similar things and
reads its arguments from @ARGV. It constructs a new ExtUtils::Autoconf
instance with the given $wd, $autoconf, $autoheader and runs
autogen().
perl -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_clean' $wd
This class method is intended to be used from Makefiles and similar things and
reads its arguments from @ARGV. It constructs a new ExtUtils::Autoconf
instance with the given $wd and runs clean().
perl -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_realclean' $wd
This class method is intended to be used from Makefiles and similar things and
reads its arguments from @ARGV. It constructs a new ExtUtils::Autoconf
instance with the given $wd and runs realclean().
configure failed. Check %s/config.logRunning ./configure failed. Diagnostic messages may be found in the according config.log file.
autogen failed. check the error messages above.Running autoheader or autoconf failed. Probably your configure.ac is
erroneous. Try running autoheader and autoconf manually.
Florian Ragwitz <rafl@debian.org>
Please report any bugs or feature requests to <bug-extutils-autoconf@rt.cpan.org>, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ExtUtils-Autoconf. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
You can find documentation for this module with the perldoc command.
perldoc ExtUtils::Autoconf
You can also look for information at:
Marc Lehmann <schmorp@schmorp.de> for the idea and a prof-of-concept implementation (autoconf.pm) in IO::AIO.
Copyright 2006 Florian Ragwitz, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| ExtUtils-Autoconf documentation | Contained in the ExtUtils-Autoconf distribution. |
package ExtUtils::Autoconf; use strict; use warnings; use Cwd; use Config; use File::Spec; use File::Path qw(rmtree); use File::Which qw(which);
our $VERSION = '0.02';
sub new { my ($class, $args) = @_; my $self = { wd => 'autoconf', autoconf => (which('autoconf'))[0] || 'autoconf', autoheader => (which('autoheader'))[0] || 'autoheader', env => { MAKE => $Config{ make }, SHELL => $Config{ sh }, CC => $Config{ cc }, CPPFLAGS => $Config{ cppflags }, CFLAGS => $Config{ ccflags }, LDFLAGS => $Config{ ldflags }, LINKER => $Config{ ld }, LIBS => q{}, %Config, }, }; bless $self, $class; if (ref $args && ref $args eq 'HASH') { $self->_process_args($args); } return $self; } sub _process_args { my ($self, $args) = @_; while (my ($k, $v) = each %{ $args }) { next unless $self->can($k); if (!ref $v) { #plain scalar $self->$k($v); } elsif (ref $v eq 'HASH') { #hashref (env) while (my ($sk, $sv) = each %{ $v }) { $self->$k($sk => $sv); } } } }
sub configure { my ($self) = @_; my $configure = 'configure'; if (!-x File::Spec->catfile($self->wd, $configure)) { $self->autogen; } if (!$self->_run_cmd("./$configure", '--prefix='. "\Q$Config{prefix}\E")) { require Carp; Carp::croak( q{configure failed. Check } . File::Spec->catfile($self->wd, 'config.log') . q{.} ); } return 1; }
sub autogen { my ($self) = @_; my $ret = $self->_run_cmd($self->autoheader) && $self->_run_cmd($self->autoconf); if (!$ret) { require Carp; Carp::croak('autogen failed. check the error messages above.'); } return 1; } *reconf = \&autogen; #compat
sub clean { my ($self) = @_; for my $file (qw( config.h config.log config.status )) { my $path = File::Spec->catfile($self->wd, $file); next unless -f $path; unlink $path; } return 1; }
sub realclean { my ($self) = @_; $self->clean; for my $file (qw( config.h.in configure )) { my $path = File::Spec->catfile($self->wd, $file); next unless -f $path; unlink $path; } rmtree( File::Spec->catfile($self->wd, 'autom4te.cache'), 0, 0 ); return 1; }
sub wd { my $self = shift; if (@_) { $self->{wd} = shift; } return $self->{wd}; }
sub autoconf { my $self = shift; if (@_) { $self->{autoconf} = shift; } return $self->{autoconf}; }
sub autoheader { my $self = shift; if (@_) { $self->{autoheader} = shift; } return $self->{autoheader}; }
sub env { my $self = shift; if (scalar @_ == 1) { my ($key) = @_; return $self->{env}->{ $key }; } elsif (scalar @_ == 2) { my ($key, $val) = @_; $self->{env}->{ $key } = $val; return $self->{env}->{ $key }; } elsif (scalar @_ != 0) { require Carp; Carp::croak('ExtUtils::Config::env expects 0, 1 or 2 arguments'); } return $self->{env}; } sub _run_cmd { my ($self, $cmd, @args) = @_; my $cwd = cwd(); if (!chdir $self->wd) { require Carp; Carp::croak("Could not chdir to `". $self->wd ."'. Did you set the working dir correctly?"); } my $ret; { local %ENV = %ENV; while (my ($k, $v) = each %{ $self->{env} }) { next unless defined $v; $ENV{$k} = $v; } $ret = system $self->env('SHELL'), -c => "\Q$cmd\E ". join(q{ }, @args); } chdir $cwd; return ($ret == 0); }
sub run_configure { my ($class) = @_; my $ac = $class->new; $ac->_process_argv; $ac->configure; }
sub run_autogen { my ($class) = @_; my $ac = $class->new; $ac->_process_argv; $ac->autogen; }
sub run_clean { my ($class) = @_; my $ac = $class->new; $ac->_process_argv; $ac->clean; }
sub run_realclean { my ($class) = @_; my $ac = $class->new; $ac->_process_argv; $ac->realclean; } sub _process_argv { my ($self) = @_; my ($wd, $autoconf, $autoheader) = @ARGV; $self->wd($wd) if defined $wd; $self->autoconf($autoconf) if defined $autoconf; $self->autoheader($autoheader) if defined $autoheader; }
1; # End of ExtUtils::Autoconf