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