Autoperl User's Manual

for Autoperl version 1.26
Last revised 7/12/2005

Overview

The objective of Autoperl is to provide a standard build environment for Perl applications that frees the developer from the need to write a complex Makefile. It is syntax-compatible with GNU Autoconf and GNU Automake, and uses the same terminology wherever possible.

In addition to a Makefile, Autoperl produces a configuration script called 'configure' that can be used to check for required library dependencies, as well as alter any of the standard file installation directories (prefix, bindir, datadir, etc.)

Writing Perl applications

Perl has traditionally been a scripting language, but over the years a large number of libraries have been written and published in the CPAN archive. It is possible to write a sophisticated application by combining several of these free libraries.

With the large variety of free UNIX systems available today, it is impossible to ensure that every library is installed on every system. Autoperl provides a dependency checking system that will alert the user to any missing libraries prior to building and installing the software.

In the C/C++ application development world, GNU Autoconf/Automake has been the standard way for resolving cross-platform differences. Autoperl attempts to make the Autoconf/Automake system available to the Perl application development process.

1. Compilation

At this time, Autoperl does not support the Perl compiler (perlcc) that ships with many Unix systems. perlcc does not produce 100% correct binary code in all cases, and is still experimental.

During the compilation phase, Autoperl will process each source code file and check for syntax errors.

2. Linking

Autoperl employs a novel approach to the linking stage of the build process. It passes the primary source code file through a custom preprocessor that replaces any calls to "require " with the contents of . This produces a unified pseudo-binary containing all of the project modules. This module can be distributed as a stand-alone application, or installed into a system PATH.

3. Runtime Variables

Autoperl allows you to easily access it's configuration variables from within your application. Everytime the configuration script is run, a header file called 'config.h' is produces that contains all of the compile-time constants. This header file can be included in your application, and accessed as native Perl variables.

Usage

Before you can use Autoperl in your application, you need to download the ./configure script from the main Autoperl website. This script should be placed in the top level directory of your source tree.

The next step is to create a file called Makefile.am that contains information about your project. The syntax of this file is compatible with Automake, with a few Perl-specific extensions.

Makefile targets

Each Makefile contains these targets:
	make all
	make test
	make install
	make uninstall
	make dist
	make package
	make clean
By default, running 'make' with no arguments will run the 'make all' target.

The 'make all' target compiles all source code files and combines them into a single executable file.

The 'make install' target installs the software on the local system. If used in combination with the DESTDIR environment variable, you can install all files under a temporary subdirectory. This is useful for creating binary packages.

The 'make uninstall' target removes the software from the local system.

The 'make test' target runs all tests under the 't/' directory

The 'make dist' target produces a gzipped tarball containing the source code and everything necessary to build the application.

The 'make package' target produces a native binary package, if Autoperl knows how to do that on your operating system.

The 'make clean' target removes temporary files and generated files, including the Makefile.

The DESTDIR concept

