Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Mar 1996 20:11:08 +0100 (MET)
From:      Andreas Klemm <andreas@knobel.gun.de>
To:        doc@freebsd.org
Cc:        ports@freebsd.org
Subject:   HOWTO make a FreeBSD port
Message-ID:  <199603171911.UAA09099@knobel.gun.de>

next in thread | raw e-mail | index | archive | help
Hi !

I've tried to make a little guide how to create a port. Ok, it still
doesn't cover every detail, but is perhaps a good guidance for the
"very beginner".

Please could someone, who is experienced in writing smgl documents,
convert this into sgml (if you like this document) ?

I think it should be included into the FreeBSD Handbook in the
ports section as an "life" example.

Additionally you native English speakers should correct a bit
my chicken English if needed ;-))

BTW: Satoshi, a new port is coming, guess what ;-))

Regards

	Andreas ///

=======================================================================

From: Andreas Klemm <andreas@knobel.gun.de>

How to create a FreeBSD port

Let's say we want to create a port of the program mapedit, that 
is heavily used by WEB authors to create clickable image maps.

In the first step we create a new directory in the ports 
directory structure, where all port files will reside:

	# mkdir -p /usr/ports/www/mapedit

In the first step we'll create a small and simple Makefile
with a minimum configuration. The first aim is to automatically
get the source archive from the ftp server. After that we'll
find out step for step, which additional thinks we have do
define there.

The starting Makefile contains only four lines:

--------------------------------------------------------------------------------
DISTNAME=	mapedit1.5
CATEGORIES=	www
MASTER_SITES=	ftp://ftp.boutell.com/pub/boutell/mapedit/
.include <bsd.port.mk>
--------------------------------------------------------------------------------

When choosing a DISTNAME it's a good starting point, to take the 
name of the source archive, since many other variables and assumptions
in the bsd.port.mk file are based on that name. 

The name of the tar archive we want to get is mapedit1.5.tar.Z.
Therefore we choose the distname mapedit1.5.

Let's type 'make extract' at the command prompt to get and extract the
sources and see what's happening:

	# make extract
	>> mapedit1.5.tar.gz doesn't seem to exist on this system.
	>> Attempting to fetch from ftp://ftp.boutell.com/pub/boutell/mapedit/.

Not bad. Make detected, that mapedit1.5.tar.Z isn't stored in
/usr/ports/distfiles and automtically tries to get the file via
ftp from the master site. The only thing we have to manage now is,
that we have to change the suffix ".tar.gz" since our source isn't
compressed with GNU zip. When browsing through /usr/share/mk/bsd.port.mk
we see the following definition:

DISTFILES - Name(s) of archive file(s) containing distribution
	(default: ${DISTNAME}${EXTRACT_SUFX}).

This means, that we have to change the variable EXTRACT_SUFX, to
get the ftp part managed, Makefile now looks like this:

-------------------------------------------------------------------------------
DISTNAME=	mapedit1.5 
CATEGORIES=	www
EXTRACT_SUFX=	.tar.Z
MASTER_SITES=	ftp://ftp.boutell.com/pub/boutell/mapedit/ 
.include <bsd.port.mk>
-------------------------------------------------------------------------------

Let's see what's happening now:

	# make extract

-------------------------------------------------------------------------------
1  >> mapedit1.5.tar.Z doesn't seem to exist on this system.
2  >> Attempting to fetch from ftp://ftp.boutell.com/pub/boutell/mapedit/.
3  Receiving file: mapedit1.5.tar.Z 
4  100%  0                                               71407 bytes. ETA:  0:00
5  mapedit1.5.tar.Z: 71407 bytes received in 49.25 seconds, 1.42 K/s.
6  >> No MD5 checksum file.
7  ===>  Extracting for mapedit1.5
-------------------------------------------------------------------------------

This looks better. Line 1 shows, that ncftp now tries to get the correct
file from the ftp server. The transmission went on without any error
(lines 3-5). Line 6 is normal. We'll create a md5 file later. This file
will then reside in the files subdir. Line 7 informs us, that the 
tar archive was automatically extracted in the subdir 'work'.

After the transmission (lines 1-5) we have now the source archive
locally stored on disk:

	/usr/ports/distfiles/mapedit1.5.tar.Z

After the extraction of the sources (line 7) we have a workdir

	/usr/ports/www/mapedit/work/mapedit1.5

The toplevel directory of the workdir shows us, that this is 
an X11 program. By defining USE_IMAKE and USE_X11 in the Makefile,
we achieve, that imake will be started up automatically before
the compilation of the sources (in the workdir) starts.

Makefile looks now like that:

--------------------------------------------------------------------------------
DISTNAME=       mapedit1.5
CATEGORIES+=    www
EXTRACT_SUFX=   .tar.Z
USE_IMAKE=      True
USE_X11=        True
MASTER_SITES=   ftp://ftp.boutell.com/pub/boutell/mapedit/
.include <bsd.port.mk>
--------------------------------------------------------------------------------

