Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

RFC: ExtUtils::Autoconf

by rafl (Friar)
on Sep 03, 2006 at 21:49 UTC ( #570970=perlmeditation: print w/ replies, xml ) Need Help??

I already wrote several XS modules, especially library bindings, and the most painful part usually was the task of making the modules portable between different library versions and operating systems.

It's not very funny try to compile c or c++ programs in a portable way using perl, even if there are some helpers like ExtUtils::CBuilder available.

I always wished there would be something like autoconf and autoheader for perl, but I doubt it'll ever exist in a way that is comparable to GNU autotools.

Therefor I decided to write some perl glue around autoconf and autoheader so those tools are easy to use from Makefile.PLs and such.

The current source code of ExtUtils::Autoconf is available here:

http://files.perldition.org/ExtUtils-Autoconf-0.01.tar.gz 22962 08b9f68758b25b7d38d5a401f9bc499f

The documentation follows: I'd be glad to get some feedback!

Cheers, Flo


NAME

ExtUtils::Autoconf - Perl interface to GNU autoconf


VERSION

Version 0.01


SYNOPSIS

    use ExtUtils::Autoconf;
    my $ac = ExtUtils::Autoconf->new;

    $foo->reconf;
    $foo->configure;
    $foo->clean;
    $foo->realclean;


DESCRIPTION

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.


TYPICAL USAGE

Typically ExtUtils::Autoconf is being used from Makefile.PLs in Perl module distributions.

AUTOCONF

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 and set configure_ac accordingly) fine 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.59)
    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.59, 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.

MAKEFILE.PL

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:

    package MY;
    sub dist_core {
        my $self = shift;
        my $inherited = $self->SUPER::dist_core(@_);
        $inherited =~ s/^(dist\s*:\s*)/$1autogen /m;
        return $inherited;
    }
    sub postamble {
        return <<"EOM";
    autogen :
    \t\$(PERLRUN) -MExtUtils::Autoconf -e 'ExtUtils::Autoconf->run_autogen'
    EOM
    }

autogen() and configure() automatically generate some files. To clean those up automatically when doing make clean or make realclean extend the postamble section like that:

    sub postamble {
        return <<"EOM";
    autogen :
    \t\$(PERLRUN) -MExtUtils::Autoconf -e 'ExtUtils::Autoconf->run_autogen'
    realclean ::
    \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.


SUBROUTINES/METHODS

new

    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:

  • wd

    The working directory for autoconf. All commands issued by ExtUtils::Autoconf will be executed in this directory.

  • autoconf

    The name of the autoconf executable.

  • autoheader

    The name of the autoheader executable.

  • env

    A 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',
                },
        });

configure

    $ac->configure;

Runs the configure script. If the configure script doesn't exist yet it'll run reconf(). Returns 1 on success or croaks on failure.

reconf

    $ac->reconf;

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.

clean

    $ac->clean;

Cleans up files which were generated during configure(). Always returns something true.

realclean

    my $success = $ac->realclean;

Cleans up files which were generated during reconf() and configure(). Always returns something true.

wd

    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.

autoconf

    my $autoconf = $ac->autoconf;
    $ac->autoconf($new_autoconf);

Accessor for the name of the autoconf executable.

autoheader

    my $autoheader = $ac->autoheader;
    $ac->autoheader($new_autoheader);

Accessor for the name of the autoheader executable.

env

    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.

run_configure

    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().

run_autogen

    perl -MExtUtils::Autoconf -e'ExtUtils::Autoconf->run_autogen' $wd, $autoconf, $autoheader, $configure_ac

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 $configure_ac and runs autogen().

run_clean

    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().

run_realclean

    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().


DIAGNOSTICS

configure failed. Check %s/config.log

Running ./configure failed. Diagnostic messages may be found in the according config.log file.

reconf failed. check the error messages above.

Running autoheader or autoconf failed. Probably your configure.ac is erroneous. Try running autoheader and autoconf manually.


AUTHOR

Florian Ragwitz <rafl@debian.org>