**NOTE** You must supply a fully qualified path to DESTDIR when using SUBDIRS. Otherwise, each subdirectory will create it's own DESTDIR like this:
make install DESTDIR=foo
$(INSTALL) README foo/
make[1]: Entering directory /home/mark/projects/autoperl-0.9.1/src
$(INSTALL) Autoperl.pm foo/
You probably don't want this. Use this instead:
make install DESTDIR=pwd`foo
This is considered an Autoperl bug.

The SUBDIRS concept

Autoperl is designed to operate recursively over any number of subdirectories under the main project directory. It is convenient, for example, to place all source code files in a directory called 'src; all documentation in a directory called 'doc'; and so forth.

If you choose to follow this convention, your top-level Makefile.am will be very simple. It will consist of a SUBDIRS definition that lists each of the subdirectories in your project.

The following is the top-level Makefile.am for Autoperl:

PROGRAM = autoperl
VERSION = 1.26
AUTHOR  = Mark Heily 

SUBDIRS = doc src t

sbin_PROGRAMS = src/autoperl.pl

EXTRA_DIST = TODO BUGS t/all.t

upload:
	@echo scp -r configure-$(VERSION) $(PROGRAM)-$(VERSION).tar.gz doc/*.html \
	       COPYING TODO BUGS ChangeLog \
	       heily.com:/home/mark/public_html/projects/autoperl
	@echo scp configure-$(VERSION) heily.com:/home/mark/public_html/projects/autoperl/configure
	perl -e 'print "cd /incoming\nput autoperl-$(VERSION).tar.gz\nput configure-$(VERSION)\n"' | ftp -a upload.sourceforge.net

upload-doc:
	cp ChangeLog TODO BUGS doc/
	cd doc ; tar -cvf - . | ssh mheily@sofi-firewall.sourceforge.net tar -C /home/groups/a/au/autoperl/htdocs -xv
	
test-all:
	rm -rf /tmp/ap-test
	perl -Isrc src/autoperl.pl
	./configure
	make
	make install DESTDIR=/tmp/ap-test
	find /tmp/ap-test/

test-pkg:
	perl -Isrc src/autoperl.pl
	./configure
	make package
	pkg_add *.tgz

diff:
	# This doesn't work well b/c 'configure' version is unknown
	diff -ruN configure configure-$(VERSION)

#include "incl.1"


Makefile.am

When you execute autoperl(1) to generate a configuration script, it parses a file called Makefile.am. This file is an Automake-style configuration file. It can contain variables and make(1) targets, just like a normal Makefile.

There are some special variables and makefile targets that you should be aware of:

PROGRAM
The official name of the program.
VERSION
The current version number of the program.
AUTHOR
The author's name and email address, in RFC2822 format.
LIB_RUN_DEPENDS
EXEC_RUN_DEPENDS
LIB_BUILD_DEPENDS
HEADER_BUILD_DEPENDS
EXEC_BUILD_DEPENDS
These variables define a list of required dependencies. They may be runtime (RUN_) or build-time (BUILD_), libraries (LIB_), headers (HEADER_) or executables (EXEC_)
foo_ARG
Declares a custom argument to ./configure named 'foo' and sets the default value.
foo_ARG_HELP
Defines a help string for the custom argument to ./configure named 'foo'.
SUBDIRS
This says to recursively make(1) one or more subdirectories
include_HEADERS
Each file here will be installed system-wide to $includedir, which by default is /usr/local/lib/site_perl
man1_MANS
Each file here is to be installed as a manpage in $prefix/man/man1
bin_PROGRAMS
Each file here is a pseudo-binary to be installed under $prefix/bin
sbin_PROGRAMS
Each file here is a pseudo-binary to be installed under $prefix/sbin
bin_SCRIPTS
Each file here is a script to be installed under $prefix/bin
sbin_SCRIPTS
Each file here is a script to be installed under $prefix/sbin
foo_SOURCES
This gives a list of all the source files that comprise 'foo', the pseudo-binary. All these files will be merged together to generate the binary.
pkgdata_DATA
Install data files under $pkgdatadir, usually /usr/local/share/
pkgdata_DOCS
Install documentation under $docdir, which defaults to /usr/local/share/doc/. This is not an Automake variable.
EXTRA_DIST
A list of extra subdirectories to include in the source code distribution when one runs 'make dist'.

Extending a Makefile

It is possible to override the built-in Makefile targets 'all' and 'clean'. Simply provide a 'all-local' and/or 'all-clean' target in your Makefile.am.

Here's an example from the Autoperl source tree:

EXTRA_DIST = autoperl.1 index.html.in manual.html.in autoperl.pod \
             screenshots.html autoperl_configure.png autoperl_usage.png 

man1_MANS = autoperl.1

pkgdata_DOCS = index.html howto.html manual.html autoperl-man1.html

all-local: clean
	gzip -c autoperl.1 > autoperl.1.gz
	pod2html autoperl.pod > autoperl-man1.html
	m4 -DVERSION=$(VERSION) index.html.in > index.html
	m4 -DAP_VERSION=$(VERSION) manual.html.in > manual.html
	rm -f pod2h* version-stamp

clean-local:
	rm -f index.html manual.html autoperl-man1.html

The above Makefile.am is used to generate the documentation by passing it through m4.

If you don't want to override the built-in Autoperl targets, you can extend them using hooks. The following hooks are defined:

These hooks are executed after the built-in Makefile targets have run.

Extending a Makefile using Perl hooks

For the most complicated tasks, it's easier to write portions of a Makefile in Perl. Autoperl has a number of hooks that allow you to write Perl code and have it executed at various stages in the build process.

These hooks are:

In the subdirectory where you want the hook to execute, write a file called 'aplocal.inc' and use one or more of the above hook names as the name of the subroutine.

For example, the following code would produce a listing of all the custom arguments passed in to ./configure:

sub post_configure_hook
{
   foreach (keys %ap::config) {
	print "$_ : " . $ap::config{$_} . "\n";
   }
}

A real-world example can be found in the top level of the Autoperl source tree. Here, post_make_all_hook() is called to create a versioned ./configure script.

sub post_make_all_hook
{
	die unless -e 'src/autoperl';
	system "cp src/autoperl configure-".$ap::config{version};
}

Including other files inside a Makefile.am

Autoperl implements an include function that is compatible with the C preprocessor (cpp). To insert the contents of another file inside Makefile.am, add a line like this:

#include "another.file"

Variables can be referenced within the #include directive, so the following works:

./configure --include-file=my.inc

(inside Makefile.am)
#include "$(include_file)"

In the above example, the contents of 'my.inc' would be inserted into the Makefile.

Embedding Perl into Makefile.am

It is also possible to embed Perl code directly into a Makefile.am by surrounding the code with braces like so:

custom-target:
	echo hi
{
	return "\t" . "/bin/true" . "\n";
}
	echo bye

In the above example, the embedded Perl code would be evaluated during the ./configure stage to produce a Makefile that looks like this:

custom-target:
	echo hi
	/bin/true
	bye

It is possible to access the %ap::config variable from within an embedded Perl snippet, so you have access to all of the configuration parameters set by the ./configure script.

Referencing variables from config.h

Everytime the configuration script is run, it generates a file called config.h that contains all of the variables passed into the ./configure script.

Here's an example from Autoperl:

# Generated by autoperl 1.26
unless (defined $ap::CONFIG_H) {

$ap::CONFIG_H = 1;
%ap::config = (
                'docdir' => '/usr/local/share/doc',
                'mandir' => '/usr/local/man',
                'pkgdatadir' => '/usr/local/share/autoperl',
                'author' => 'Mark Heily ',
                'program' => 'autoperl',
                'ovr_custom' => 'default',
                'crap' => 'good',
                'infodir' => '/usr/local/info',
                'cc' => '/usr/bin/perl -c',
                'sysconfdir' => '/usr/local/etc',
                'bindir' => '/usr/local/bin',
                'confdir' => '/usr/local/etc/autoperl',
                'libexecdir' => '/usr/local/libexec',
                'make' => '/usr/bin/make',
                'autoperl' => '$(TOPDIR)/configure --autoperl',
                'localedir' => '/usr/local/locale',
                'install' => '$(TOPDIR)/configure --autoperl install -p',
                'version' => '1.26',
                'includedir' => '/usr/local/lib/site_perl',
                'datadir' => '/usr/local/share',
                'sbindir' => '/usr/local/sbin',
                'libdir' => '/usr/local/lib',
                'perl' => '/usr/bin/perl',
                'def_custom' => 'default',
                'ld' => '$(TOPDIR)/configure --autoperl link',
                'destdir' => '',
                'prefix' => '/usr/local',
                'localstatedir' => '/usr/local/var'
              );

# Allow references to $ap::foo 

$ap::{docdir} = sub { '/usr/local/share/doc' };
$ap::{mandir} = sub { '/usr/local/man' };
$ap::{pkgdatadir} = sub { '/usr/local/share/autoperl' };
$ap::{author} = sub { 'Mark Heily ' };
$ap::{program} = sub { 'autoperl' };
$ap::{ovr_custom} = sub { 'default' };
$ap::{crap} = sub { 'good' };
$ap::{infodir} = sub { '/usr/local/info' };
$ap::{cc} = sub { '/usr/bin/perl -c' };
$ap::{sysconfdir} = sub { '/usr/local/etc' };
$ap::{bindir} = sub { '/usr/local/bin' };
$ap::{confdir} = sub { '/usr/local/etc/autoperl' };
$ap::{libexecdir} = sub { '/usr/local/libexec' };
$ap::{make} = sub { '/usr/bin/make' };
$ap::{autoperl} = sub { '$(TOPDIR)/configure --autoperl' };
$ap::{localedir} = sub { '/usr/local/locale' };
$ap::{install} = sub { '$(TOPDIR)/configure --autoperl install -p' };
$ap::{version} = sub { '1.26' };
$ap::{includedir} = sub { '/usr/local/lib/site_perl' };
$ap::{datadir} = sub { '/usr/local/share' };
$ap::{sbindir} = sub { '/usr/local/sbin' };
$ap::{libdir} = sub { '/usr/local/lib' };
$ap::{perl} = sub { '/usr/bin/perl' };
$ap::{def_custom} = sub { 'default' };
$ap::{ld} = sub { '$(TOPDIR)/configure --autoperl link' };
$ap::{destdir} = sub { '' };
$ap::{prefix} = sub { '/usr/local' };
$ap::{localstatedir} = sub { '/usr/local/var' };


# Allow references to $ap::config{foo} or $ap::config->{foo} 
$ap::config = \%ap::config;
}

1;

All of the variables listed above could have been modified by various parameters passed into the configuration script.

To use config.h in your program, simply 'require' it into every source code file that needs to reference these variables. This allows you can reference the variables as follows:

$ap::config{foo}

Custom arguments to ./configure

Every argument that is passed in on the command line of a configure script will be placed in the $ap::config variable.

For example, if a user typed:

  ./configure --foo=1 --bar=2 --baz=3

The config.h would look like:

$ap::config = +{
          foo => 1,
          bar => 2,
          baz => 3,
       };

There are two special prefixes: --with/--without and --enable/--disable. These are convenient ways of implicitly declaring a boolean value at configure time.

For example, if a user typed:

./configure --with-foo --without-bar --enable-baz

The config.h would look like:

$ap::config = +{
           foo => 1,
           bar => 0,
           baz => 1,
       };
If your application uses custom arguments, it's a good idea to declare them in configure.in. While this is not strictly necessary, it ensures that your argument is documented and initialized with a default value.

To declare a custom argument, use the _ARG and _ARG_HELP variables in Makefile.am as follows:

    argname_ARG = 
    argname_ARG_HELP = help string

For example:

    with_ssl_ARG = 0
    with_ssl_ARG_HELP = enable support for SSL/TLS

This would allow a user to pass the flag '--with-ssl' to ./configure

Autoconf parser

Autoperl implements an Autoconf-style parser to perform macro substitutions on arbitrary files. If you define a variable called AC_CONFIG_FILES, and list one or more files there, Autoperl will parse the .in file and substitute variables in the @VARIABLE@ format.

For example,

AC_CONFIG_FILES = index.html

would cause index.html.in to be parsed:


@PROGRAM@ Documentation

and generate an index.html like so:


YourProgramName Documentation

Installation Directories

(FIXME: reformat as HTML)

    Autoperl allows the user to designate what directories the package
    should be installed. When running configure, the options below can be
    given (prepended with '--'), e.g. --prefix=/usr
    
   Prefix
    DO NOT confuse prefix with destdir -- destdir is used to relocate
    the entire package to a subdirectory. See the section *VARIABLES* for
    information about the destdir variable.

    --prefix
     A prefix used in constructing the default values of the variables
     listed below. The default value of prefix should be /usr/local.

   Executables
    --bindir
     The directory for installing executable programs that users can run.
     The default is $(prefix)/bin, which is normally /usr/local/bin

    --sbindir
     The directory for installing executable programs that can be run from
     the shell, but are only generally useful to system administrators. The
     default is $(prefix)/sbin, which is normally /usr/local/sbin

    --libexecdir
     The directory for installing executable programs to be run by other
     programs rather than by users. The default is $(prefix)/libexec,
     which is normally /usr/local/libexec.

   Documentation
    --docdir
     The directory containing ASCII documentation, examples, etc., for this
     package. The default is $(datadir)/doc.

    --mandir
     The directory for The configure script has the ability to: - Check for
     missing or broken library dependencies - Check for required system
     binaries in the user's path - Define an alternate installation prefix
     or custom install path using DESTDIR - Enable or disable certain
     application-specific features at build time

     The generated Makefile has the ability to: - Build a source tarball via
     the 'make dist' target - Install the application via the 'make install'
     target - Remove temporary files via the 'make clean' target

      installing the Man pages for this package. The default is $(datadir)/man.

    --infodir
     The directory for installing the Info files for this package. The
     default is $(datadir)/info.

   Libraries
    --libdir
     The directory for installing library dependencies. Do not install
     executables here, they probably ought to go in $(libexecdir) instead.
     The default is $(prefix)/lib. Consider this as the package's private
     library path.

   Data
     --datadir
      The root of the directory tree for read-only architecture-independent
      data files. The default is $(prefix)/share.

     --localstatedir
      The directory for installing data files which the programs modify
      while they run, and that pertain to one specific machine. Users should
      never need to modify files in this directory to configure the
      package's operation; put such configuration information in separate
      files that go in $(datadir) or $(sysconfdir). The default is
      $(prefix)/var.

     --sharedstatedir
      The directory for installing architecture-independent data files which
      the programs modify while they run. The default is $(prefix)/com.

     --localedir
      The directory for installing locale-specific message catalogs for this
      package. The default is $(datadir)/locale.

   Configuration files
     --sysconfdir
      The directory for installing read-only data files that pertain to a
      single machine--that is to say, files for configuring a host. Mailer
      and network configuration files, /etc/passwd, and so forth belong
      here. All the files in this directory should be ordinary ASCII text
      files. The default is /etc.

     --confdir
     The directory for package-specific configuration files. The default
     is '/etc/${packagename}'

   Unimplemented

     Not all of the GNU installation directories have been implemented;
     those omitted are

     exec_prefix
      In the GNU system, $exec_prefix is used in constructing the default
      values of some of the variables listed below. The default value of
      exec_prefix should be $(prefix). Generally, $(exec_prefix) is used for
      directories that contain machine-specific files (such as executables
      and subroutine libraries), while $(prefix) is used directly for other
      directories.

      Autoperl makes no such distinction. Use prefix instead.

     man1dir, man2dir, ...
     man1ext, man2ext, ...
      Use mandir instead, and append which section of the manual is
      appropriate. For example, $(mandir)/man1/

     For more information, see the GNU Coding Standards, section 7.2.4.

Experimental Features

This section describes features of Autoperl that are considered to be
experimental.

* Support for other languages

There is basic support for building C and Python programs with Autoperl.
For examples, see recvmail and mboard on http://heily.com/mark/projects

* Building native binary packages

Building native binary packages

package.in file format:

The format is:

  : 

Anything after a hash mark (#) is considered to be a comment, and is ignored.
Blank lines are ignored, unless they are part of a multi-line field.

Valid keywords are:

- Package

	The name of the binary package to produce. Usually the same name
as the program.

- Title

	A one-line title, less than 75 characters.

- Description

	A multiline description of the program.

- License

	The name of the copyright license used by the program

- Project-URI

	The program's home page on the World Wide Web.

- Source-URI

	A URI where the source code can be downloaded from.

- VuXML-URI

	A URI where the VuXML vulnerabilities document can be downloaded from.

- Requires

	A comma-seperated list of requried executables or headers

Here is an example from the Autoperl source code.

---cut here---
# $Id$
#
# package.in for Autoperl
#

Package: 	autoperl
Title: 		A configuration and build system for Perl applications
Project-URI:	http://heily.com/~mark/projects/autoperl
Source-URI: 	%{project_uri}/autoperl-%{version}.tar.gz
VuXML-URI:	%{project_uri}/advisories.xml
Requires:       perl, uname
License:	Artistic
Description:

  Autoperl is a configuration and build system for Perl applications
that is modelled after the GNU Autoconf and Automake tools. 


---cut here---

Copyright and License

Copyright (C) 2003,2004,2005 Mark Heily <devel@heily.com>

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See the file called COPYING for the complete text of the license.