If we type 'make' again in the port toplevel directory
(/usr/ports/www/mapedit), we'll notice that make is clever
and remembers, that the source is already here, and that
it was extrected in a previous step. This is done by 0 Byte
file in the workdir, that act as a marker.
In this case the file /usr/ports/www/mapedit1.5/work/.extract_done
prevents a new extraction.

	# make

--------------------------------------------------------------------------------
1  >> No MD5 checksum file.
2  ===>  Patching for mapedit1.5
3  ===>  Configuring for mapedit1.5
4  mv -f Makefile Makefile.bak
5  imake -DUseInstalled -I/usr/X11R6/lib/X11/config
6  make Makefiles
7  make includes
8  make depend
9  gccmakedep  --   -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 
         -DNARROWPROTO  -DANSI  -- gd.c mapedit.c
10  In file included from gd.c:1:
11 /usr/include/malloc.h:2: warning: #warning "this file includes <malloc.h> 
         which is obsoleted, use <stdlib.h> instead"
--------------------------------------------------------------------------------

As we can see in line 5, imake was now properly called, before
starting the compilation, that would have started after the 'make
depend'.

The error message informs us now, that we should make some 
modification to the sources, since FreeBSD prefers the header
file <stdlib.h>. This will be a good example, how we add
patches to this port. So that even the patching of the sources
is done automatically by make.

All we have to do is to change the sources in the workdir, make
context diffs and place them into a subdir called patches.

	# grep malloc work/mapedit1.5/*
	work/mapedit1.5/gd.c:#include <malloc.h>
	work/mapedit1.5/mapedit.c:#include <malloc.h>

Save the files you want to modify later

	# cp work/mapedit1.5/gd.c work/mapedit1.5/gd.c.orig
	# cp work/mapedit1.5/mapedit.c work/mapedit1.5/mapedit.c.orig

Modify the files 

	# vi `grep -l malloc work/mapedit1.5/*`

For example:

	#ifdef __FreeBSD__
	#include <stdlib.h>
	#else
	#include <malloc.h>
	#endif

Create the directory for the patches, and collect the context
diffs:

	# mkdir /usr/ports/www/mapedit/patches

You have to stay in the workdir directory !

	# cd /usr/ports/www/mapedit/work/mapedit1.5
	# diff -c gd.c.orig gd.c.orig > ../../patches/patch-aa
	# diff -c mapedit.c.orig mapedit.c.orig > ../../patches/patch-ab

Now we want to test, if everything runs fine, including this new
patch feature:

	# cd ../.. 		# topdir of the port /usr/port/www/mapedit
	# make clean

--------------------------------------------------------------------------------
===>  Cleaning for mapedit1.5
--------------------------------------------------------------------------------

Please note, doing a make clean removes the whole work directory !

At this point we'll create a checksum file (md5 file), so this
step is done, too.

	# make makesum

This creates a md5 file in /usr/ports/www/mapedit/files/md5 with
the following content:

	MD5 (mapedit1.5.tar.Z) = 7ad4bd45951dc2e07bad032379e96ed2

This makes sure, that people using your port, have grabbed the
correct source archive and that it's not corrupt.

Again we start the port by typing simply 'make'

	# make

--------------------------------------------------------------------------------
1   Checksums OK.
2   ===>  Extracting for mapedit1.5
3   ===>  Patching for mapedit1.5
4   ===>  Applying FreeBSD patches for mapedit1.5
5   ===>  Configuring for mapedit1.5
6   mv -f Makefile Makefile.bak
7   imake -DUseInstalled -I/usr/X11R6/lib/X11/config
8   make Makefiles
9   make includes
10  make depend
11  gccmakedep  --   -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 
        -DNARROWPROTO  -DANSI  -- gd.c mapedit.c
12  ===>  Building for mapedit1.5
13  gcc -m486 -O2     -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 
         -DNARROWPROTO  -DANSI -c gd.c
14  gcc -m486 -O2     -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 
         -DNARROWPROTO  -DANSI -c mapedit.c
15  rm -f mapedit
16  gcc -o mapedit -m486 -O2      -L/usr/X11R6/lib gd.o mapedit.o    -lXaw -lXmu -L/usr/X11R6/lib -lXt -lX11 -lXt -lSM -lICE -lXExExt -lXext -lX11 -lm   
--------------------------------------------------------------------------------

What's new ? After creating the md5 file, we'll get informed now, 
that we got the correct sources and that they aren't coruppted (line 1)
In the following we see a successfully running port. We are now ready to
install the package by simply typing

	# make install

--------------------------------------------------------------------------------
Checksums OK.
===>  Installing for mapedit1.5
/usr/bin/install -c -s  mapedit /usr/X11R6/bin/mapedit
install in . done
make: don't know how to make mapedit.man. Stop
*** Error code 2
...
--------------------------------------------------------------------------------

Oh, what happened now ... Well, the package comes without manual page.
We have to tell 'make' this circumstance in the Makefile, too, by defining
NO_INSTALL_MANPAGES. Makefile now looks like this:

