Gentoo Logo
Gentoo Logo Side

[ << ] [ < ] [ Home ] [ > ] [ >> ]


2. Eclass HOWTO

Content:

2.a. Introduction to eclasses

The idea behind eclasses

eclasses are modules of shared code. They are written in bash and have the same syntax as ordinary ebuilds, and are sourced ('inherited') by ebuilds and other eclasses, to provide default settings and functionality across many similar ebuilds.

This is used to ensure maximum code reuse among similar ebuilds.

This first chapter shows briefly how to write an eclass incorporating the standard tricks and techniques used in existing eclasses. The second is an overview of the kde eclasses.The third explains how to write a KDE ebuild using the kde group of eclasses.

An example of a simple eclass

Here is a fictive sourceforge.eclass, designed to provide homepage and download locations to sourceforge.net-hosted projects:

Code Listing 1: Example: sourceforge.eclass

# Copyright 2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2 or later
# Author Dan Armak <danarmak@gentoo.org>
# $Header: /var/www/www.gentoo.org/raw_cvs/gentoo/xml/htdocs/proj/en/devrel/handbook/hb-guide-eclass.xml,v 1.1 2004/07/17 21:05:00 plasmaroo Exp $
ECLASS=sourceforge
INHERITED="$INHERITED $ECLASS"
# This eclass sets $HOMEPAGE and $SRC_URI to the standard vaules for
# sourceforge.net - hosted projects.

HOMEPAGE="http://${PN}.sourceforge.net/"
SRC_URI="http://download.sourceforge.net/${PN}/${P}.tar.gz"

Note: The ECLASS= and INHERITED= lines help portage handle dep caching with eclasses; they must be present in every eclass, or things will break. $ECLASS is also used by EXPORT_FUNCTIONS(). These variables might be deprecated in the future though, and be set by portage automatically in inherit().

The first four lines are headers, just like those in any ebuild. The next two lines are a short description of the eclass. The rest of the code does the actual work - setting SRC_URI and HOMEPAGE.

Most eclasses go beyond setting variables and providing helper functions; they contain default versions of the special ebuild functions (src_unpack, src_compile and so on). Before writing a default function in an eclass, you should be aware of the default functions already contained in ebuild.sh. They are what gets executed if you don't put some function in your ebuild (not even via an eclass); the default src_unpack() is often used. If you haven't yet, go and look at the default implementations in ebuild.sh.

This is all you need to know to actually write eclasses. Put your new eclass in $PORTDIR/eclass/, and put this line at the beginning of your ebuild:

Code Listing 2: How to inherit eclasses

inherit sourceforge

The contents of the eclass will be sourced at this point. Remember that any variables or functions defined in the eclass can be overriden in the ebuild, whose code executes after any eclasses. Therefore, you should try to put as much default settings and common code in your eclass as possible. Any nonstandard settings and modifications can then be put into the ebuild.

Oh, and you can inherit several eclasses at the same time by saying:

Code Listing 3: Inheriting multiple eclasses

inherit eclass1 eclass2 [...]

...but watch their order! Remember, eclasses can inherit one another and override each other's settings, so you should be careful when dealing with multiple eclasses that might influence one another.

We will now go over all the tricks of eclass writing, before moving on to the actual eclasses in portage.

inherit()

This function lives in ebuild.sh and handles inheriting (sourcing) of eclasses. It is called with a list of eclass names to inherit: inherit <eclass1> [eclass2 eclass3...].

Besides actually sourcing the eclass files, it sets the ECLASS and INHERITED variables which are used by portage for caching eclass modification timestamps. The INHERITED variable might be of use in writing eclasses: it contains a list of all eclasses inherited (sourced) up to this point, in order. Thus an eclass can use it to determine whether or not it was called from some other eclass.

EXPORT_FUNCTIONS

A good eclass's predefined functions can often be used as-is; the ebuild will then contain very little code (which is good). Sometimes, though, the eclass functions won't do exactly what you need. You could write a new function in your ebuild, overriding the function definition from the eclass. However, this would minimize the benefit of code reuse. So we try to 'extend' the eclass functions instead.

Suppose you want to extend src_compile(). You can write an src_compile() definition in your ebuild, which would only include the parts missing from the eclass src_compile(). You would then call the eclass src_compile() from within the code of your custom function.

