Maintainer's Perspective
Basics
This section tends to lag behind the GAR Tips and GAR Variables documents, so be sure to read them regularly!
From the package maintainer's perspective, the GAR system is a library of make targets that can be configured by setting certain special variables or overridden file-by-file. To make a GAR package, you make a directory for a package inside the directory representing its category. Inside this directory, you create a Makefile describing your package.
An Example
The best way to understand the process of making a new package is to look at an example:
GARNAME = grep GARVERSION = 2.4.2 CATEGORIES = utils MASTER_SITES = ftp://ftp.gnu.org/pub/gnu/grep/ DISTFILES = $(DISTNAME).tar.gz DESCRIPTION = grep define BLURB The GNU family of grep utilities may be the "fastest grep in the west". GNU grep is based on a fast lazy-state deterministic matcher (about twice as fast as stock Unix egrep) hybridized with a Boyer-Moore-Gosper search for a fixed string that eliminates impossible text from being considered by the full regexp matcher without necessarily having to look at every character. The result is typically many times faster than Unix grep or egrep. (Regular expressions containing backreferencing will run more slowly, however.) endef CONFIGURE_SCRIPTS = $(WORKSRC)/configure BUILD_SCRIPTS = $(WORKSRC)/Makefile INSTALL_SCRIPTS = $(WORKSRC)/Makefile CONFIGURE_ARGS = $(DIRPATHS) include ../../gar.mk
The first few lines set some basic bookkeeping info. The GARNAME and GARVERSION refer to the package name and version string as the GAR system will manipulate them. They are also used to create the convenience variable DISTNAME, which defaults to $(GARNAME)-$(GARVERSION) (since most GNU or automake-using packages name their tarballs in that fashion).
The fetch target will, by default, try to grab $(MASTER_SITES)$(DISTFILES) for each of the space-separated entries in either variable.
Next are some basic description variables. The DESCRIPTION variable should be a short, one-line description of the package, while the BLURB is a longer multi-paragraph description. This BLURB is taken straight from the debian package for grep.
The actual build of the system depends on the CONFIGURE_SCRIPTS, BUILD_SCRIPTS, and INSTALL_SCRIPTS variables. These point to a space-separated list of files that are essential to the configure, build, and install steps (respectively).
The GAR system is pretty smart, and will know what to do with most types of scripts. It knows to just run CONFIGURE_SCRIPTs named "configure", and to run "make" or "make install" in the directory where a Makefile lives. It also knows that Imakefiles use xmkmf, and so forth. For most packages, no special magic needs to happen here.
We usually, however, need to specify the CONFIGURE_ARGS to include the directory settings that we define in gar.conf.mk. This currently requires setting it to include $(DIRPATHS). This may, in future, not be necessary for packages that use autoconf-generated configure scripts. Some older configure scripts don't accept all of the standard directories, so the package maintainer must set them by doing something like:
NODIRPATHS += --bindir --sbindir --libexecdir --datadir --infodir NODIRPATHS += --sysconfdir --sharedstatedir --localstatedir --libdir NODIRPATHS += --includedir --mandir
But this is uncommon.
Finally, we include the gar.mk library. This takes all of the variable setting we've done and puts it to good use. This allows your little teeny Makefile to provide the seven basic targets described in the User Perspective section. It must come last (or, at least, after all of the variables have been set) in order to function properly.
Dependencies
Often a package will require the presence of another in order to compiler or run. Most binary packaging systems require the user to satisfy these dependencies manually. GAR, on the other hand, attempts to satisfy them automatically.
To specify that one gar package depends on another, there are three basic variables (soon to become more): DEPENDS, LIBDEPS, and BUILDDDEPS. The format of these variables is a space-separated list of category/package tuples. Thus, the parted package depends on e2fsprogs-libs, and its Makefile contains the following line:
LIBDEPS = lib/e2fsprogs-libs
This tells GAR to go into ../../lib/e2fsprogs-libs and install that package before proceeding with parted's configure step.
Checksum file
The package isn't complete until there is a checksum file. Finish up your Makefile, and then run "make fetch". If all the files look correct to you, run "make makesum" and check the resulting "checksums" file into CVS alongside the Makefile. This checksums file will be consulted during the "make checksum" phase.
When defaults aren't enough
Quite often, the default behavior isn't what one would hope. You can pass parameters to your configure script with CONFIGURE_ARGS, but what if the GAR system doesn't know about your configuration script type? What if the configuration steps aren't enough? What if they're flat-out wrong? What if the same is true for the fetch, extract, or install rules?
Fortunately, the system provides for this in a number of ways. What follows are a few of the mechanisms that a package maintainer can use to override or enhance the default behaviors.
Overriding Variables
Sometimes, a package just doesn't treat your configuration information the way you'd like. Either it munges the parameters you pass too much (or too little), or it just doesn't prompt you for certain variables. Fortunately, we have the technology to set variables so that they will keep our munged values.
For a detailed description of this, read the "Override Make Vars" GAR Tip.
Here is an example package that uses this. w3m's Makefile uses non-standard directory variables internally, and does not allow you to specify them via the configure script. Thus, we do the following:
BIN_DIR = $(bindir) LIB_DIR = $(libdir) HELP_DIR = $(docdir) BUILD_ARGS = BIN_DIR="$(BIN_DIR)" LIB_DIR="$(LIB_DIR)" HELP_DIR="$(HELP_DIR)" INSTALL_ARGS = BIN_DIR="$(BIN_DIR)" LIB_DIR="$(LIB_DIR)" HELP_DIR="$(HELP_DIR)"
- Note that the BUILD_ARGS line could also be written as
BUILD_OVERRIDE_DIRS = BIN_DIR LIB_DIR HELP_DIR
Although the INSTALL_ARGS could not, due to the fact that INSTALL_OVERRIDE_DIRS prepends $(DESTDIR), and the w3m package already honors $(DESTDIR)!
For more information on INSTALL_OVERRIDE_DIRS, see the "Install Override Dirs" GAR Tip. For more information on $(DESTDIR), see the "Implicit Destdir Considered Harmful" GAR Tip.
pre- and post- rules
For each of the seven basic targets, there exist slots for per-package pre- and post- rules. That means that the package maintainer can specify work to be done immediately before or after a rule.
As an example, let's consider the util-linux package. It doesn't use a standard autoconf-style configure script, but it can be configured by setting a variable at the top of the MCONFIG file. Thus, the end of our utils/util-linux/Makefile looks like the following:
CONFIGURE_SCRIPTS = $(WORKSRC)/configure BUILD_SCRIPTS = $(WORKSRC)/Makefile INSTALL_SCRIPTS = $(WORKSRC)/Makefile CONFIGURE_ARGS = $(DIRPATHS) include ../../gar.mk pre-configure: echo "DESTDIR=$(DESTDIR)" > $(WORKSRC)/MCONFIG.NEW cat $(WORKSRC)/MCONFIG >> $(WORKSRC)/MCONFIG.NEW mv $(WORKSRC)/MCONFIG.NEW $(WORKSRC)/MCONFIG $(MAKECOOKIE)
Thus, before the configure script is run, the package-defined pre-configure rule adds code setting DESTDIR to the $(prefix) variable in MCONFIG. For more information on $(DESTDIR), see the "Implicit Destdir Considered Harmful GAR Tip.
Note that we put the pre-configure after the include, as per the "Rules After Include" GAR Tip. This ensures that our rule won't be trumped by any rules in the included files.
As another example, the Bourne Again SHell (bash) can be linked to with the name "sh" in order to cause it to behave (somewhat) like a POSIX Bourne Shell. Thus, the end of our shells/bash/Makefile looks like:
CONFIGURE_SCRIPTS = $(WORKSRC)/configure BUILD_SCRIPTS = $(WORKSRC)/Makefile INSTALL_SCRIPTS = $(WORKSRC)/Makefile CONFIGURE_ARGS = $(DIRPATHS) include ../../gar.mk post-install: (cd $(DESTDIR)$(bindir); ln -sf bash sh) $(MAKECOOKIE)
Thus creating the symbolic link to sh.
For more information on $(DESTDIR), see the "Implicit Destdir Considered Harmful GAR Tip.
Overriding default behavior
Sometimes it's not enough to merely enhance the behavior of a rule. Sometimes the default handler for a given script is dead wrong, or the script has no default handler. In this case, it is easy enough to provide your own handler.
For example, the Perl package has a file called configure.gnu that needs to be run. The GAR system doesn't know that it's just like a standard configure script, so we have to tell it like so:
CONFIGURE_SCRIPTS = $(WORKSRC)/configure.gnu BUILD_SCRIPTS = $(WORKSRC)/Makefile INSTALL_SCRIPTS = $(WORKSRC)/Makefile NODIRPATHS += --exec_prefix --bindir --sbindir --libexecdir \ --datadir --infodir --sysconfdir --sharedstatedir \ --localstatedir --libdir --includedir --mandir CONFIGURE_ARGS = $(DIRPATHS) include ../../gar.mk configure-$(WORKSRC)/configure.gnu: cd $(WORKSRC) && $(CONFIGURE_ENV) ./configure.gnu $(CONFIGURE_ARGS) $(MAKECOOKIE)
The custom configure target should perform the same steps that a user would at the command line, with appropriate changing of directories and setting of environment variables. In this case, we do exactly what happens in the standard library routine for configure scripts, but we use configure.gnu instead of simply configure. Notice that we put CONFIGURE_ENV in even though we don't use it, in order to be consistent with the standard library routines.
At the end, we run $(MAKECOOKIE) to signify that this step is complete. This lets GAR know where to pick up where it left off if the build only gets partway through.
Putting the two together
The following example is from the net-tools package, which has a bizarre interactive configuration system. The maintainer automated this by setting some variables at the top of the package's Makefile and then piping the output of the "yes" program into the configurator in order to accept all defaults.
CONFIGURE_SCRIPTS = $(WORKSRC)/Makefile BUILD_SCRIPTS = $(WORKSRC)/Makefile INSTALL_SCRIPTS = $(WORKSRC)/Makefile include ../../gar.mk pre-configure: echo "BASEDIR=$(prefix)" > $(WORKSRC)/Makefile.NEW cat $(WORKSRC)/Makefile >> $(WORKSRC)/Makefile.NEW mv $(WORKSRC)/Makefile.NEW $(WORKSRC)/Makefile $(MAKECOOKIE) configure-$(WORKSRC)/Makefile: # if you want non-default answers to the "make config" # questions, you'll have to go through and answer the # questions the way you want, and then preserve the # resulting file (instead of the action below, which # simply uses the defaults every time) yes '' | make -C $(WORKSRC) config $(MAKECOOKIE)
Patching
Sometimes the system simply won't build from pristine upstream sources, no matter how much fiddling you do in pre- and post- rules. For instances like these, we provide patches with our packages.
The easiest way to make a patch is to have gar do it for you. Run "make extract" and then go make your changes in work/. Once you're done making changes, run "make makepatch". This will create a file named "gar-base.diff" in the files/ directory, representing all the differences between the upstream sources and your modified tree.
Add this file to the PATCHFILES variable in your Makefile (e.g., "PATCHFILES = gar-base.diff") and verify the effectiveness and integrity of your patch. Then run "make makesum" to update the checksums file. Don't forget to commit all three files (Makefile, checksums, and files/gar-base.diff) into CVS.
In addition, the system will download any third-party patches listed in PATCHFILES from the list of MASTER_SITES if it can't find them on the local system. It is legitimate to have more than one patch file; some of our packages have several.
Here's the util-linux package again as an example. We made the file utils/util-linux/files/no-chown.patch as a patch to the original sources. Then in our Makefile we put:
PATCHFILES = no-chown.patch
Providing nonexistent behavior
Suppose you want to perform a configure step, but there is no actual program or script associated with the step of configuration. You could conceivably want to run a series of shell commands to create a configuration file. Since there is no actual script to run, you would specify "custom" as the CONFIGURE_SCRIPTS.
For example, look at the way the tracesroute package performs its build step. There was no makefile, so the maintainer had to provide a method for the compilation commands to be run semi-manually. Thus, the BUILD_SCRIPTS is set to "custom", and a build-custom target is created.
WORKSRC = $(WORKDIR) BUILD_SCRIPTS = custom include ../../gar.mk build-custom: $(CC) $(CFLAGS) -o $(WORKSRC)/tracesroute $(WORKSRC)/traceroute.c -lresolv -lm $(MAKECOOKIE)
It is worth noting that WORKSRC is set to WORKDIR because the .c file is extracted via extraordinary means.
It is the opinion of the GAR authors that any package supplying a -custom rule should properly provide a generalized rule for inclusion in the gar.lib.mk file. It may or may not be useful; however, for there to be a generalized default rule that turns .c files into executables.
Manifest-based installs
One of the most common occasions where a package maintainer would like to use a -custom rule is when installing software that has no built-in installation mechanism. Moving files from location to location is common enough that GAR provides a general mechanism for this.
A package maintainer can specify the locations, permissions, and modes of a file (or collection of files) in a file called manifest. This file contains a list of installation tuples (one per line) of the following format:
source:destination[:mode[:owner[:group]]]
An installation tuple may use shell variables taken from the GAR environment, but must enclose them in curly braces instead of parentheses. Thus, a sample manifest file may contain the following:
${WORKSRC}/nwall:${DESTDIR}${bindir}/nwall:2755:root:tty ${WORKSRC}/src/foo:${DESTDIR}${sharedstatedir}/foo ${WORKSRC}/yoink:${DESTDIR}${sysconfdir}/yoink:0600
Note that all options after the destination location for the file are optional, but one must provide all preceeding options in order to define a given optional field. Thus to specify the owner of a file, one must also specify the mode.
For more information on $(DESTDIR), see the "Implicit Destdir Considered Harmful" GAR Tip.