Porting an application means starting with the original sources and changing them a little bit to make it work. When using a recipe the port will work on many platforms.
The presence of the variable "PORTNAME" triggers A-A-P to handle the recipe as
a port recipe. This will happen:
1. Add the dependency:
all: dependcheck builddepend
fetch checksum extract patch configure build test
package install rundepend
2. For each of the targets in the dependency above add a dependency based on
the variables set in the recipe.
You can define dependencies for:
do-XXX replace the body of a step
pre-XXX do something before a step
post-XXX do something after a step
General info provided by the port recipe:
Various variables need to be set to specify properties of the port.
PORTNAME name of the port "foobar"
PORTVERSION app version number "3.8alpha"
PORTREVISION port patchlevel "32"
--> foobar-3.8alpha_32
info URL http://www.foobar.org
MAINTAINER_NAME maintainer name John Doe
MAINTAINER maintainer e-mail john@foobar.org
PORTCOMMENT short description get foo into the bar
PORTDESCR long description blah blah blah
IS_INTERACTIVE requires user input yes or no
Variables that can be used by the port recipe:
WRKDIR directory all files are extracted in and the building
is done in default: "work"
DISTDIR directory where downloaded distfiles are stored
default: "distfiles"
PATCHDISTDIR directory where downloaded patches are stored
default: "patches"
PKGDIR directory where files are stored before creating a
package default: "pack"
Variables that may be set by the port recipe, defaults are set only after
reading the recipe:
WRKSRC Directory inside $WRKDIR where the unpacked sources
end up. This should be the common top directory in the
unpacked archives. default: $PORTNAME-$PORTVERSION
When using CVS it is always set to $CVSWRKSRC (also
when $WRKSRC was already set).
CVSWRKSRC Directory inside $WRKDIR where files obtained with CVS
end up. default: the first entry in
$CVSMODULES
NO_WRKSUBDIR When not empty, $WRKSRC will be empty instead of using
the default value. default: not set
PATCHDIR Directory inside $WRKDIR where patches are to be
applied. default: $WRKSRC
BUILDDIR Directory inside $WRKDIR where building is to be
done. default: $WRKSRC
TESTDIR Directory inside $WRKDIR where testing is to be
done. default: $WRKSRC
INSTALLDIR Directory inside $WRKDIR where $INSTALLCMD is to be
done. default: $WRKSRC
CONFIGURECMD Set to the command used to configure the application.
Usually "./configure".
Default: nothing
BUILDCMD Set to the command used to build the application.
Usually just "make".
Default: "aap".
TESTCMD Set to the command used to test the application.
Usually "make test".
Default: "aap test".
INSTALLCMD Set to the command used to do a fake install of the
application.
Default: "aap install DESTDIR=$PKGDIR
For running configure, define a pre-build target. Example:
pre-build:
:cd $WRKDIR/$WRKSRC
:sys LANG=de ./configure --with-extra
DEPENDENCY FORMAT
Dependencies on other modules are specified with the various DEPEND_
variables. The format of these variables is a list of items.
Items are normally white separated, which means there is an "and" relation
between them. Alternatively "|" can be used to indicate an "or" relation.
DEPENDS = perl python require both perl and python
DEPENDS = perl | python require perl or python
Parenthesis can be used to group items. Parenthesis must be used when
combining "or" and "and" relations. Example:
(foo bar) | foobar Either both "foo" and "bar" or "foobar"
foo bar | foobar Illegal
foo (bar | foobar) "foo" and either "bar" or "foobar"
When a dependency is not met the first alternative will be installed, thus the
order of "or" alternatives is significant.
Each item is in one of these formats:
name-version_revision a specific version and revision
name any version
name-regexp a version specified with a regular
expression (shell style)
name>=version_revision any version at or above a specific
version and revision
name>version_revision any version above a specific version
and revision
name<=version_revision any version at or below a specific
version and revision
name<version_revision any version below a specific version
and revision
name!version_revision any version but a specific version and
revision
In the above "_revision" can be left out to ignore the revision number. It
actually works as if there is a "*" wildcard at the end of each item.
"name" can contain wildcards. When a part is following it is appended at the
position of the wildcard (or at -9 if it comes first).
foo-* matches foo-big, foo-big-1.2 and foo-1.2
foo-*!1.2 matches foo-big, foo-big-1.2 and skips foo-1.2
The version specifications can be concatenated, this creates an "and"
relation. Example:
foo>=1.2<=1.4 versions 1.2 to 1.4 (inclusive)
foo>=1.2!1.8 versions 1.2 and above, excluding 1.8
xv>3.10 versions above 3.10, accepts xv-3.10a
The "!" can be followed by parenthesis containing a list of specifications.
This excludes the versions matching the specifications in the parenthesis.
Example:
foo>=1.1!(>=1.3<=1.5) versions 1.1 and higher, but not
versions 1.3 to 1.5
foo>=6.1!6.1[a-z]* version 6.1 and later but not 6.1a,
6.1rc3, etc.
When a dependency is not met the newest version that meets the description is
used.
For systems that do not allow specifying dependencies like this in a binary
pacakge, the specific package version that exists when generating the package
is used.
DEPENDENCIES FOR VARIOUS STEPS
The various variables used to specify dependencies:
DEPEND_FETCH Required for fetching files. Also for
computing checksums.
DEPEND_EXTRACT Required for unpacking archives.
DEPEND_BUILD Required for building but not necessarily for
running; these are not included in the binary
package; items may also appear in DEPEND_RUN.
DEPEND_TEST Required for testing only; don't include items
that are already in DEPEND_RUN.
DEPEND_RUN Required for running; these will also be
included in the generated binary package.
DEPENDS Used for DEPEND_BUILD and DEPEND_RUN when
empty.
Only the dependencies specified with DEPEND_RUN will end up in the generated
binary package. When using a shared library, it is recommended to put a
dependency on the developer version (includes header files) in DEPEND_BUILD
and a dependency on the library itself in DEPEND_RUN. The result is that when
installing binary packages the header files for the library don't need to be
installed.
The "CONFLICTS" variable should be set to specify modules with which this one
conflits. That means only one of the two packages can be installed in the
same location. It should still be possible to install the packages in
different locations. The format of CONFLICTS is identical to that of the
DEPENDS_ variables.
Dependencies are automatically installed, unless "AUTODEPEND" is "no".
The dependencies are normally satisfied by installing a port. When a
satisfying port can not be found a binary package is installed.
The ports and packages are first searched for on the local system. When not
found the internet is searched.
The order of searching can be changed with "AUTODEPEND":
binary only search for binary packages, default
locations
source only search for ports, default locations
source {path = /usr/ports http://ports.a-a-p.org}
only search for ports in /usr/ports and on the
ports.a-a-p.org web site.
STEPS
These are the individual steps for installing a ported application. Each step
up to "install" depends on the previous one. Thus "aap install" will do all
the preceding steps. But the steps that have already been successfully done
will be skipped. The "rundepend", "installtest", "clean", etc. targets do not
depend on previous steps, they can be used separately.
dependcheck: check if required dependencies can be fulfilled
This doesn't install anything yet, it does an early check if building
and/or installing the port will probably work before starting to
download files.
This uses all the DEPEND_ variables that will actually be used.
Fails if something is not available.
fetchdepend: check dependencies for fetch and checksum
Uses DEPEND_FETCH, unless disabled with AUTODEPEND=no
fetch: get required files
if $CVSMODULES is set and $CVS is not "no", obtain files from CVS
uses $CVSROOT or cvsroot attribute in $CVSMODULES
$CVSWRKSRC is where the files will end up (default is first
entry in $CVSMODULES)
also obtain $CVSDISTFILES if defined
also obtain $CVSPATCHFILES if defined
use post-fetch to rename directories
else
if $DISTFILES is set obtain them
if $PATCHFILES is set obtain them
Use MASTER_SITES for [CVS]DISTFILES
Use PATCH_SITES for [CVS]PATCHFILES
the [CVS]DISTFILES are put in $DISTDIR
the [CVS]PATCHFILES are put in $PATCHDISTDIR
The directory can be overruled with a {distdir = dir} attribute on
individual patch files.
Files that already exist are skipped (if there is a checksum error,
delete the file(s) manually).
checksum: check if checksums are correct
The port recipe writer must add the "do-checksum" target with
":checksum" commands to verify that downloaded files are not
corrupted. Example:
# >>> automatically inserted by "aap makesum" <<<
do-checksum:
:checksum $DISTDIR/foo-1.1.tgz {md5 = 2341423423423423434}
:checksum $PATCHDISTDIR/foo-patch3.gz {md5 = 3923858739234}
# >>> end <<<
The "aap makesum" command can be used to generate the lines.
extractdepend: check dependencies for extract and patch
Uses DEPEND_EXTRACT, unless disabled with AUTODEPEND=no
extract: unpack the archives
unpack archives in the right place
use $EXTRACT_ONLY if defined, otherwise $DISTFILES or
$CVSDISTFILES when CVS was used
Uses the "extract" action. Do extract a new type of archive:
add filetype detection for this type
define an "extract" action
Extraction is done in $WRKDIR. A subdirectory may be specified with
the "extractdir" attribute on each archive.
DISTFILES = foo-1.1.tgz foo_doc-1.1.tgz {extractdir = doc}
patch:
apply patches not applied already
$PATCHCMD defines the patch command, default "patch -p < "
The patch file name is appended, unless "%s" appears in the
string, then it's replaced by the file name.
A "patchcmd" attribute on each patch file may specify a patch command
that overrules $PATCHCMD.
The patches are applied in $WRKDIR/$PATCHDIR (default: $WRKSRC).
A "patchdir" attribute on each patch file may overrule the value of
$PATCHDIR.
builddepend: check dependencies for configure and build
Uses DEPEND_BUILD, unless disabled with AUTODEPEND=no
configure: configuration
autoconf/imake/etc. USE_IMAKE
may be empty
build:
run make or aap
USE_GMAKE
USE_BSDMAKE
BUILDCMD=make foo default: "aap"
Done in $WRKDIR/$BUILDDIR, default: $WRKDIR/$WRKSRC
testdepend: check test dependencies
Uses DEPEND_TEST.
check if all required items are present
try to install them automatically, unless disabled AUTODEPEND=no
This is skipped when "SKIPTEST=yes"
test:
check if building was done properly
TESTCMD=make testall default: "aap test"
This is skipped when "SKIPTEST=yes"
Done in $WRKDIR/$TESTDIR, default: $WRKDIR/$WRKSRC
package: create binary package
Two methods to select files to include:
1. list of files below $WRKDIR, with "dest" attr where they end up
PACKFILES = $WRKSRC/bin/prog {dest = /usr/local/bin/prog}
$WRKSRC/man/prog.1 {dest = usr/local/man/man1/prog.1}
2. prog to fake-install into $PKGDIR, use all files there.
INSTALLCMD = "aap install DESTDIR=$PKGDIR"
INSTALLDIR in $WRKDIR default is $WRKSRC
$PKGDIR/$PREFIX is where files end up
generate packing list and other files for local package system
execute pkg_create or equivalent
install: install the binary package
in home dir or in system (require typing root password)
execute pkg_add or equivalent
Exception: This updates the "rundepend" and "installtest" targets
after updating the post-install target. This allows doing "aap
install", which is a lot more obvious than "aap installtest".
rundepend: check runtime dependencies
Check if all required items specified with $DEPEND_RUN are present and
tries to install them automatically, unless $AUTODEPEND is "no".
This is skipped if $SKIPRUNTIME is "yes". The pre-rundepend and
post-rundepend are still done, they should check $SKIPRUNTIME
themselves.
"aap rundepend" will _not_ cause previous steps to be updated.
installtest: test if the installed package works
This is empty by default, specify a "do-installtest" target to
actually do something.
Note that when $SKIPRUNTIME is "yes" the dependencies have not been
verified and running the application might not work.
deinstall: uninstall the binary package
Execute pkg_delete or equivalent.
Does not depend on other steps.
clean: delete all generated, unpacked, patched and CVS files
not the downloaded files.
Does not depend on other steps.
distclean: delete everything except the toplevel recipe
Does not depend on other steps.
makesum: generate checksum file
Generates a checksum file to be able the check if the fetched files
were not corrupted.
The generated file can be included into the port recipe.
Does not depend on other steps. The files must already be present.
You can use "aap fetch --nofetch-recipe" to obtain the files, if
needed (it obtains the files but not the recipes).
srcpackage: generate a package with recipe and source files
Put main recipe and all downloaded files into an archive. The
resulting archive can be installed without downloading.
Depends on the "fetch" target.
PORT DESCRIPTION
The text to describe the port is usually a page full of plain text. Here is an
example:
PORTDESCR << EOF
This is the description of the port.
See our website http://myport.org.
EOF
In the rare situation that "EOF" actually appears in the text you can use
anything else, such as "THEEND".
USING AUTOCONF
The autoconf system is often used to configure C programs to be able to
compile them on any Unix system. This section explains how to use autoconf
with A-A-P in a nice way.
A recipe that uses the generated configure script can start like this:
$BDIR/config.h $BDIR/config.aap : \
configure config.arg config.h.in config.aap.in
:sys ./configure `file2string("config.arg")`
:move {force} config.h $BDIR/config.h
:move {force} config.aap $BDIR/config.aap
config.arg:
:touch {exist} config.arg
:update $BDIR/config.aap
:include $BDIR/config.aap
What happens here is that the "config.aap" target is updated before any of the
building is done. This is required, because running the configure script
will generate or update the "config.aap" file that influences how the building
is done.
The arguments for configure are stored in the "config.arg" file. This
makes it easy to run configure again with the same arguments. There should be
a "config.txt" file that explains all the possible configure arguments, with
examples that can be copied into "config.arg". Example:
# Select the library to be used for terminal access. When omitted a
# series of libraries will be tried. Useful values:
--with-tlib=curses
--with-tlib=termcap
--with-tlib=termlib
The user can now copy one of the example lines to his "config.arg" file.
Example:
# select specific terminal library
--with-tlib=termcap
Comment lines can be used, they must start with a "#". Note: a comment after
an argument doesn't work, it will be seen as an argument.
When updating to a new version of the program, the same "config.arg" file
can still be used. A "diff" between the old and the new "config.txt" will
show what configure arguments have changed.
"config.aap" and "config.h" are put in $BDIR, because they depend on the
current system. They might also depend on the variant to be build. In that
case the ":variant" statement must be before the use of $BDIR. However, if
the variant is selected by running configure, the variant must come later.
"config.aap" and "config.h" are then updated when selecting another variant.
For a developer there also needs to be a method to generate the configure
script from configure.in. This needs to be done even before configure is run.
Prepending this to the example above should work:
configure {distributed} : configure.in
:del {force} config.cache config.status
:sys autoconf
:update configure
The "{distributed}" attribute on the target indicates that the "configure"
file is included in the distribution. When "configure" was not built (there
is no old signature for it) but it does exist, it doesn't need to be build.
This is useful to avoid running autoconf after unpacking sources that already
include the up-to-date configure script. But when "configure.in" changes
after executing the recipe once, configure will be built, because the
signatures will be remembered when executing the recipe. When changing
configure.in before executing the recipe (or after deleting the recipe file
manually) no building will be done, the change will not be noticed.
The "config.cache" and "config.status" files are deleted, because they may
become invalid when generating a new configure script. |