However, if you create a new function called src_compile(), bash will forget about the old one and you won't be able to call it! That's where the EXPORT_FUNCTIONS macro comes into play.

Let's look at another problem for a moment. Suppose that foo.eclass and bar.eclass both define src_compile(). If you inherit both foo and bar you'll get a different src_compile() depending on the order in which you inherit them. That's ok; you're supposed to keep track of your inheritance order. But you may want to call either of the two src_compile()s explicitly.

So, every eclass adds to the functions that it defines a prefix. For example, foo.eclass will define a function called foo_src_compile(), and bar.eclass will define a bar_src_compile(). That way, the ebuild can call either function and know what it'll get.

However, we also want to have some default function called just src_compile(), or the ebuild will have to define one. The EXPORT_FUCTIONS macro solves both this problem and the one presented earlier.

Code Listing 4: EXPORT_FUNCTIONS() (from ebuild.sh)

EXPORT_FUNCTIONS() {
	while [ "$1" ]; do
		eval "$1() { ${ECLASS}_$1 ; }" > /dev/null
		shift
	done
}

The inherit() function sets $ECLASS to the eclass's name before sourcing it. The eclass, at its end, calls EXPORT_FUNCTIONS(), passing as parameters the list of default functions it provides. For example, if you call

Code Listing .5

EXPORT_FUNCTIONS src_compile src_install

then EXPORT_FUNCTIONS will call eval() on the following string:

Code Listing .6

src_unpack() { foo_src_compile() ; }
src_compile() { foo_src_compile() ; }

Now, whichever eclass is inherited last will define the default src_compile() function, but both functions can be directly called by the ebuild if needed.

You can also extend the default src_compile() function by calling the eclass's function from within your own function. You then have to use the default function's full name of foo_src_compile. An example:

Code Listing 7: Extending eclass-provided default functions in your ebuild

#in foo.eclass:
foo_src_compile() {
	[default code here]
}

EXPORT_FUNCTIONS src_compile
#end eclass code

#in an ebuild:
inherit foo

src_compile() {
	[custom code here]
	foo_src_compile
	[more custom code]
}

Function sections

Sometimes, extending default functions by having code execute before and after isn't flexible enough. When dealing with long, complex functions, you often want to have your custom code run in the middle of those functions.

Function sections provide for greater flexibility required here. They break the functions down into sections and allow you to execute code between any two sections.

The implementation is simple. Let's take as an example the src_compile() function from base.eclass. (Note: it no longer exists, but it's a good example :-) It looks like this:

Code Listing 8: Example from original base.eclass

base_src_compile() {
    ./configure || die
    emake || die
}

Here is the same function, divided into sections:

Code Listing 9: The same function divided into sections.

base_src_compile() {
 
    [ -z "$1" ] && base_src_compile all
 
    while [ "$1" ]; do
        case $1 in
            configure)
                ./configure || die;;
            make)
                emake || die;;
            all)
                base_src_compile configure make;;
        esac
    shift
    done
 
}

The code has been divided into two sections: configure and make. In our simple example, they correspond to the two commands in the original function.

In the center of the new function is a while;case...esac;shift;done block. This block matches the parameters to the function with the defined section names and executes the corresponding lines of code.

The special case all calls the same function recursively with a list of sections in order. It's up to the eclass's author to maintain this list.

The line before the block says that a call without parameters should be treated the same as a call with the single parameter all. As you see, this function recurses a lot. Note, however, that the call base_src_compile configure all make is also legal; it will execute base_src_compile configure configure make make.

Now, in your ebuild (or eclass) that inherits from base.eclass, you get the stub function src_compile which calls base_src_compile without parameters. This makes base_src_compile execute all, that is, all its sections. You can leave it as-is. If you wish to extend it, you can define a new src_compile and call base_src_compile a section at a time:

Code Listing 10: Using the sectioned src_compile()

src_compile() {
    run_my_code1
    base_src_compile configure
    run_my_code2
    base_src_compile make
    run_my_code3
}

As you can see, the function sections add flexibility since you can now insert code between the two sections, as well as run them in a different order or run only some of the sections provided. This makes for greater code reuse overall.

The debug-print-* functions

These are more functions provided by ebuild.sh. They add verbose debug output facilities to eclasses, to allow you to trace their execution more easily without having to read the long traces provided by the bash debug mode. All my eclasses call these functions a lot.

debug-print() simply prints all its parameters with the 'debug:' prefix. It is called whenever there's something interesting to put in the debug log.