--------------------------------------------------------------------------------
DISTNAME=       mapedit1.5
CATEGORIES+=    www
EXTRACT_SUFX=   .tar.Z  
USE_IMAKE=              True
USE_X11=                True
NO_INSTALL_MANPAGES=    True 
MASTER_SITES=   ftp://ftp.boutell.com/pub/boutell/mapedit/   
.include <bsd.port.mk>
--------------------------------------------------------------------------------

After that modification we repeat the 'make install' step.
Now the output is:

--------------------------------------------------------------------------------
Checksums OK.
===>  Installing for mapedit1.5
/usr/bin/install -c -s  mapedit /usr/X11R6/bin/mapedit
install in . done
** Missing package files for mapedit1.5 - installation not recorded.
*** Error code 1
...
--------------------------------------------------------------------------------

Ok, well done. We only have to create some missing files
for package management, so that the package can be recorded
properly as installed. 

This is needed to be able to use the package management utilities
like pkg_delete and friends.

For this purpose we create the following files in a separate
pkg directory:

COMMENT		a one line description of the package
--------------------------------------------------------------------------------
mapedit - a WWW authoring tool to create clickable maps
--------------------------------------------------------------------------------

DESCR		a short description of the package (a "screen full")
--------------------------------------------------------------------------------
mapedit was made for the purpose "blah", etc, etc etc, from foo@bar.com
--------------------------------------------------------------------------------

PLIST		a list of installed files that belong to the package

The PLIST file is hevily used by the package management utilities
like pkg_delete.

A suitable PLIST file for mapedit would be:

--------------------------------------------------------------------------------
/usr/X11R6/bin/mapedit
--------------------------------------------------------------------------------

A new test. We hope, it's the final one ;-)

	# make clean all install

--------------------------------------------------------------------------------
===>  Cleaning for mapedit1.5
Checksums OK.
===>  Extracting for mapedit1.5
===>  Patching for mapedit1.5
===>  Applying FreeBSD patches for mapedit1.5
===>  Configuring for mapedit1.5
mv -f Makefile Makefile.bak
imake -DUseInstalled -I/usr/X11R6/lib/X11/config
make Makefiles
make includes
make depend
gccmakedep  --   -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 -DNARROWPROTO 
 -DANSI  -- gd.c mapedit.c
===>  Building for mapedit1.5
gcc -m486 -O2     -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 -DNARROWPROTO
  -DANSI -c gd.c
gcc -m486 -O2     -I/usr/X11R6/include  -DCSRG_BASED  -DFUNCPROTO=15 -DNARROWPROTO
  -DANSI -c mapedit.c
rm -f mapedit
gcc -o mapedit -m486 -O2      -L/usr/X11R6/lib gd.o mapedit.o    -lXaw -lXmu -L/us
r/X11R6/lib -lXt -lX11 -lXt -lSM -lICE -lXExExt -lXext -lX11 -lm   
===>  Installing for mapedit1.5
/usr/bin/install -c -s  mapedit /usr/X11R6/bin/mapedit
install in . done
--------------------------------------------------------------------------------

Ok, well done ! Now we should finally add a note into Makefile,
who's the maintainer of this packages. So the very last Makefile
looks like this:

--------------------------------------------------------------------------------
# New ports collection makefile for:    mapedit
# Version required:     1.5
# Date created:         Sun Mar 17 20:00:31 MET 1996
# Whom:                 Andreas Klemm <andreas@knobel.gun.de>
#

DISTNAME=       mapedit1.5
CATEGORIES+=    www
EXTRACT_SUFX=   .tar.Z

MAINTAINER=     andreas@knobel.gun.de

USE_IMAKE=              True
USE_X11=                True
NO_INSTALL_MANPAGES=    True

MASTER_SITES=   ftp://ftp.boutell.com/pub/boutell/mapedit/

.include <bsd.port.mk>
--------------------------------------------------------------------------------

That's it folks. After doing the port you can send it as
compressed tar archive uuencoded to the maintainer of the
ports collection.

	# cd /usr/ports/www/mapedit
	# make clean
	# cd ..
	# tar cvzf mapedit.tar.gz mapedit
	# uuencode mapedit.tar.gz < mapedit.tar.gz > mapedit.tar.gz.uue
	# mail -s "new port www/mapedit" PortsMaintainer < mapedit.tar.gz.uue

This is only an example, normally one has to say some more things about
the port ;-) And don't forget to send it as user, not as root ;-))
-- 
andreas@knobel.gun.de         /\/\___      Wiechers & Partner Datentechnik GmbH
   Andreas Klemm          ___/\/\/         $$  Support Unix - aklemm@wup.de  $$
pgp p-key  http://www-swiss.ai.mit.edu/~bal/pks-toplev.html  >>> powered by <<<
ftp://sunsite.unc.edu/pub/Linux/system/Printing/aps-491.tgz  >>>    FreeBSD <<<
"Ich bleibe bei der Aussage und trotze den Flames. :-)"    Ulli Horlacher 02/96



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199603171911.UAA09099>