BUGS

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. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ExtUtils::Autoconf

You can also look for information at:


ACKNOWLEDGEMENTS

Marc Lehmann <schmorp@schmorp.de> for the idea and a prof-of-concept implementation (autoconf.pm) in the IO::AIO manpage.


LICENSE AND COPYRIGHT

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.

Comment on RFC: ExtUtils::Autoconf
Select or Download Code
Re: RFC: ExtUtils::Autoconf
by Tanktalus (Canon) on Sep 04, 2006 at 01:55 UTC

    This looks like a wonderful idea. But I do have one question which perhaps you can answer in your documentation. How do I use this? I know, I know - the synopsis says how to use it. But what I mean is ... how do I do that? How do I take advantage of this technology (for that really is what it is) in my XS-based module distribution?

    Specifically, what steps must I, as a module author, take to take advantage of your hard work (and generosity)?

    In that answer, I hope you include details such as what if the target machine does not (yet) have ExtUtils::Autoconf installed yet, and how this might work within CPAN to automatically grab ExtUtils::Autoconf and then proceed from there. I mention this specifically because I suspect that you envision this to be called from Makefile.PL from CPAN, but if I use ExtUtils::Autoconf from within Makefile.PL, won't Makefile.PL fail to even compile before getting to tell CPAN what its prereqs are? But, if you merely call eval { require ExtUtils::Autoconf; ... }, then the Makefile will be created by CPAN, it'll go off to install EU::A, and come back to a Makefile that doesn't take into consideration all this? This would seem to be a catch-22.

    However, I don't know that this is how this works. I'm just supposing it based on the most obvious way to me to implement it - you may be long past this point in your development and design, so please - don't just tell me, put it in the docs :-)

    Thanks! (PS: ++! Autoconf == good! ;-})

      Thanks for your comments!

      I just edited the documentation above and included some information about using ExtUtils::Autoconf from Makefile.PL. It currently only covers ExtUtils::MakeMaker Makefile.PLs, but I intend to write Module::Install::Autoconf, which will integrate it well into Module::Install.

      I don't have much clue about Module::Build, so any help in getting ExtUtils::Autoconf to work with it would be very appreciated.

      Cheers, Flo

Re: RFC: ExtUtils::Autoconf
by rvosa (Curate) on Sep 04, 2006 at 18:06 UTC
    Splendid idea, looking forward to trying it out. One question, though. As far as I know, most autotools actually are in Perl. I think this means they don't really have to be "extutils" from the perl perspective. It has always surprised my that this gnu software isn't on CPAN - but I think you would have the right (under the gpl) to change that and to package your release with (some of) the autotools and achieve tighter integration than you have now.

      The module is currently under ExtUtils:: as it interfaces with autoconf using the autoconf executables, which are external tools.

      I didn't really know that autoconf is mostly written in Perl. I really like the idea of integrating autoconf into the distribution. I just took a look into it and saw that all executables of autoconf, except the `autoconf' executable itself, are written in perl. Unfortunately autoconf comes with quite a lot of m4 macros. These could be integrated with the distribution as well, but then it would still require an m4 executable, which, unfortunately, isn't written in Perl. So doesn't seem easily possible to integrate autoconf in my module, even if the idea is very appealing.

      Cheers, Flo

        Well, I guess you couldn't reach full integration - but at least to the point where the autotools themselves (and their underlying *.pms) are part of the distribution, requiring users only to have m4.

        (Note: I'm not entirely sure if all this is easy or even a good idea. I just like the notion of being able to download and install the autotools from cpan, with few prerequisites.)
Re: RFC: ExtUtils::Autoconf
by xdg (Monsignor) on Sep 05, 2006 at 12:11 UTC

    How do you handle autoconf/autoheader not being available? E.g. On a standard Win32 machine?

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      This module can't work without autoconf and autoheader being present. Therefor it croaks if those executables could not been found or if the user hasn't specified a path to some existing executables to use

      Cheers, Flo

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://570970]
Approved by Corion
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2014-12-27 22:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (177 votes), past polls