debug-print-function() prints 'debug: entering function $1, parameters: $2 [$3 ....] It is called at the beginning of a function.

debug-print-section() prints 'debug: now in section $1'. It is called at the beginning of a function's section.

The debug output normally goes into $T/eclass-debug.log. You can set the ECLASS_DEBUG_OUTPUT env. variable (in make.globals/conf or in the environment) and output will be sent there as well. You can also set it to the special value 'on', which echoes output to stdout together with the other emerge messages.

Let's add typical debug output statements to our sample function:

Code Listing 11: Adding debug statements

base_src_compile() {
 
    debug-print function $FUNCNAME $*
    [ -z "$1" ] && base_src_compile all
 
    while [ "$1" ]; do
        case $1 in
            configure)
                debug-print-section configure
                ./configure || die;;
            make)
                debug-print-section make
                make || die;;
            all)
                debug-print-section all
                base_src_compile configure make;;
        esac
    shift
    done
 
    debug-print "$FUNCNAME: result is $RESULT"
}

FYI, $FUNCNAME is a bash builtin that returns the current function's name.

2.b. Existing eclasses

Introduction

Most eclasses are simple, and you should simply read them and maybe glance at a couple of ebuilds using them to understand how they work. Also, most eclasses are well-commented, so it's best to read them.

This chapter documents the overall relationship between the kde* eclasses.

base.eclass

This eclass defines some default variables and functions, similar to those you'd get by default in a non-inheriting ebuild (which are defined in ebuild.sh). You probably aren't interested in using it directly, but rather through one of the kde eclasses, which inherit it.

One interesting bit of functionality it provides is the autopatch capability. If you set the PATCHES variable to conain a list of files in your ebuild that uses base_src_unpack() (or kde_src_unpack()), the sources will be patched from those files. The patches need to work with -p0 when run from $S.

Note that you can set PATCHES without defining a custom src_unpack() in your ebuild! That is what it's for.

The newer epatch() function from eutils.eclass is much more powerful - it supports compressed patches, patch directories and series, and automatic detection of the patch level - and I intend to make autopatch use it sonmeday.

Note that the patch section in base_src_unpack() is deprecated and will be removed soon. If you see an ebuild using it, it needs to be converted to the autopatch style.

cvs.eclass

This eclass provides the functionality needed to create 'live' cvs ebuilds. Such ebuilds fetch sources from a specified cvs server at unpack time, thus always getting the latest bugs and fixes from upstream.

However, the necessary (versioning etc.) support for live cvs ebuilds has not yet been added to portage. They can work with this eclass, but it is inconvinient in many respects. Think twice before creating a live cvs ebuild; perhaps a regular cvs snapshot would be better. If you intend to add such an ebuild to portage, be aware of the cvs ebuild guidelines in the developer's guide.

Before inheriting cvs.eclass, set any non-default settings you want (at least the server address and module name). See the list of configurable settings and default values at the beginning of cvs.eclass, marked as 'ebuild-configurable settings'.

After that, things are mostly automatic. A cvs_src_unpack() (no sections) is provided. If you wish to know more, read the eclass itself.

kde-functions.eclass

This eclass contains all KDE-related helper functions. Some of them you should never need to use directly in an ebuild; these are not mentioned here, and should be well-commented in the source.

Note that by 'helper functions' I mean any functions that aren't special ebuild functions (src_unpack() etc.). All kde eclasses containing such 'special' functions inherit kde-functions.

The only code outside any functions in kde-functions.eclass (which thus runs on sourcing) is a block that determines whether or not the current ebuild is one from kde-base. If it is, KDEBASE=true is set. This variable is used in various logic tests elsewhere and it is comfortable to have one centralized test for it.

The current multi-kdedir scheme

A short explanation about the way Gentoo manages multiple KDE versions:

A KDE (that is, things from kde-base) live in /usr/kde/${major-version}.${minor-version}. So, fex., KDE 3.1.x lives in /usr/kde/3.1. However, this scheme was established after the KDE 3.0 release, and so older versions live in nonstandard locations: KDE 3.0.x lives in /usr/kde/3 (and not /usr/kde/3.0), and KDE 2.2.2 (the only 2.x version we have) lives in /usr/kde/2. The cvs ebuilds I maintain install into /usr/kde/cvs.

Any number of KDEs with different minor versions can thus coexist. kde-base packages have a SLOT of major.minor (e.g. 3.0, 3.1).

Since QT versions are supposed to be fully backward compatible across minor versions, we have only one of each major version installed and with a different slot; they live in /usr/qt/$major.

A non-kde-base ebuild always installs in /usr. The kde-env package puts KDEDIRS=/usr in env.d, allowing these apps to run properly. The app compiles and links against the latest KDE libraries found; the eclass checks the standard locations in descending order - /usr/kde/cvs, then /usr/kde/3.1, then /usr/kde/3. (kde-base ebuilds will always link against the kdelibs of their own version.) This of course also depends on the parameter given to need-kde() (see below).

There are several special variables you can set to change the default settings of this system. Their prime usage is to compile an ebuild against a specific KDE you have installed for testing, but you can also use them to install a KDE in a nonstandard location, and so have, fex., both KDE 3.0.1 and 3.0.2 installed side-by-side. This, again, is most useful for testing and development.

All KDE apps (base and non-base) will install into $KDEPREFIX, if set. It overrides all other logic in the eclasses.

A KDE app (even if it is a kde-base one) will try to link against the kdelibs installed in $KDELIBSDIR, if set. If it fails, it will fall back to the default logic of locating the latest kdelibs (or the proper version for kde-base version).

need-kde(), need-qt(), set-kdedir(), set-qtdir()

kde-functions.eclass provides two pairs of functions: need-kde(), need-qt() and set-kdedir(), set-qtdir(). These functions handle the details of multiple KDEs and QTs setup.

The need-kde() function is called with a parameter which is the minimal version number of kdelibs required. It adds the proper dependencies to DEPEND, RDEPEND and call the set-kdedir() function. If no parameter is passed, a version number of 0 (zero) is used, meaning that any version will satisfy the dependency. need-kde() also calls need-autoconf() and need-automake() with the correct parameters for this KDE version.

The set-kdedir() function then determines the installation prefix and kdelibsdir location your ebuild should use. These are passed to you in $PREFIX and $KDEDIR, respectively (and are handled automatically in kde.eclass). Note that no ebuild should ever address $KDEPREFIX or $KDELIBSDIR directly!

need-kde() also looks up the minimal version of QT required for this version of kdelibs from a table. It then calls need-qt() with this version. A qt-only (i.e. non-kde) app's ebuild usually calls need-qt directly, bypassing need-kde.

The need-qt() function adds the equired QT verision to DEPEND, RDEPEND and calls set-qtdir() with it. The set-qtdir() function sets QTDIR to be the default location of this version of QT. Unlike set-kdedir(), set-qtdir() doesn't actually check if there's a QT installed there.

need-kde() (or need-qt()) needs to be called from the main part of the ebuild (i.e. not from a function), so that any changes to DEPEND and RDEPEND affect emerge.

need-autoconf(), need-automake()

These functions set the necessary environment variables to make the requested version of autoconf or automake run. They also unset all previously set variables of this kind. For example, calling 'need-automake 1.4' will set NEED_AUTOMAKE_1_4=1 and unset all other WANT_AUTOMAKE* variables. For more info see the functions' code and the comments at the beginning of /usr/bin/auto{conf,make} (on a Gentoo system).

kde_sandbox_patch()

Some KDE makefiles are broken. They chmod or chown files in PREFIX when installing, but do not respect DESTDIR ($D). I.e. when installing, they correctly copy a file to $DESTDIR/$PREFIX/path/foo, but then try to chmod +x the file $PREFIX/path/foo on the live filesystem which may not even exist. And if it does exist, the sandbox prevents this operation.

This function runs a generic sed on makefiles which fixes all known cases of the problem. It is called with the directories to be processed as parameters, and processes Makefile, Makefile.in and Makefile.am in those directories. For example:

Code Listing 12: Processing

src_unpack() {
    base_src_unpack
    kde_sandbox_patch ${S}/dir1 ${S}/dir2/dir3
}

kde_remove_flag()

This is used to weed out compiler flags that are known to break packages. You call it after unpacking with the subdirectory of $S in which to work as the first parameter, and the name of the flag to remove as the second. Note that it is not recursive. Example: "kde_remove_flag foodir/barfoo -fomit-frame-pointer".

kde_remove_dir() and $KDE_REMOVE_DIR

This function removes the specified subdir from complation. It deletes it and removes all mention of it from the subdirs file, configure and the makefiles. Note that it only works on subdirs of $S for now, not on 2nd level subdirs. You can call it with a list of subdirs to remove; it works on each parameter in turn.

You can call it directly, but to avoid having to define a custom src_unpack() just to do that, you can set KDE_REMOVE_DIR to a list of subdirs to remove. kde_src_unpack() will call 'kde_remove_dir $KDE_REMOVE_DIR' after unpacking. As you can see, I go to some lengths to avoid having to define an extra function in an ebuild, because this makes the ebuilds much cleaner and more readable.

kde.eclass

This is the main, central KDE eclass. It contains most of the KDE-related code. All KDE ebuilds inherit it, one way or another. The kde eclass inherits base and kde-functions.

As with the other eclasses, read it to find out what it does. Most of it should be self-obvious. Here is a short summary:

The eclass's global section (i.e. the one that's executed when you inherit it) adds the correct deps on kde-env, automake, autoconf, make and perl (the last is used by standard configure scripts for fast makefile generation). It also sets the default SLOT="0".

kde_src_unpack() basically just calls base_src_unpack(), passing on any parameters (e.g. sections to execute). After that, it adds kde-specific items. It touches all .ui files in the unpacked sources to regenerate any stale .cpp,.h files. It also calls kde_remove_dir() with $KDE_REMOVE_DIR if this variable is set (see above in the section on kde-functions).

kde_src_compile() also has several fixes. One is exporting kde_widgetdir="$KDEDIR/lib/kde3/plugins/designer" to get around a bug in older kde acinclude.m4.in's. Another is setting HOME="$T/fakehome", so that any accesses to $HOME/.kde and $HOME/.qt aren't stopped by the sandbox, and don't affect the user's home directory. It is a bug (or shortcoming) of uic that it always tries to access config files in these locations.

kde_src_compile() has several sections. myconf adds to $myconf the default kde configure script parameters, such as --prefix=${PREFIX} (remember, $PREFIX is set by set-kdedir()). You can add your own values to $myconf either before or after this section; just remember never to overwrite old values, because users can expect to set $myconf in the shell and in this way add something to the configure parameters used by the ebuild.

The configure section runs the configure script in $S, passing $myconf to it. If the configure script does not exist, it tries to generate it by running make -f Makefile.cvs or make -f admin/Makefile.common. Thus, this stage of compilation (which is needed for cvs snapshots, or ebuilds that patch files like configure.in) is also done automatically.

The make section simply runs emake || die. Finally, there is an all section which runs all of the above.

Finally, kde_src_install() has a make section which runs make install, and a dodoc section which runs dodoc on some standard doc names in $S, such as README and COPYING.

kde-base.eclass

This eclass is now deprecated, ebuilds should "inherit kde" instead.

kde-dist.eclass

This eclass is for the core kde distribution packages in kde-base/*. It inherits kde.

It sets the correct DESCRIPTION and HOMEPAGE and calls need-kde $PV. The simpler, smaller kde-base/ packages (e.g. kdetoys) don't need to make any changes to it; most of those that do only add deps and patches.

kde-i18n.eclass

This eclass is for the kde-i18n-* packages. In fact, all kde-i18n ebuilds are completely identical and so all they have to do is inherit from this eclass. Their $P, $P, $PV variables do the rest.

kde.org.eclass

This eclass is also deprecated, and all the code has been moved to kde-dist.eclass.

koffice-i18n.eclass

This eclass is meant for the koffice-i18n-* packages and is very similar to kde-i18n.eclass. Again, all kde-i18n ebuilds are completely identical and so all they have to do is inherit from this eclass.

kde-source.eclass

This eclass works on top of cvs.eclass, adding some kde-specific functionality. For example, it automatically fetches the admin/ dir from the kde-common module of kde cvs. Read the eclass to find out more, including kde-cvs-specific settings you can pass to it.

2.c. Writing KDE ebuilds

Introduction

This chapter explains how to write standard KDE ebuilds. All that is said here is mostly a rehashing of the information about eclasses above. When in doubt, look at other ebuilds, at the eclasses, or ask.

A typical KDE ebuild

The code below should be obvious after reading this howto:

Code Listing 13: A simple KDE ebuild, #1

<Header goes here...>
inherit kde

Some ebuilds end right here. Others need some customization.

The next stage is to add any extra deps. Remember: *always* extend variables, never override!

Because our goal is to avoid defining custom ebuild functions unless we have to, we set all the settings we can, and call all the helper functions we can, directly from the ebuild's main section. Remember though that there are limitations on code in the main section; for example, it must not produce any output (debug-print() output probably doesn't count though).

Code Listing 14: A simple KDE ebuild, #2: adding extra dependencies

DEPEND="foo/bar"
RDEPEND="bar/foo"

We also want to add some extra arguments to myconf, which are then passed to configure (assuming that we use kde_src_compile's configure section):

Code Listing 15: A simple KDE ebuild, #4: passing arguments to configure

myconf="$myconf --with-foobar"

We also have a patch to add. If it can be applied using -p0 in $S, we can use base_src_unpack's autopatch section. Remember, kde_src_unpack() calls base_src_unpack() passing on any parameters you gave it.

Code Listing 16: A simple KDE ebuild, #5: autopatching

PATCHES="$FILESDIR/$P-myfix.diff"

Finally, we want an extend src_install() to put in place some documentation:

Code Listing 17: A simple KDE ebuild, #6: extending src_install()

src_unpack() {
    kde_src_install
    dodoc $S/doc/*
}

Let's look at the ebuild we have created in this example:

Code Listing 18: A simple KDE ebuild - complete listing

<Header goes here...>
inherit kde

# add deps
DEPEND="foo/bar"
RDEPEND="bar/foo"

# always enable foobar
myconf="$myconf --with-foobar"

# fix terrible bug
PATCHES="$FILESDIR/$P-myfix.diff"

src_unpack() {
    kde_src_install
	# install some extra docs not included in make install's targets
    dodoc $S/doc/*
}

A typical ebuild with optional KDE functionality

When adding kde (eclass) functionality to an existing ebuild, you should simply prefix each kde-specific line with use kde && , or create whole if [ -n "`use kde`" ]; then; fi blocks.

To the general section, add the following (only if USE kde is set, of course):

Code Listing 19: Optional KDE support - main ebuild section

inherit kde-functions

# This will add kdelibs, kde-env to your dep strings and set $KDEDIR
# to the correct value:

need-kde $version # minimal version of kde your app needs

# Add anything else you need for kde support:
use kde && myconf="$myconf --with-my-parameter"

Then, tell your app to look for KDE in the $KDEDIR setting that is available after calling need-kde(). If you do not want the kdelibs dep to be added, call set-kdedir() instead of need-kde().


[ << ] [ < ] [ Home ] [ > ] [ >> ]



The contents of this document are licensed under the Creative Commons - Attribution / Share Alike license.
Print
line
Updated­ September 09, 2004
line
Donny Davies
Ebuild HOWTO - Author

Peter Gavin
Author

Karl Trygve Kalleberg
Author

Mike Frysinger
Author

Daniel Robbins
Author/Editor

John P. Davis
Author/Editor

Jorge Paulo
Editor

Sven Vermeulen
Editor

Zack Gilburd
Editor

Benny Chuang
Editor

Erwin
Editor

Dan Armak
Eclass HOWTO - Author

Alastair Tse
Common Ebuild Mistakes - Author

Paul De Vrieze
Metadata Document - Author

Owen Stampflee
Ebuild Policy - Original Author

Seemant Kulleen
Editor

Jon Portnoy
Editor

Carl Anderson
Editor

Ciaran McCreesh
Contributor

Nicholas D. Wolfwood
Contributor

Marius Mauch
Contributor

Tim Yamin
Author/Editor

Gentoo Developer Relations Team
Editors

line
Summary:  This section aims to provide developers with a guide detailing how eclasses work and how they can be applied to ebuilds.
line
$99/mo dedicated servers

No BS Dedicated Gentoo Linux Servers from vr.org.

line
Tek Alchemy

Tek Alchemy offers dedicated servers and other hosting solutions running Gentoo Linux.

line
php|architect

php|architect is the monthly magazine for PHP professionals, available worldwide in print and electronic format. A percentage of all the sales will be donated back into the Gentoo project.

line
SevenL.net

Seven L Networks provides customizable Dedicated Servers for your customized Gentoo install. Colocation and other hosting services are also provided.

line
The Gentoo Linux Store
line
Copyright 2001-2004 Gentoo Foundation, Inc. Questions, Comments, Corrections? Email www@gentoo.org.